Comprehensive guides and references for the OpenFrame platform
The Authorization Server Core And Tenant Context module is the foundation of OpenFrame’s multi-tenant OAuth2 and OpenID Connect (OIDC) authorization infrastructure. It is responsible for:
This module is used by the OpenFrame Authorization Server application entrypoint and works closely with persistence, SSO, and user domain services.
At a high level, this module sits between:
flowchart TD
Browser["Browser / OAuth2 Client"] --> AuthzEndpoints["Authorization Server Endpoints"]
AuthzEndpoints --> TenantFilter["TenantContextFilter"]
TenantFilter --> TenantContext["TenantContext (ThreadLocal)"]
AuthzEndpoints --> SecurityChain["Spring Security Filter Chain"]
SecurityChain --> UserDetails["UserDetailsService"]
SecurityChain --> OAuth2Login["OAuth2 Login (OIDC)"]
SecurityChain --> TokenCustomizer["OAuth2TokenCustomizer"]
TokenCustomizer --> UserService["UserService"]
AuthzEndpoints --> JwkSource["Tenant-aware JWKSource"]
JwkSource --> TenantKeyService["TenantKeyService"]
OAuth2Login --> DynamicClientRepo["DynamicClientRegistrationRepository"]
The key differentiator of this module is that every critical operation (authentication, token issuance, key resolution) is tenant-aware.
Class: AuthorizationServerConfig
This class configures the Spring Authorization Server and core security infrastructure for OAuth2 and OIDC.
multipleIssuersAllowed(true)) to support multi-tenant deploymentsflowchart TD
Start["Incoming OAuth2 Request"] --> Match["Match Authorization Endpoints"]
Match --> Authenticated["Require Authentication"]
Authenticated --> JwtSupport["Enable JWT Resource Server"]
JwtSupport --> End["OAuth2 / OIDC Response"]
OAuth2AuthorizationServerConfigurerProviderAwareAuthenticationEntryPoint for HTML flowsThe jwkSource bean dynamically resolves signing keys per tenant.
flowchart LR
Request["JWKS Request"] --> TenantContextNode["Resolve Tenant ID"]
TenantContextNode --> KeyService["TenantKeyService.getOrCreateActiveKey()"]
KeyService --> JwkSet["Return RSAKey in JWKSet"]
Key characteristics:
TenantContextTenantKeyService to fetch or generate RSA keysThe OAuth2TokenCustomizer<JwtEncodingContext> enriches access tokens with domain-specific claims.
tenant_iduserIdrolesIf a user has role OWNER, the system implicitly adds ADMIN.
flowchart TD
Principal["Authenticated Principal"] --> ResolveTenant["Get Tenant ID"]
ResolveTenant --> LoadUser["UserService.findActiveByEmailAndTenant()"]
LoadUser --> AddClaims["Add tenant_id, userId, roles"]
AddClaims --> IssueToken["Signed JWT"]
This ensures:
AuthorizationServerConfig also defines:
UserDetailsService (tenant-aware user lookup)PasswordEncoder (BCrypt)AuthenticationManager using DaoAuthenticationProviderUser resolution always uses:
Class: SecurityConfig
This configuration handles all non-authorization-server security concerns.
It defines the default Spring Security filter chain.
flowchart TD
Request["Incoming Request"] --> PublicCheck["Is Public Endpoint?"]
PublicCheck -->|Yes| Permit["Permit Access"]
PublicCheck -->|No| RequireAuth["Require Authentication"]
RequireAuth --> FormOrOauth["Form Login or OAuth2 Login"]
Permitted endpoints include:
/oauth/**/login/password-reset/**/.well-known/**/tenant/**All other routes require authentication.
The module configures:
AuthSuccessHandlerSsoAuthorizationRequestResolverA specialized JwtDecoderFactory supports Microsoft multi-tenant issuers using a regex-based issuer validator.
During OIDC login:
flowchart TD
OidcUser["OIDC User"] --> ResolveTenant2["Resolve Tenant ID"]
ResolveTenant2 --> GetSsoConfig["SSOConfigService.getSSOConfig()"]
GetSsoConfig -->|Auto Provision Enabled| DomainCheck["Allowed Domain?"]
DomainCheck -->|Yes| CreateUser["UserService.registerOrReactivateFromSso()"]
CreateUser --> PostProcess["RegistrationProcessor.postProcessAutoProvision()"]
If:
Then a new user is automatically registered.
This ensures smooth enterprise onboarding flows.
Class: DynamicClientRegistrationRepository
Implements ClientRegistrationRepository.
Loads OAuth2 client registrations dynamically per tenant.
TenantContextnull if unresolvedflowchart TD
FindClient["findByRegistrationId()"] --> ResolveTenant3["Resolve Tenant ID"]
ResolveTenant3 -->|Null| Fail["Return null"]
ResolveTenant3 -->|Found| LoadClient["DynamicClientRegistrationService.loadClient()"]
This enables:
Class: TenantContext
A lightweight static utility that stores the current tenant ID in a ThreadLocal.
setTenantId(String tenantId)getTenantId()clear()This enables:
Class: TenantContextFilter
A OncePerRequestFilter that resolves and enforces tenant context for every request.
tenant query parameterExcluded contexts:
loginssopublic.well-knownflowchart TD
Request2["HTTP Request"] --> ParsePath["Parse URI Path"]
ParsePath --> CheckPrefix["Tenant Prefix Present?"]
CheckPrefix -->|Yes| SetContext["Set TenantContext + Session"]
CheckPrefix -->|No| CheckQuery["Check tenant Query Param"]
CheckQuery -->|Found| SetContext
CheckQuery -->|Not Found| CheckSession["Check Session Attribute"]
CheckSession -->|Found| SetContext
SetContext --> Continue["Continue Filter Chain"]
Continue --> Clear["Clear ThreadLocal in finally"]
If a tenant changes mid-session:
This prevents cross-tenant session leakage.
The module enforces tenant isolation at multiple layers:
| Layer | Mechanism |
|---|---|
| Request | TenantContextFilter |
| Thread Scope | TenantContext (ThreadLocal) |
| Authentication | Tenant-aware UserDetailsService |
| Token | Custom JWT claims |
| Key Management | Per-tenant RSA keys |
| OAuth Clients | DynamicClientRegistrationRepository |
This layered enforcement ensures:
The Authorization Server Core And Tenant Context module collaborates with:
It acts as the security backbone of the OpenFrame platform.
flowchart TD
Start2["Incoming Request /{tenant}/oauth2/authorize"] --> TenantFilter2["TenantContextFilter"]
TenantFilter2 --> AuthChain["Security Filter Chain"]
AuthChain --> UserLookup["UserDetailsService"]
UserLookup --> TokenIssue["JWT Issuance"]
TokenIssue --> CustomClaims["Add tenant_id + roles"]
CustomClaims --> Sign["Sign with Tenant RSA Key"]
Sign --> Response["Return Token"]
The Authorization Server Core And Tenant Context module provides the secure, multi-tenant identity backbone of OpenFrame. By combining:
It ensures that authentication and authorization are both scalable and strongly isolated across tenants.
This module is critical to the security posture and SaaS architecture of the OpenFrame platform.