Skip to main content
Version: 1.0

Standards compliance

IDENTOS PBAC implements a broad set of open standards for OAuth 2.0, OpenID Connect, and User-Managed Access. Protocol compliance is handled at the endpoint layer, while authorization logic and policy enforcement are delegated to an external OPA policy engine — keeping the two concerns cleanly separated.

Compliance summary

StandardDescriptionStatus
OAuth 2.0 / OIDCOAuth 2.0 (RFC 6749), OAuth 2.1, OpenID Connect Core 1.0Implemented
RFC 9449OAuth 2.0 Demonstrating Proof of Possession (DPoP)Implemented
RFC 7591OAuth 2.0 Dynamic Client RegistrationImplemented — with and without software statements
RFC 8693OAuth 2.0 Token ExchangePartial — basic exchange done; actor token planned
RFC 8707Resource Indicators for OAuth 2.0Implemented
RFC 9396OAuth 2.0 Rich Authorization Requests (RAR)Fully implemented
draft-ietf-oauth-client-id-metadata-documentClient ID Metadata Document (CIMD)Implemented
UMA 2.0User-Managed Access 2.0 GrantPartial — resource reg, delegation done; RPT flow planned
OIDC / UserInfoOpenID Connect Core 1.0 UserInfo + Discovery detailFully implemented
MCP Authorization Specification (draft)OAuth 2.1 profile for Model Context ProtocolCompliant — see below

All endpoints follow the OAuth 2.0 framework (RFC 6749/6750) and are extended with the standards above. Policy enforcement at each endpoint is handled by OPA, keeping protocol compliance separate from authorization logic.


OAuth 2.0 and OpenID Connect

See also

Getting tokens — grant type examples and DPoP. Token introspection — RS validation patterns.

This section describes the OAuth 2.0 and OpenID Connect Core 1.0 compliance posture of the PBAC Authorization Server, covering supported grant types, PKCE enforcement, token handling, discovery metadata, and the OAuth 2.1 hardening requirements.

References:

OAuth 2.0 / OAuth 2.1

Supported Grant Types

Grant TypeValueStatusNotes
Authorization Codeauthorization_codeImplementedPKCE required per OAuth 2.1
Client Credentialsclient_credentialsImplementedConfidential clients only (§4.2.2)
Refresh Tokenrefresh_tokenImplemented
Token Exchangeurn:ietf:params:oauth:grant-type:token-exchangeImplementedRFC 8693; endpoint wired, policy-evaluated
Implicitresponse_type=tokenRemovedRejected per OAuth 2.1 §1.9
Resource Owner PasswordpasswordRemovedRejected per OAuth 2.1 §1.9

Token Types

TypeStatusNotes
Bearer tokensImplementedRFC 6750; Authorization: Bearer
DPoPImplementedRFC 9449; proof validation at token endpoint, cnf.jkt at introspection, policy-driven enforcement via OPA

Client Authentication Methods

MethodStatusNotes
client_secret_basicImplementedHTTP Basic auth at token endpoint
client_secret_postImplementedCredentials in POST body
private_key_jwtImplementedRFC 7523; validated via ClientAssertionValidator
noneImplementedPublic clients (PKCE required)

PKCE (RFC 7636 / OAuth 2.1 §9.8)

PKCE is enforced for all authorization code flows. Public clients must always supply a code_challenge. Confidential clients may omit it, but the challenge is validated when present.

RequirementStatusNotes
S256 method supportedImplementedcode_challenge_method=S256
plain methodAccepted (not recommended)Spec permits it; S256 is preferred
Missing code_challenge for public clientsRejectedinvalid_request with PKCE-related description
Wrong code_verifier rejectedImplementedinvalid_grant / invalid_request

Authorization Code Lifecycle (OAuth 2.1 §4.1.2)

RequirementStatusNotes
Single-use codesImplementedSecond use returns invalid_grant
Codes expire ≤ 10 minutesImplemented
Redirect URI exact matching (§3.1.2)ImplementedString comparison; prefix/partial matches rejected

Token Endpoint Behaviour

RequirementStatusNotes
Content-Type: application/json responseImplemented
Cache-Control: no-storeImplementedSet on all token responses
Pragma: no-cacheImplemented
grant_type requiredImplementedinvalid_request if absent
Fragment component rejected in resourceImplementedRFC 8707 §2

OpenID Connect Core 1.0

ID Tokens

ID tokens are issued in the authorization code flow when openid is included in the granted scopes.

RequirementStatusNotes
iss, sub, aud, exp, iat required (§2)ImplementedAll claims present in issued tokens
Signed with JWS; algnone (§2)ImplementedRS256 via NimbusJwtEncoder
aud contains client_id (§2)Implemented
nonce echoed when present in request (§2, §3.1.2.1)ImplementedStored in AuthorizationCode, forwarded to ID token
auth_time included when max_age requested (§3.1.2.1)Implemented
Not issued when openid scope absent (§3.1.2.1)Implemented

UserInfo Endpoint (§5.3)

RequirementStatusNotes
GET /userinfo with Bearer tokenImplementedRFC 6750
POST /userinfoImplemented§5.3.1
sub claim required in response (§5.3.2)Implemented
sub matches sub in ID token (§5.3.2)Implemented
Content-Type: application/json (§5.3.2)Implemented
401 with WWW-Authenticate for invalid/missing token (§5.3.3)Implemented
Cache-Control: no-store on responseImplemented
profile scope → name claims (§5.4)Implementedname, preferred_username
email scope → email claims (§5.4)Implementedemail, email_verified

Prompt Parameter (§3.1.2.1)

ValueStatusNotes
noneImplementedReturns login_required redirect when no active session
none combined with other valuesRejectedReturns invalid_request
login, consent, select_accountPassed through to upstream IdP

Discovery (OpenID Connect Discovery 1.0)

The discovery document is served at GET /.well-known/openid-configuration. Its content is derived from the pbac.oidc.issuer configuration and live policy data.

Metadata FieldRequiredStatusValue
issuerYesImplementedFrom pbac.oidc.issuer
authorization_endpointYesImplemented{issuer}/authorize
token_endpointYesImplemented{issuer}/token
jwks_uriYesImplemented{issuer}/.well-known/jwks.json
response_types_supportedYesImplemented["code"]
subject_types_supportedYesImplemented["public"]
id_token_signing_alg_values_supportedYesImplemented["RS256"]; none excluded
userinfo_endpointRecommendedImplemented{issuer}/userinfo
scopes_supportedRecommendedImplemented["openid","profile","email"]
claims_supportedRecommendedImplemented["sub","name","email","preferred_username","email_verified"]
introspection_endpointExtensionImplemented{issuer}/introspect
authorization_details_types_supportedExtension (RAR)ImplementedDerived from policy data at runtime

JWKS Endpoint

  • Path: GET /.well-known/jwks.json
  • Format: JWK Set (keys array) with at least one RSA public key
  • Key management: Auto-generated for dev; set pbac.oidc.jwks-path for production

Compliance matrix

RequirementSpec ReferenceStatusNotes
Authorization code flowRFC 6749 §4.1Implemented
Client credentials flowRFC 6749 §4.4Implemented
Refresh token flowRFC 6749 §6Implemented
Token exchangeRFC 8693Implemented
Implicit grant removedOAuth 2.1 §1.9Implementedunsupported_response_type
ROPC grant removedOAuth 2.1 §1.9Implementedunsupported_grant_type
PKCE S256 mandatory (public clients)OAuth 2.1 §9.8Implemented
PKCE S256 supported (confidential clients)RFC 7636Implemented
Exact redirect URI matchingOAuth 2.1 §3.1.2Implemented
Authorization codes single-useOAuth 2.1 §4.1.2Implemented
Authorization codes ≤ 10 min expiryOAuth 2.1 §4.1.2Implemented
Client credentials: confidential onlyOAuth 2.1 §4.2.2Implemented
client_secret_basic authRFC 6749 §2.3.1Implemented
private_key_jwt authRFC 7523Implemented
Bearer token usageRFC 6750Implemented
Cache-Control: no-store on token responsesRFC 6749 §5.1Implemented
OIDC ID token required claims (iss/sub/aud/exp/iat)OIDC Core §2Implemented
ID token signed RS256OIDC Core §2Implemented
nonce echoed in ID tokenOIDC Core §2Implemented
auth_time when max_age requestedOIDC Core §3.1.2.1Implemented
prompt=none handlingOIDC Core §3.1.2.1Implemented
UserInfo sub claimOIDC Core §5.3.2Implemented
UserInfo sub matches ID token subOIDC Core §5.3.2Implemented
OIDC Discovery documentOIDC Discovery 1.0Implemented
JWKS endpointOIDC Discovery 1.0Implemented
DPoP sender-constrained tokensRFC 9449ImplementedProof validation at /token; cnf.jkt in introspection; policy-driven enforcement
Refresh token rotation (public clients)OAuth 2.1 §4.3.1ImplementedNew refresh token issued on each use; previous token invalidated
Pairwise subject identifiersOIDC Core §8.1Not implementedPublic subject type only
ID token at_hashOIDC Core §3.3.2.11Not implementedOptional for code flow

Roadmap

  • Pairwise subject identifiers (OIDC Core §8.1)
  • at_hash in ID token (optional per spec)
  • Initial access token for protected registration (RFC 7591)

RFC 7591: Dynamic Client Registration

See also

Registering software — DCR walkthrough with software statements.

OAuth 2.0 Dynamic Client Registration Protocol compliance for the /register endpoint.

Reference: RFC 7591

Endpoint and protocol

RequirementStatusImplementation
POST to registration endpointDonePOST /register
Content-Type: application/jsonDoneSpring MVC default
Accept: application/jsonDoneSpring MVC default
TLS for transportN/ADeployment concern

Client metadata (request)

FieldRequiredStatusNotes
redirect_urisY (redirect flows)Done@NotEmpty validation
token_endpoint_auth_methodNDonenone, client_secret_post, client_secret_basic, private_key_jwt
grant_typesNDoneDefault: authorization_code, refresh_token
response_typesNDoneDefault: code
scopeNDone
client_nameNDone
client_uriNDone
logo_uriNDone
contactsNDone
tos_uriNDone
policy_uriNDone
jwks_uriNDone
jwksNDone
software_idNDone
software_versionNDone
software_statementNDoneJWT string; signature verification configurable via PBAC_SOFTWARE_STATEMENT_VERIFY

Response (201 Created)

FieldRequiredStatusNotes
client_idYDoneAS-assigned UUID
client_secretIf confidentialDoneRandom 32-char; hashed in DB
client_id_issued_atNDoneUnix timestamp
client_secret_expires_atIf secret issuedDone0 = never expires
All registered metadataYDoneEchoed in response

Error response (400)

Error CodeStatusWhen
invalid_redirect_uriDoneValidation (future)
invalid_client_metadataDoneValidation, missing_explicit_declarations
invalid_software_statementDoneUntrusted issuer, malformed JWT
unapproved_software_statementDoneDenylist, policy deny

Software statement

RequirementStatusNotes
JWT formatDoneheader.payload.signature
iss claimDoneUsed for trust check (OPA)
Signature verificationDoneConfigurable via PBAC_SOFTWARE_STATEMENT_VERIFY (default: false); when enabled, verifies via issuer JWKS URI

Test references

ScenarioTest
Valid RS registrationtest_register_rs_allowed
Valid client registrationtest_register_client_allowed
Denylist denytest_register_denied_denylist
Step-uptest_register_step_up
Missing redirect_uristest_register_missing_redirect_uris_returns_400
Invalid metadatatest_register_invalid_token_endpoint_auth_method_returns_400
Private key JWT registrationtest_register_private_key_jwt_client (integration-tests/test_private_key_jwt.py)

Plain DCR (no software statement)

When public_client_policy.enabled: true is set in policy data, clients may register without a software_statement. Grant types are validated against public_client_policy.dcr.allowed_grant_types. Both public (token_endpoint_auth_method: none) and confidential clients are supported.

Open items

  • redirect_uri format validation (RFC 6749)
  • Initial access token support (protected registration)

RFC 8693: Token Exchange

See also

Token exchange — agent scope narrowing and cross-domain identity.

OAuth 2.0 Token Exchange compliance for the /token endpoint.

Reference: RFC 8693

Endpoint and protocol

RequirementStatusImplementation
Grant type urn:ietf:params:oauth:grant-type:token-exchangeDonePOST /token routes to token exchange flow
Confidential client requiredDonePublic clients rejected
TLS for transportN/ADeployment concern

Request parameters (Section 2.1)

ParameterRequiredStatusNotes
grant_typeYDoneMust be urn:ietf:params:oauth:grant-type:token-exchange
subject_tokenYDoneValidated against issued tokens; must be active and unexpired
subject_token_typeYDoneOnly urn:ietf:params:oauth:token-type:access_token supported
actor_tokenNPlannedNot yet accepted; needed for delegation chain scenarios
actor_token_typeNPlannedPaired with actor_token
resourceNDoneResolved to resource type for policy evaluation
audienceNPartialAccepted but not enforced in policy
scopeNDoneValidated; must be subset of subject token scopes
requested_token_typeNPartialAccepted and echoed in response; not validated against AS capabilities

Response (Section 2.2.1)

FieldRequiredStatusNotes
access_tokenYDoneNewly issued token
token_typeYDoneBearer
expires_inRecommendedDoneIncluded in response
issued_token_typeYDoneEchoed from request or defaulted
scopeConditionalDoneIncluded when granted scopes differ from request
refresh_tokenNN/ANot issued (correct per spec — SHOULD NOT for temporary credentials)

Scope narrowing

Scope narrowing is enforced by OPA policy. When a token exchange is requested:

  1. The subject token's granted scopes are extracted.
  2. The requested scopes must be a subset of the subject token's scopes.
  3. If any requested scope exceeds what the subject token grants, the request is denied.

This ensures each step in a delegation chain can only maintain or narrow access — never expand it.

Status: Done

Act claim (Section 4.1)

RequirementStatusNotes
act claim in issued token identifying the actorPlannedRequires actor_token support
Nested act for chained delegationPlannedDepends on act claim implementation

The act claim enables audit trails showing who acted on whose behalf. This is a key requirement for agentic delegation scenarios.

Error handling (Section 2.2.2)

Error CodeStatusWhen
invalid_grantDoneSubject token not found, expired, or invalid type
invalid_requestDoneMissing required parameters
invalid_tokenPlannedSpec-specific error for token validation failures
invalid_targetPlannedSpec-specific error for unreachable resource/audience

Currently, token validation failures return invalid_grant. Spec-aligned error codes (invalid_token, invalid_target) are planned.

Subject token types (Section 3)

Token Type URIStatus
urn:ietf:params:oauth:token-type:access_tokenDone
urn:ietf:params:oauth:token-type:refresh_tokenNot supported
urn:ietf:params:oauth:token-type:id_tokenNot supported
urn:ietf:params:oauth:token-type:saml1Not supported
urn:ietf:params:oauth:token-type:saml2Not supported
urn:ietf:params:oauth:token-type:jwtNot supported

Only access tokens are currently accepted as subject tokens. Additional types may be added based on deployment requirements.

Security considerations (Section 7)

RequirementStatusNotes
Subject token not invalidated by exchangeDoneOriginal token remains valid after exchange
Scope can only narrow, never expandDoneOPA policy enforces subset check
Confidential client requiredDonePublic clients rejected at token endpoint

Discovery metadata

RequirementStatusNotes
grant_types_supported includes token exchangePlannedNot yet advertised in /.well-known/openid-configuration

Open items

  • actor_token / actor_token_type parameter support and act claim generation
  • Advertise token exchange in discovery metadata
  • Spec-aligned error codes (invalid_token, invalid_target)
  • Audience enforcement in policy evaluation
  • Validation of requested_token_type against AS capabilities

RFC 8707: Resource Indicators

See also

Getting tokens — using resource and resource_types parameters.

Reference: RFC 8707

IDENTOS PBAC supports RFC 8707 resource indicators via the resource parameter on authorization and token requests. The resource URI is resolved to a resource_type via database lookup and passed to OPA as input.request.resource and input.request.resolved_resource_type. When no DB match exists, callers can provide a resource_type hint parameter. Fragment components in the resource parameter are rejected per RFC 8707 §2.


RFC 9396: Rich Authorization Requests

See also

Getting tokens — RAR examples.

OAuth 2.0 Rich Authorization Requests (RAR) compliance for the authorization and token endpoints.

Reference: RFC 9396

Overview

RequirementStatusImplementation
authorization_details = JSON array of objectsDoneParse, validate in AuthorizeController, TokenController
Each entry must have type (required)DoneValidation on parse; reject with invalid_authorization_details
Mutual exclusivity with resource/scopeDoneReject when both RAR and resource/scope present

Authorization request (Section 3)

RequirementStatusImplementation
authorization_details as request parameterDoneGET /authorize?authorization_details=[...]
JSON array of objectsDoneJackson parse; validate structure
type required per entryDoneReject missing/invalid type
Mutual exclusivityDoneinvalid_request when both sent

Error invalid_authorization_details (Sections 5, 8)

RequirementStatusImplementation
Use error code invalid_authorization_detailsDoneTokenExceptionHandler, AuthorizeException
Unknown typeDoneoauth.rar.rego; reject type not in resource.types or rar.types
Invalid structure (missing type, wrong types)DoneController validation
Unknown fields for known typeN/APolicy may extend; baseline passes through

Token request (Section 6)

RequirementStatusImplementation
authorization_details in token requestDonePOST /token with form param authorization_details
client_credentials: use form paramDoneTokenController parses authorization_details
authorization_code: use stored from codeDoneTokenService reads from AuthorizationCode
Mutual exclusivityDoneinvalid_request when both RAR and resource/scope

Token response (Section 7)

RequirementStatusImplementation
MUST return authorization_details in token responseDoneTokenResponse.authorizationDetails
Return granted_authorization_details from PDPDoneFrom oauth.rar.granted_authorization_details

JWT access token (Section 9.1)

RequirementStatusNotes
authorization_details as JWT claimN/AOpaque tokens only; not implemented

Introspection (Section 9.2)

RequirementStatusImplementation
Return authorization_details when AS included itDoneIntrospectResponse; populated from pdp_output

Discovery metadata (Section 10)

RequirementStatusImplementation
authorization_details_types_supportedDoneWellKnownController; union of resource.types keys and rar.types

Policy layer

ComponentPurpose
oauth.rar.regoValidates type, delegates entitlements for resource types, RAR-only types via rar.types
oauth.rar.extExtension point for custom deny (e.g. payment_initiation rules)
oauth.authorize.regoIntegrates RAR flow; mutual exclusivity; invalid_authorization_details
oauth.token.regoIntegrates RAR flow; granted_authorization_details in result

Test references

ScenarioTest
RAR client_credentials tokentest_rar_client_credentials_token_returns_200
Token response includes authorization_detailstest_rar_token_response_includes_authorization_details
Introspect returns authorization_detailstest_rar_introspect_returns_authorization_details
Mutual exclusivity (token)test_rar_mutual_exclusivity_reject_both
Mutual exclusivity (authorize)test_rar_authorize_mutual_exclusivity_reject_both
Unknown type → invalid_authorization_detailstest_rar_unknown_type_returns_invalid_authorization_details
Resource type (urn:as:userinfo) with scopestest_rar_resource_type_urn_as_userinfo_with_scopes
Resource type with locationstest_rar_resource_type_with_locations
Custom RAR-only type (payment_initiation)test_rar_custom_rar_only_type_payment_initiation
RAR authorize full flowtest_rar_authorize_full_flow_code_then_token

UMA 2.0

See also

Token introspection — introspect with RS context. Obligations — RS obligation patterns.

User-Managed Access (UMA) 2.0 Grant for OAuth 2.0 Authorization compliance.

References:

Resource registration (Section 3.2)

RequirementStatusImplementation
POST to create resourceDonePOST /resource_registration/resource
GET to read resourceDoneGET /resource_registration/resource/{id}
GET to list resourcesDoneGET /resource_registration/resource
PUT to update resourceDonePUT /resource_registration/resource/{id}
DELETE to remove resourceDoneDELETE /resource_registration/resource/{id}
PAT required (Bearer with uma_protection)DoneValidated on every request
Resource scopes ceiling enforcementDoneScopes validated against resource type definition
Owner tracking (user or client)DoneUser-owned via PAT sub claim; client-owned when no user context

Protection API token (PAT)

RequirementStatusNotes
PAT as Bearer token with uma_protection scopeDoneRequired for resource registration and permission endpoints
User PAT via authorization_code flowDoneCarries sub claim for user-owned resources
Client PAT via client_credentials flowDoneNo sub; used for client-managed resources
Resource indicator urn:as:introspectDoneUsed in token request to obtain PAT

Permission endpoint (Section 4)

RequirementStatusNotes
POST to create permission ticketDonePOST /permission
PAT requiredDoneBearer with uma_protection scope
Returns 201 with opaque ticketDoneTicket stored with resource ID and requested scopes
Ticket expiryDone5-minute TTL
Multiple permissions per requestPlannedCurrently one resource per ticket

Token endpoint — RPT issuance (Section 1, 4)

The full UMA grant flow requires the token endpoint to accept a permission ticket and issue a Requesting Party Token (RPT).

RequirementStatusNotes
Accept ticket parameter at /tokenPlannedToken endpoint does not yet consume permission tickets
Validate ticket existence and expiryPlannedTickets are stored but not redeemed
Issue RPT with granted permissionsPlannedNo distinct RPT token type; access tokens serve this role today
Consume ticket after issuance (one-time use)PlannedNo consumption logic
Policy evaluation before RPT issuancePlannedOPA integration for ticket-based grants
Planned

The permission ticket → RPT exchange at the token endpoint is not yet implemented. Permission tickets can be created but are not consumed to issue RPTs. This is the primary gap in the UMA 2.0 flow.

Introspection (Section 5)

RequirementStatusNotes
Introspect with PAT (Bearer uma_protection)DoneValidates caller PAT and re-evaluates policy
Introspect with Basic authDoneFor clients with introspection scope entitlement
RS-supplied context (resource, scopes, action)DoneMerged into PDP re-evaluation
permissions array in responsePlannedUMA spec requires resource_id + scopes per permission

Delegation

PBAC extends UMA with an explicit Delegation Store for time-bound, revocable grants.

RequirementStatusNotes
User → Client delegationDoneGrantee is client_id; stored with resource, scopes, expiry
User → User delegationDoneGrantee is subject_id; same non-expansive constraints
Non-expansive enforcementDoneDelegated scopes must be subset of resource scopes
RevocationDoneSoft-delete with revoked_at timestamp
Expiry enforcementDoneExpired grants are not evaluated
Delegation evaluated at token timeDoneOPA receives delegation context in PDP input
Delegation evaluated at introspect timeDoneRS can pass delegation metadata in context

The Delegation Store is managed via the /delegation endpoint (requires delegation_management scope).

Discovery metadata (Section 2)

RequirementStatusNotes
resource_registration_endpointDoneAdvertised in /.well-known/openid-configuration
permission_endpointDoneAdvertised in /.well-known/openid-configuration
introspection_endpointDoneAdvertised in /.well-known/openid-configuration
uma_profiles_supportedPlannedNot yet advertised

Summary

The UMA 2.0 implementation provides:

  • Complete resource registration, permission ticket creation, PAT handling, delegation management, and discovery metadata.
  • Planned permission ticket → RPT exchange at the token endpoint, permissions array in introspection responses, and full UMA profile advertisement.

The delegation model goes beyond the UMA baseline by supporting explicit user-to-user and user-to-client grants with non-expansive enforcement, revocation, and time-bound expiry.

Open items

  • Permission ticket consumption at the token endpoint (RPT issuance)
  • permissions array in introspection response per UMA Section 5
  • uma_profiles_supported in discovery metadata
  • Multiple permissions per ticket request
  • Expired ticket cleanup

OIDC UserInfo and Discovery

See also

OAuth endpoints reference — full endpoint documentation.

This section maps OIDC Core 1.0 and OpenID Connect Discovery 1.0 requirements to the PBAC Authorization Server implementation.

OIDC Core 1.0

UserInfo Endpoint (Section 5.3)

RequirementImplementation
Protected resource, Bearer tokenGET/POST /userinfo; validates Authorization: Bearer
5.3.1 UserInfo Request: GET/POST, Bearer in AuthorizationBoth HTTP methods supported; token extracted from header
5.3.2 Successful Response: sub REQUIRED, JSON, Content-Typesub always returned; Content-Type: application/json; Cache-Control: no-store
5.3.3 Error Response: 401, WWW-Authenticate401 with WWW-Authenticate: Bearer error="invalid_token" for missing/invalid/expired token
5.4 Scope Values: profile, email request claimsprofilename, preferred_username; emailemail, email_verified

Token Response (Section 3.1.3.3)

RequirementImplementation
id_token when openid scopeid_token included in authorization_code token response when openid in granted scopes

ID Token (Section 2)

RequirementImplementation
iss, sub, aud, exp, iatAll required claims in signed JWT
Signed with JWSRS256; signed via NimbusJwtEncoder
nonce (when in auth request)Passed from AuthorizationCode to id_token
auth_time (optional)Supported when provided

Data Minimization

  • SubjectUserInfo stores only: name, email, preferred_username (plus subject_id, identity_provider_id)
  • Claims returned only when corresponding scope is granted

Security

  • Token validation: AccessTokenRepository.findByTokenWithClientAndIdentityProvider; checks expiresAt
  • Requires openid in granted_scopes for UserInfo
  • Requires subjectId (user context); client_credentials tokens return 401
  • Cache-Control: no-store on UserInfo responses

OpenID Connect Discovery 1.0

Discovery SectionRequirementImplementation
4.1 Well-Known URI/.well-known/openid-configurationGET returns JSON
issuerRequiredFrom pbac.oidc.issuer
authorization_endpointRequired{issuer}/authorize
token_endpointRequired{issuer}/token
jwks_uriRequired{issuer}/.well-known/jwks.json
response_types_supportedRequired["code"]
subject_types_supportedRequired["public"]
id_token_signing_alg_values_supportedRequired (RS256)["RS256"]
userinfo_endpointRecommended{issuer}/userinfo
scopes_supportedRecommended["openid","profile","email"]
claims_supportedRecommended["sub","name","email","preferred_username","email_verified"]

JWKS Endpoint

  • Path: /.well-known/jwks.json
  • Purpose: Expose public RSA key(s) for ID token signature verification
  • Format: JWK Set with keys array; each key has kty, kid, n, e
  • Key management: Auto-generated for dev; configurable via pbac.oidc.jwks-path for production

MCP Authorization Specification

See also

Protect MCP servers with the gateway — MCP gateway setup and integration.

The MCP Authorization Specification (draft) defines an OAuth 2.1 profile for securing Model Context Protocol servers. PBAC implements all normative requirements.

Reference: MCP Authorization Specification

Compliance summary

RequirementMCP ObligationStatusNotes
Authorization code grant with PKCEMUSTImplementedS256 enforced for public clients
Refresh token rotationMUST (public clients, §4.3.1)ImplementedNew token issued on every refresh; previous invalidated
Dynamic Client Registration (RFC 7591)MAYImplementedPlain DCR enabled via public_client_policy
Client ID Metadata Document (CIMD)SHOULDImplementedURL-format client_id in /authorize triggers CIMD resolution
Protected Resource Metadata (RFC 9728)SHOULDImplementedGET /.well-known/oauth-protected-resource on MCP gateway
registration_endpoint in discoverySHOULDImplementedPresent in /.well-known/openid-configuration
client_id_metadata_document_supported in discoverySHOULDImplementedSet to true
Implicit grant removedMUST NOTImplementedunsupported_response_type returned
Client credentials grantN/AImplementedAvailable for server-to-server flows

CIMD flow

When an MCP client presents a URL-format client_id at /authorize:

  1. The AS fetches the JSON document at that URL.
  2. It validates client_id and redirect_uris against the request parameters.
  3. A transient public client is created with registration_type: cimd.
  4. granted_resources are synthesized from data.oauth.public_client_policy.cimd.granted_resources in policy data.
  5. The authorization code flow proceeds normally.

The MCP gateway uses CIMD so that any compliant MCP client can connect without pre-registration.

Plain DCR flow

When public_client_policy.enabled: true is set in policy data, MCP clients that support Dynamic Client Registration can register themselves before starting the authorization flow:

curl -s -X POST https://pbac.example.com/register \
-H "Content-Type: application/json" \
-d '{
"redirect_uris": ["http://localhost:19876/callback"],
"client_name": "Claude Code",
"token_endpoint_auth_method": "none",
"grant_types": ["authorization_code", "refresh_token"]
}'

The registered client_id can then be used in subsequent authorization requests.


Next steps