Implicit grant (§4.2) and Resource Owner Password Credentials grant (§4.3) intentionally not implemented per RFC 9700 §2.1.2 and §2.4.
RFC 9700
OAuth 2.0 Security Best Current Practice
Full
RFC 6750
Bearer Token Usage
Full
RFC 7009
Token Revocation
Full
Revocation invalidates the entire token family; the JTI blocklist is propagated to all cluster nodes via CRDT gossip. Additionally, ahdapa acts as an RFC 7009 client when revoking upstream IdP tokens: when revoke_on_replace = true on an upstream IdP, old access tokens are revoked at the upstream’s revocation endpoint on replacement.
RFC 7636
PKCE
Full
plain method intentionally not supported.
RFC 8693
Token Exchange
Full
Full OBO flow including actor_token validation, act claim chains, multi-way scope intersection (requested, subject token, client registration, federation policy ceiling, target client scopes), delegation target guards (delegation_targets / delegation_target_category), federation policy resolution (pattern-based identity mapping for workload federation), service identity resolution (when the resolved subject matches a registered client_id), and HBAC enforcement. When the subject token is an ID token (no scope claim), the subject-scope constraint is skipped; remaining ceilings still apply. Impersonation (acting as a different user without a subject token) is not supported.
RFC 8707
Resource Indicators
Full
resource parameter supported at authorization and token endpoints. Per-client allowed_resources restricts which resource URIs a client may request. Resource-driven aud claim in access tokens. resource_indicators_supported advertised in discovery metadata.
RFC 8628
Device Authorization Grant
Full
verification_uri_complete (§3.2) intentionally omitted to reduce phishing risk.
RFC 9126
Pushed Authorization Requests
Full
RFC 9207
Authorization Server Issuer Identification
Full
RFC 8705
OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens
Full
Subject DN (§2.1.1) and SAN-based (§2.1.2) client authentication: tls_client_auth_san_dns, tls_client_auth_san_uri, tls_client_auth_san_ip, tls_client_auth_san_email. IPv6 SAN addresses are compared via parsed IpAddr for canonical equivalence. When DPoP and mTLS are both active, cnf.jkt and cnf.x5t#S256 are both present in the same cnf object. In cluster mode the client-certificate thumbprint is carried in the internal auth-code payload so the origin node embeds it in the access token without re-seeing the certificate.
RFC 9449
DPoP
Full
Server-issued nonces are supported: the server returns a DPoP-Nonce header when a DPoP proof is present, and validates the nonce claim on subsequent proofs. Nonce generation is conditional on DPoP proof presence (nonces are not issued to non-DPoP requests).
"EdDSA" migrated to "Ed25519" and "Ed448" per §4. "EdDSA" is accepted as a deprecated alias in configuration and verification. Key generation and signing use ML-DSA-44, ML-DSA-65, and ML-DSA-87 via native-ossl.
RFC 9964
ML-DSA for JOSE and COSE
Full
ML-DSA-44, ML-DSA-65, and ML-DSA-87 key types (kty=AKP) with JWK pub field. The priv field (32-byte seed format per §4) is validated when present and rejected in public-key-only contexts. COSE identifiers are JOSE-only (WebAuthn uses COSE integers separately).
Credential issuance at POST /credential (OID4VCI). Per-client opt-in via sd_jwt_enabled. Selective disclosure of standard OIDC claims (name, given_name, family_name, email, groups, etc.). Signing uses the server’s active JWT signing key. Advertised in discovery as credential_endpoint and sd_jwt_alg_values_supported.
Pairwise subject identifiers (HMAC-SHA256, per-client sector key). acr_values_supported includes Kerberos (FreeIPA-authenticated sessions). ID token signing algorithm is configurable per client via id_token_signed_response_alg.
OIDC Discovery 1.0
Full
scopes_supported and claims_supported are rebuilt from the CRDT scope definitions on every request.
OIDC Federation 1.0
Partial
Self-signed Entity Statement published at /.well-known/openid-federation (including authority_hints when trust anchors are configured); bilateral trust via pre-configured [federation].trusted_issuers; multi-hop trust-chain validation (leaf through intermediaries to trust anchor) via [federation].trust_anchors with configurable max_chain_depth (default 5). Metadata policy operators (value, add, default, one_of, subset_of, superset_of, essential) are applied top-down from anchor to leaf. Resolved chains are cached with TTL derived from the shortest exp in the chain. Trust marks, subordinate listing (/list endpoint), and the /fetch endpoint for serving our own subordinate statements are not yet implemented.
Token Authority endpoint at POST /at/account/{id}/token. Authentication is Kerberos SPNEGO only; constraint values are derived from the authenticated Kerberos principal — this is a Kerberos-identity binding, not the telephony tnauthlist profile. Advertised in discovery as token_authority_endpoint when [gssapi] is configured. Only tktype = "JWTClaimConstraints" is accepted.
Used as the authority token constraint encoding format. The permittedValues fields bind Kerberos-specific claims: sub carries the authenticated Kerberos principal (e.g. alice@IPA.TEST), iss carries the server issuer URL, and (for host/service principals) dns carries the IPA-managed FQDNs for that principal. This is distinct from the telephony tnauthlist use of the same extension.
RFC 9118
EnhancedJWTClaimConstraints
Full
Ahdapa builds and DER-encodes an EnhancedJWTClaimConstraints structure. mustInclude is set to ["sub"], requiring the ACME server to reject any PASSporT that omits the sub claim. permittedValues binds sub to the Kerberos principal, iss to the server issuer URL, and (for host/service principals) dns to the IPA-managed FQDNs returned by an LDAP subtree search against cn=accounts for objects with managedBy pointing to the principal’s DN. The base64url-encoded DER is carried as tkvalue in the signed authority token JWT. mustExclude is supported by the ASN.1 codec but is not populated in the current issuance path.
The following algorithms are advertised in the discovery document and accepted for client authentication (private_key_jwt; client_secret_jwt uses HMAC-SHA2 only):
The default signing algorithm for tokens issued by the server is ES256 (ECDSA P-256). The algorithm is configurable via [server] jwt_signing_algorithm; changing it on an existing deployment triggers automatic key rotation on the next startup, with the old public key retained for backward verification. The active signing key is rotatable via the admin API and propagates to all cluster nodes automatically.
ID tokens may be signed with any algorithm from the same set (configurable via id_token_signed_response_alg per client).
Full — accepted at /token, device grant polling, and /par
client_secret_jwt
Full — accepted at /token, device grant polling, and /par
client_secret_basic
Full
client_secret_post
Full
none
Supported for public clients
tls_client_auth
Full (RFC 8705)
self_signed_tls_client_auth
Full (RFC 8705)
kerberos_client_auth
Full (FreeIPA extension) — client presents a Kerberos AP-REQ in Authorization: Negotiate; SPNEGO is verified server-side; principal matched against a registered exact value or glob pattern. Accepted at /token, /device_authorization, /revoke, and /introspect. Advertised in discovery only when [gssapi] is configured. Not available via dynamic client registration. See Kerberos client authentication for setup.
HTTP-Redirect (DEFLATE+base64), HTTP-POST (base64), and Artifact binding (type 0x0004) with SOAP resolution at POST /saml2/artifact.
OASIS SAML 2.0 Metadata (saml-metadata-2.0-os)
Partial
IdP and SP EntityDescriptor generation at /saml2/metadata and /saml2/sp/metadata/{upstream_id}. IdP metadata includes ArtifactResolutionService. Remote metadata import via admin API (POST /api/admin/saml2/sp/import-metadata and /saml2/idp/import-metadata) supports both bare EntityDescriptor and EntitiesDescriptor wrapper documents, with optional XML signature verification via trusted_certificate_pem. When metadata_url is stored, metadata is automatically re-fetched every [saml2] metadata_refresh_interval_secs (default 1 hour).
OASIS SAML 2.0 Profiles (saml-profiles-2.0-os)
Partial
Web Browser SSO Profile (both IdP and SP roles). Single Logout Profile (front-channel only, including SP-initiated SLO).
XML Digital Signatures (xmldsig-core)
Full (RSA, ECDSA)
libxmlsec1-openssl FFI. Outgoing SAML Responses are signed via sign_xml when sign_responses or sign_assertions is enabled (both default to true). Incoming assertion signatures are verified in the ACS handler and SLO handler using registered certificates. Supported key types: RSA, ECDSA P-256, ECDSA P-384. EdDSA and ML-DSA keys are not supported for XML signatures.
Credentials are merged from FreeIPA LDAP (ipa passkey-register) and the server’s own database at assertion time.
W3C WebAuthn Level 2 §7.1 (registration)
Full
FIDO MDS / attestation statement verification
Partial
Disabled by default (FreeIPA passkeys are registered externally). Set [passkey] mds_url = "https://mds3.fidoalliance.org/" to enable MDS blob fetching (refreshed every mds_refresh_interval_secs, default 24 h). Configure [passkey] mds_trusted_root_pem with the FIDO Alliance root certificate(s) for JWT blob signature verification and x5c chain validation (iterative, arbitrary depth). When enabled, revoked AAGUIDs are rejected and packed attestation is verified: with x5c, the certificate chain is walked against MDS root certificates; without x5c (self-attestation), the credential’s own public key is used for signature verification. tpm format is accepted but not cryptographically verified. Set [passkey] require_attestation = true to reject registrations with fmt: "none" or unverifiable chains.
Passkey login is enabled by setting ipa.passkey_rp_id in the configuration.
Supported COSE key types: EC2/P-256 (ES256), OKP/Ed25519 (EdDSA, COSE alg -8), RSA (RS256). FreeIPA stores passkey public keys as base64-encoded SPKI DER; ahdapa converts between SPKI DER and COSE CBOR transparently via cose_to_spki_der() / spki_der_to_cose() in src/auth/passkey.rs. Passkey management in IPA API mode uses the dedicated user_add_passkey / user_remove_passkey JSON-RPC commands.
These gaps are deliberate design decisions aligned with RFC 9700 (Security BCP) or the server’s scope:
alg=none JWTs (RFC 7519 §8): Not supported. No legitimate AS use case; security risk.
PKCE plain method (RFC 7636): S256-only per RFC 9700 §2.1.1.
Nested JWTs (RFC 7519 §5.2, §7.2): Not needed; no JWE implementation.
COSE support in RFC 9964: Server is JOSE-only. WebAuthn COSE algorithm integers are handled separately in src/auth/passkey.rs.
CORS/JSONP for revocation (RFC 7009 §2.3): Not needed; revocation is server-to-server.
JAR request parameter (RFC 9101): request_parameter_supported and request_uri_parameter_supported are both false in discovery. Request objects are not needed because PAR (RFC 9126) is supported and provides equivalent confidentiality and integrity without the complexity of signed/encrypted request JWTs.
RFC 7523 urn:ietf:params:oauth:grant-type:jwt-bearer: The client must have either a jwks_uri or inline jwks registered (RFC 7591 §2; mutually exclusive). The assertion iss must be present in [federation].trusted_issuers (or resolvable via a trust-chain anchor); it does not need to equal the requesting client’s client_id.
RFC 7591 Dynamic Client Registration: Client CRUD is available via the admin API (/api/admin/clients). The public POST /register endpoint accepts three authorization mechanisms: (1) a Kerberos service principal session from the server’s realm, (2) a JWT initial access token issued via POST /api/admin/registration-tokens (RFC 7591 §3, typ: "reg+jwt", supports one-time-use tokens), or (3) a static bearer token configured via server.registration_token. When none of these paths are available, /register returns 404.
Token Exchange (RFC 8693) impersonation: Full OBO delegation with actor_token is supported. Pure impersonation (acting as a different user without a subject token carrying that user’s identity) is not supported.
OIDC Federation 1.0: The server publishes a spec-compliant Entity Statement at /.well-known/openid-federation (including authority_hints when trust anchors are configured). Trust chain validation supports multi-hop intermediary resolution: the chain walker follows authority_hints from the leaf upward through intermediaries until a configured trust anchor is reached, with configurable max_chain_depth (default 5). Metadata policy operators (value, add, default, one_of, subset_of, superset_of, essential) are applied top-down from anchor to leaf. Resolved chains are cached with TTL derived from the shortest exp in the chain. Trust marks, subordinate listing (/list endpoint), and the /fetch endpoint for serving our own subordinate statements are not yet implemented.
kerberos_client_auth — HBAC hostgroup resolution: When kerberos_hbac_service is set on a Kerberos client, HBAC rules match machine principals by individual hostname and by IPA hostgroup membership. Hostgroup memberships for the requesting machine and the IdP server are resolved via LDAP at token time, and HBAC service-group memberships are also resolved. LDAP errors during group resolution are non-fatal: if the lookup fails, only direct-name and category=all rules continue to match.
Wrapping key distribution: The cluster wrapping key is stored locally on each node; only its UUID is gossiped. When a node sees an unfamiliar UUID it fetches the raw key via GET /api/gossip/wrapping-key, which returns a CMS EnvelopedData blob sealed to the requesting node’s ML-KEM-768 public key. Gossip sync messages themselves are wrapped in CMS SignedData(EnvelopedData) (ECDSA P-256 outer signature, ML-KEM-768 inner encryption per recipient). Restrict /api/gossip/sync and /api/gossip/wrapping-key to the cluster subnet as an additional defence-in-depth measure.