API Authorization Profile
Most API programs assert "we use OAuth" and stop there. This profile says which OAuth — a small set of requirements you can check against the artifacts an API already publishes, at two assurance tiers, so conformance is a CI lint instead of an annual review. It follows the profile, don't invent posture: every requirement grounds in an existing IETF or OpenID standard. Generalized from Germany's federal API authorization security profiles into a standard-neutral form any API program — public or private — can adopt.
normal — the baseline
Grounded in RFC 9700 (OAuth 2.0 Security BCP) and OAuth 2.1 hardening: HTTPS everywhere, no implicit or password grants, declared scopes, security on every operation, no none signing algorithm. The default for any API using OAuth.
high — FAPI 2.0
A strict superset grounded in the FAPI 2.0 Security Profile: sender-constrained tokens (DPoP or mTLS), private_key_jwt/mTLS client authentication, Pushed Authorization Requests, PKCE S256, code-only response types, asymmetric signing. For high-assurance, cross-boundary, or machine-to-machine-at-scale APIs.
Two lint targets
The posture lives in two artifacts, so conformance is checked against both. Your OpenAPI carries the security-scheme contract, global and operation security, declared scopes, and the shape of OAuth flows. Your OAuth Authorization Server metadata (RFC 8414) carries the FAPI-specific truth: client authentication, DPoP, PAR, PKCE, response types, and signing algorithms.
Executable, not aspirational
The profile ships as @api-common/spectral-api-authorization-ruleset — two Spectral rule files using built-in functions only, so they run anywhere Spectral runs, with fixtures and a passing test harness. Adopt it by reference from Ruleset Commons and lint on every commit.
An honest floor
Static conformance is necessary, not sufficient. It checks the declared contract, not the running system — it cannot verify a live DPoP proof, real token binding, or that object-level authorization is correct (that is the OWASP ruleset). A clean report means the contract is not leaving an obvious door open; the rest is owed to your code, tests, and gateway.
Lint your API
spectral lint openapi.yaml -r api-authorization-openapi.yaml
# lint your authorization server metadata
curl -s https://as.example.gov/.well-known/openid-configuration -o as-metadata.json
spectral lint as-metadata.json -r api-authorization-oauth-metadata.yaml