Skip to content

WebAPI Security & Authorization Model Proposal (Spring Security, JDK 21) #2476

@chrisknoll

Description

@chrisknoll

WebAPI Authorization Model Proposal (Spring Security, JDK 21)

Background

As part of the WebAPI 3.0 modernization effort (JDK 21, Spring Boot 3.5), we are redesigning the authorization layer while migrating away from Apache Shiro toward pure Spring Security.

The current Shiro-based model is largely HTTP path–driven, which has resulted in:

  • One permission per endpoint
  • Tight coupling between REST structure and authorization
  • Difficulty expressing business-level functions
  • High maintenance overhead as endpoints evolve

This issue proposes a function-centric, capability-based authorization model that better fits WebAPI’s collaboration and security needs.

Goals

  • Authorize functions, not endpoints
  • Avoid permission explosion
  • Support entity ownership and fine-grained sharing
  • Scale cleanly in both data size and performance
  • Maintain strong referential integrity
  • Integrate naturally with Spring Security
  • Support both global roles and per-entity access

Core Concepts

Capabilities vs Entity Access

Authorization is separated into two additive mechanisms:

  1. Global capability permissions
  2. Entity-specific permissions

Either mechanism can independently grant access.

Wildcard entity permissions such as read:cohort:12 are explicitly avoided.

Global Capability Permissions

Capabilities are stored as Spring Security authorities.

Permission format:

<action>:<scope>

Examples:

  • create:cohort
  • read:cohort
  • write:conceptset
  • report:generate
  • report:view
  • admin:*

Capabilities grant broad authority and do not reference entity IDs.

Entity-Specific Permissions

Entity-level access is stored in entity-specific permission tables, one per entity type.

These permissions allow fine-grained sharing without granting global authority.

Authorization Model (Additive)

Access to an entity is granted if any of the following is true:

  • User has the relevant global capability
  • User owns the entity
  • User has an entity-level permission grant

Capabilities do not gate entity permissions.

Read Authorization Logic

canReadEntity(user, entity) =
  has read:<entity>
  OR is owner
  OR has READ permission

Write Authorization Logic

canWriteEntity(user, entity) =
  has write:<entity>
  OR is owner
  OR has WRITE permission

Actions

  • create – create a new entity
  • read – read an entity definition
  • write – modify or delete an entity
  • report:generate – execute analyses that generate results
  • report:view – view or fetch generated results
  • admin – administrative/system actions

Removed Permission Patterns

The following patterns do not exist:

  • read:cohort:12
  • write:conceptset:*
  • read:*:123

This prevents permission explosion and orphaned permissions.

Entity Access Control Model

Each entity type defines its own permission table.

Example: Cohort Definition Permissions

cohort_definition_permission
- id
- cohort_id (FK -> cohort_definition.id)
- user_id (FK -> sec_user.id)
- permission_type (READ, WRITE)

Example: Concept Set Permissions

concept_set_permission
- id
- concept_set_id (FK -> concept_set.id)
- user_id (FK -> sec_user.id)
- permission_type (READ, WRITE)

Ownership rules:

  • Creators receive WRITE
  • Owners implicitly have READ
  • Ownership is not stored as a permission row

Listing Entities

There is no separate list permission.

List endpoints return only entities the user can read, based on:

  • Global read capability
  • Ownership
  • Entity-level permission

Admin Permissions

admin:* includes:

  • Source management
  • Cache clearing
  • System configuration
  • Background task control
  • Operational maintenance

Admins may bypass entity-level permission checks where appropriate.

Performance Considerations

  • Capability checks are in-memory
  • Ownership checks are simple FK comparisons
  • Entity permission checks are indexed lookups
  • No wildcard parsing
  • No polymorphic joins

Why Spring Security

Spring Security provides:

  • Active maintenance
  • First-class Spring Boot support
  • Method-level authorization
  • OAuth/JWT integration
  • Strong ecosystem alignment

Shiro is endpoint-centric, encourages wildcard permissions, and is poorly aligned with Spring Boot 3.x.

Summary

  • Migrate to Spring Security
  • Use function-centric capabilities
  • Use additive authorization
  • Separate global and entity permissions
  • Avoid wildcard entity permissions
  • Use entity-specific permission tables
  • Separate reporting permissions as report:*

Next Steps

  • Implement authorization services
  • Add Spring Security AuthorizationManagers
  • Replace Shiro configuration
  • Design migration strategy

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions