RFC compliance matrix
Every standard the library actively cites in its code, mapped to the package that implements it and the option / feature that gates it.
Status legend
full implements the OP-facing surface the library claims for that spec end-to-end.
partial implements the parts the OP needs; some optional sections are out of scope by design.
planned in the spec list, not landed yet.
out out-of-scope; structurally not the library's concern.
refused deliberately rejected (e.g. alg=none).
These labels describe implementation coverage, not OpenID Foundation certification. A full label does not override requirements outside this library's stated scope; the exceptions in each row still apply.
OIDC core / discovery
| Standard | Status | Where |
|---|---|---|
| OpenID Connect Core 1.0 | partial (response_type=code only; Aggregated and Distributed claim types §5.6.2 are not emitted; pairwise sub §8.1 is now wired via op.WithPairwiseSubject. See "Out of scope by design" below.) | op/, internal/authorize, internal/tokenendpoint, internal/userinfo, internal/sector |
| OpenID Connect Discovery 1.0 | partial (metadata endpoint is implemented, but id_token_signing_alg_values_supported omits RS256, which Discovery requires) | internal/discovery |
| OpenID Connect Dynamic Client Registration 1.0 | partial (core flow, sector_identifier_uri fetch, application_type=web / =native redirect rules, JWKs / pairwise / response-type cross-checks, PUT reserved-field rejection, post_logout_redirect_uris round-trip, and the five JWE alg/enc encrypted-response families are enforced; client_secret is intentionally omitted from GET /register/{id} responses, software_statement is not accepted) | internal/registrationendpoint |
| OpenID Connect RP-Initiated Logout 1.0 | full | internal/endsession |
| OpenID Connect Back-Channel Logout 1.0 | full | internal/backchannel |
| OpenID Connect Front-Channel Logout 1.0 | out (iframe / third-party-cookie signalling is intentionally not shipped; use Back-Channel Logout) | — |
| OpenID Connect Session Management 1.0 | out (third-party-cookie-dependent; back-channel preferred) | — |
| OpenID Connect CIBA Core 1.0 | partial (poll delivery only; ping / push deferred to v2+) | internal/ciba, internal/cibaendpoint, op.WithCIBA |
OAuth 2.0 core RFCs
| RFC | Status | Where / option |
|---|---|---|
| RFC 6749 OAuth 2.0 Framework | partial (authorization-code, refresh-token, and client-credentials surfaces; implicit and password grants are intentionally not implemented) | op/, internal/authorize, internal/tokenendpoint |
| RFC 6750 Bearer Token Usage | partial (OP-issued bearer tokens and OP-hosted resource endpoints such as UserInfo / introspection; general RS challenge behaviour belongs to resource servers) | internal/tokens, internal/userinfo, internal/introspectendpoint |
| RFC 6819 Threat Model & Security Considerations | partial (security guidance applied across the OP; not a standalone protocol surface) | whole codebase |
| RFC 7009 Token Revocation | full (gated by feature.Revoke) | internal/revokeendpoint |
| RFC 7521 Assertion Framework | partial (private_key_jwt client authentication only; assertion grants and client_secret_jwt are intentionally not implemented) | internal/clientauth |
| RFC 7523 JWT Bearer Assertions for Client Auth | partial (private_key_jwt; JWT bearer authorization grants and client_secret_jwt are not implemented, and client_secret_jwt is rejected at registration with invalid_client_metadata) | internal/clientauth |
| RFC 7591 Dynamic Client Registration | partial (gated by feature.DynamicRegistration; software_statement is rejected with invalid_software_statement) | internal/registrationendpoint |
| RFC 7592 DCR Management | partial (read / update / delete; PUT omission resets to server defaults rather than deleting fields, and the response only re-emits client_secret on a none → confidential auth-method upgrade or an explicit rotation request) | internal/registrationendpoint |
| RFC 7636 PKCE | full (only S256; plain refused) | internal/pkce |
| RFC 7662 Token Introspection | full (gated by feature.Introspect) | internal/introspectendpoint |
RFC 7800 Confirmation Methods (cnf) | full | internal/dpop, internal/mtls, internal/tokens |
| RFC 8252 OAuth 2.0 for Native Apps | partial (OP-side native redirect / loopback hardening; client-app behaviour is out of scope) | internal/registrationendpoint, internal/authorize |
| RFC 8414 Authorization Server Metadata | full | internal/discovery |
| RFC 8485 Vectors of Trust | partial (consumed via ACR/AAL mapping) | op/aal.go, op/acr.go |
| RFC 8628 Device Authorization Grant | full (gated by op.WithDeviceCodeGrant; slow_down ladder persisted atomically with LastPolledAt; op/devicecodekit ships the brute-force gate + revoke audit hook) | internal/devicecode, internal/devicecodeendpoint, op/devicecodekit |
| RFC 8693 OAuth 2.0 Token Exchange | full (gated by op.RegisterTokenExchange; act chain mandatory whenever actor differs from subject; cnf rebinding to request's verified DPoP / mTLS) | internal/customgrant/tokenexchange |
| RFC 8705 OAuth 2.0 mTLS Client Auth & Cert-Bound Tokens | partial (feature.MTLS wires certificate-bound access tokens and mtls_endpoint_aliases; token endpoint tls_client_auth / self_signed_tls_client_auth dispatch is not wired) | internal/mtls |
| RFC 8707 Resource Indicators | partial (canonicalisation and client allow-list enforcement across authorize / token / device / CIBA; built-in grants currently narrow most issuance paths to a single resource value) | internal/resourceindicator, internal/authorize, internal/tokenendpoint, internal/devicecodeendpoint, internal/cibaendpoint |
| RFC 8725 JWT Best Current Practices | full (alg allow-list, type checks) | internal/jose |
| RFC 9068 JWT Profile for Access Tokens | partial (JWT issuance is ES256-only, while §2.1 requires RS256 support; the verifier also accepts tokens without the §2.2 required jti) | internal/tokens |
| RFC 9101 JAR (JWT-Secured Authorization Request) | full (gated by feature.JAR) | internal/jar |
| RFC 9126 PAR (Pushed Authorization Requests) | full (gated by feature.PAR) | internal/parendpoint |
| RFC 9207 OAuth 2.0 Authorization Server Issuer Identifier | full | internal/authorize (iss parameter on the response) |
RFC 9396 Rich Authorization Requests (authorization_details) | full (gated by op.WithAuthorizationDetailTypes; validated at /authorize, /par, /token, persisted on the grant, echoed on JWT access tokens and introspection, advertised in discovery) | internal/authorizationdetails, op/authorization_details.go |
| RFC 9449 DPoP | full incl. §8 nonce flow (gated by feature.DPoP) | internal/dpop, op.WithDPoPNonceSource |
| RFC 9470 OAuth 2.0 Step Up Authentication Challenge | full (OP honours acr_values / max_age reauthentication via ACR rules; op.StepUpChallenge builds the resource-server WWW-Authenticate challenge the embedder's RS returns) | op/rule.go (RuleACR), op/stepup.go |
| RFC 9700 OAuth 2.0 Security Best Current Practice | partial (OP-side BCP posture; resource-server and client-side requirements remain with embedders) | whole codebase |
| RFC 9701 JWT Response for OAuth 2.0 Token Introspection | full (signed JWT default; JWE-wrapped per client introspection_encrypted_response_alg / _enc metadata) | internal/introspectendpoint, internal/jose |
| RFC 9728 OAuth 2.0 Protected Resource Metadata | full (gated by op.WithProtectedResources; served at /.well-known/oauth-protected-resource with the issuer stamped into authorization_servers) | internal/protectedresource, op/protected_resource.go |
IETF drafts
| Draft | Status | Where |
|---|---|---|
OAuth 2.0 Grant Management (draft-ietf-oauth-grant-management) | partial (gated by op.WithGrantManagement; grant_management_action / grant_id honoured, query / revoke endpoint mounted, grant_id on the token response, discovery advertisement. Tracks an IETF draft — surface may change on a draft update) | internal/grantmgmtendpoint, op/grant_management.go |
JOSE family
| RFC | Status | Where |
|---|---|---|
| RFC 7515 JWS | partial (compact JWS surfaces used by JWT / JAR / JARM / DPoP / client assertions; general JSON serialization is not exposed) | internal/jose |
| RFC 7516 JWE | partial — closed allow-list (RSA-OAEP-256 / ECDH-ES{,+A128KW,+A256KW} × A{128,256}GCM). Inbound JWE request_object (JAR / PAR §6.1), outbound JWE id_token, JWT-shape userinfo, JARM authorization response, and RFC 9701 introspection response wired. RSA1_5 refused (CVE-2017-11424 padding oracle); RSA-OAEP-384/512, dir, symmetric-only A*KW deferred to v2+ | internal/jose, op.WithEncryptionKeyset |
| RFC 7517 JWK | partial (JWK Set publication and client JWKS consumption for supported asymmetric key types; symmetric oct keys are not accepted for signing) | internal/jwks |
| RFC 7518 JWA | partial — issuance is ES256 only; verification accepts RS256, PS256, ES256, EdDSA. HS* and none refused | internal/jose |
| RFC 7519 JWT | partial (signed / encrypted JWT surfaces used by OIDC and OAuth extensions; unsecured JWTs are refused) | internal/jose |
| RFC 7638 JWK Thumbprint | full (used by DPoP cnf.jkt) | internal/dpop |
RFC 8037 Edwards-curve DSA / EdDSA | partial (Ed25519; Ed448 not enabled) | internal/jose |
FAPI family
The FAPI2Baseline Go identifier retains the former Baseline name. The final specification is FAPI 2.0 Security Profile. The OFCS results cited here are for the named Implementer's Draft test plans; they do not establish conformity with every requirement of the final specifications. In particular, the library rotates refresh tokens, whereas Security Profile §5.3.2.1(9) allows rotation only in extraordinary circumstances. The library also accepts the token endpoint URL and array values in private_key_jwt aud; §5.3.2.1(8) requires accepting only the issuer identifier as a string. These are current Final-profile conformance gaps.
| Profile | Status | Switch |
|---|---|---|
| FAPI 2.0 Security Profile | partial (PAR, PKCE and sender-constrained tokens are implemented; this switch also requires JAR as a library choice. See the final-specification limitation above and OFCS.) | op.WithProfile(profile.FAPI2Baseline) |
| FAPI 2.0 Message Signing | partial (JAR and JARM are implemented; the final specification permits separate signing profiles and inherits the Security Profile requirements) | op.WithProfile(profile.FAPI2MessageSigning) |
| FAPI 1.0 Advanced | out | — (use FAPI 2.0) |
| FAPI-CIBA | partial (library preset: poll mode, JAR, DPoP or mTLS, a 10-minute access-token TTL ceiling, requested_expiry ≤ 600 s, and an access-token revocation path. The historical ID1 plan uses mTLS; the demo selects it explicitly. The 60-minute request-object age limit is a library constraint; see OFCS.) | op.WithProfile(profile.FAPICIBA) |
| OpenID iGov High | out | — |
The profile enumeration also carries profile.Baseline, which is not a FAPI profile: it declares the OAuth 2.1 / RFC 9700 posture and adds PKCE on every authorization-code request, including confidential clients. See Declaring a security profile.
Other RFCs the library cites
| RFC | Use |
|---|---|
| RFC 1918 | Private-network deny-list for back-channel logout SSRF defense |
| RFC 2606 | Reserved example domains in tests / examples |
| RFC 3986 | URI parsing |
| RFC 4122 | UUIDv4 generation |
| RFC 4226 | HOTP building block used by the TOTP authenticator |
| RFC 4514 | DN handling for mTLS subject DN |
| RFC 4648 | Base64url encoding |
| RFC 5280 | X.509 cert validation |
| RFC 5321 | SMTP address length bounds for email OTP inputs |
| RFC 6238 | TOTP authenticator |
| RFC 6265 | Cookie syntax |
| RFC 6711 | Authentication Context Class Reference values registry |
| RFC 7230 / 7231 / 7232 / 7235 | HTTP/1.1 (now superseded by RFC 9110) |
| RFC 7239 | Forwarded header parsing for trusted-proxy handling |
| RFC 7807 | application/problem+json (selected error paths) |
| RFC 8017 | RSA-PSS / RSA-OAEP algorithm references through JOSE |
| RFC 8141 | URN handling for PAR request_uri values |
| RFC 8176 | AMR values registry |
| RFC 8259 | JSON |
| RFC 9110 | HTTP semantics |
Out of scope by design
A handful of OIDC Core / OAuth surfaces are intentionally not implemented. The library tracks each one as a row with status: out-of-scope in the scenario catalog (test/scenarios/catalog/<feature>.yaml) so the policy is auditable alongside the tests that pin everything else.
response_typeiscodeonly. Implicit (id_token,id_token token), hybrid (code id_token, ...), andresponse_type=noneare not issued. RFC 9700 §2.1.2 deprecates the implicit grant; FAPI 2.0 mandates code. Discovery advertisesresponse_types_supported: ["code"].fragmentresponse mode is not wired. Withcode-only issuance there is nothing to put in the URL fragment.queryandform_postare both implemented (the latter renders an auto-submitting HTML form per OIDC Core Form Post Response Mode 1.0); whenfeature.JARMis on, the four*.jwtvariants are also wired. Discovery advertisesresponse_modes_supported: ["query", "form_post"]by default and appends*.jwtmodes when JARM is enabled.- Aggregated and Distributed claim types (OIDC Core §5.6.2) are not emitted. Only Normal claims are produced; the
_claim_names/_claim_sourceskeys never appear in tokens or UserInfo responses. client_secret_jwtis refused at registration. Useprivate_key_jwtinstead. The HMAC-shared-secret JWT profile is rejected withinvalid_client_metadata: token_endpoint_auth_method client_secret_jwt is not supported.- JWE alg / enc allow-list is closed. The default set is
RSA-OAEP-256+ECDH-ES{,+A128KW,+A256KW}for key-wrap andA{128,256}GCMfor content.WithSupportedEncryptionAlgscan narrow but not extend.RSA1_5is permanently rejected (CVE-2017-11424);RSA-OAEP-384/RSA-OAEP-512,dir, and symmetric-onlyA*KWare deferred to v2+. - CIBA push and ping delivery modes are not implemented. Discovery advertises
backchannel_token_delivery_modes_supported: ["poll"]exclusively so a client cannot negotiate them. - Custom-grant handlers cannot supply refresh-token values. A handler that wants refresh issuance sets
CustomGrantResponse.IssueRefreshToken; the OP mints and persists the credential through its ownRefreshTokenStore, preserving lineage, rotation, replay cascade, and DPoP / mTLS binding. If the client is not registered forrefresh_token, the access-token response still succeeds andcustom_grant.refresh_droppedrecords the omission.
Out of scope (intentional)
Not every RFC in the OAuth / OIDC sphere is the OP's responsibility. The library deliberately doesn't ship support for the following — they belong to the resource server, the client SDK, or other layers.
| RFC / Spec | Status | Notes |
|---|---|---|
| RFC 9421 — HTTP Message Signatures | out | Resource-server (API protection) concern, not OP. The OP-side equivalents are JAR (RFC 9101) for signed authorization requests, JARM for signed authorization responses, and DPoP (RFC 9449) for proof-of-possession on /token and /userinfo. RS-side HTTP signing is the embedder's responsibility. |
Verification
The list is grepped from the live source under op/ and internal/. You can audit it yourself:
git clone https://github.com/libraz/go-oidc-provider.git
cd go-oidc-provider
grep -rhoE 'RFC [0-9]+' op/ internal/ | sort -uThe list above mirrors the output of that command, with the ones that are normative-for-the-library called out and the ones that are incidental references rolled up in "Other".