{"_id":"@api-common/spectral-api-authorization-ruleset","name":"@api-common/spectral-api-authorization-ruleset","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@api-common/spectral-api-authorization-ruleset","version":"0.1.0","description":"A curated, owned, grounded Spectral ruleset for the API Authorization Profile — lint your OpenAPI and OAuth Authorization Server metadata against OAuth 2.1 / FAPI 2.0 at two tiers (normal/high). An API Commons tool.","type":"module","license":"Apache-2.0","author":{"name":"API Evangelist","url":"https://apievangelist.com"},"homepage":"https://apicommons.org/api-authorization","repository":{"type":"git","url":"git+https://github.com/api-commons/spectral-api-authorization-ruleset.git"},"bugs":{"url":"https://github.com/api-commons/spectral-api-authorization-ruleset/issues"},"keywords":["spectral","oauth","fapi","api-authorization","api-security","dpop","ruleset","governance","openapi","oauth-metadata","linting","api-commons"],"main":"api-authorization-openapi.yaml","exports":{"./openapi":"./api-authorization-openapi.yaml","./oauth-metadata":"./api-authorization-oauth-metadata.yaml"},"engines":{"node":">=18"},"scripts":{"lint:openapi:clean":"spectral lint fixtures/openapi-clean.yaml -r api-authorization-openapi.yaml -f json","lint:openapi:bad":"spectral lint fixtures/openapi-noncompliant.yaml -r api-authorization-openapi.yaml -f json","lint:meta:clean":"spectral lint fixtures/oauth-metadata-clean.json -r api-authorization-oauth-metadata.yaml -f json","lint:meta:bad":"spectral lint fixtures/oauth-metadata-noncompliant.json -r api-authorization-oauth-metadata.yaml -f json","test":"node scripts/test-ruleset.mjs"},"devDependencies":{"@stoplight/spectral-cli":"^6.11.1"},"publishConfig":{"access":"public"},"scarfSettings":{"enabled":false},"gitHead":"d70d1288da0bc01b12605eee000d1926712b229a","_id":"@api-common/spectral-api-authorization-ruleset@0.1.0","_nodeVersion":"25.2.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-SPNXkrzgdK3ZyPRbDTQr0KxwztKNxMQLDlxPTwJP+KmUgrXeErmTub9WEjRg+C494XRwMtIr9is6ue2ajNOrrQ==","shasum":"1eb11ebe72c87b5adbe42e2d2898b504c619551d","tarball":"https://registry.npmjs.org/@api-common/spectral-api-authorization-ruleset/-/spectral-api-authorization-ruleset-0.1.0.tgz","fileCount":9,"unpackedSize":44396,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIHNmA9Xzsj1muD3t64prPncEqgH5aqSPKKRRUzhNqHPjAiEAsAG4JdE4yxS86qAzVeG0owkYfGNTcLM0lTM5aaPcnbk="}]},"_npmUser":{"name":"api-commons","email":"info@apicommons.org"},"directories":{},"maintainers":[{"name":"api-commons","email":"info@apicommons.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/spectral-api-authorization-ruleset_0.1.0_1784134433514_0.6749994298325463"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-15T16:53:53.349Z","0.1.0":"2026-07-15T16:53:53.653Z","modified":"2026-07-15T16:53:53.939Z"},"maintainers":[{"name":"api-commons","email":"info@apicommons.org"}],"description":"A curated, owned, grounded Spectral ruleset for the API Authorization Profile — lint your OpenAPI and OAuth Authorization Server metadata against OAuth 2.1 / FAPI 2.0 at two tiers (normal/high). An API Commons tool.","homepage":"https://apicommons.org/api-authorization","keywords":["spectral","oauth","fapi","api-authorization","api-security","dpop","ruleset","governance","openapi","oauth-metadata","linting","api-commons"],"repository":{"type":"git","url":"git+https://github.com/api-commons/spectral-api-authorization-ruleset.git"},"author":{"name":"API Evangelist","url":"https://apievangelist.com"},"bugs":{"url":"https://github.com/api-commons/spectral-api-authorization-ruleset/issues"},"license":"Apache-2.0","readme":"# Spectral API Authorization Ruleset\n\n**A curated, owned, grounded [Stoplight Spectral](https://github.com/stoplightio/spectral) ruleset for the [API Authorization Profile](https://apicommons.org/api-authorization) — lint your API's authorization posture against OAuth 2.1 and FAPI 2.0 at two tiers, in one line.**\n\n`@api-common/spectral-api-authorization-ruleset` turns \"we use OAuth\" into something you can **check on every commit**. It encodes a two-tier authorization profile — **`normal`** (grounded in [RFC 9700](https://datatracker.ietf.org/doc/html/rfc9700) / OAuth 2.1) and **`high`** ([FAPI 2.0](https://openid.net/specs/fapi-2_0-security-profile.html)) — as Spectral rules that use **built-in functions only** (no custom JavaScript), so it runs anywhere Spectral runs.\n\nWhy this exists: the standards for secure API authorization already exist — the problem is that almost nobody checks their API against them. This ruleset is the \"profile, don't invent\" idea made executable: every rule names the RFC or FAPI clause it enforces. It was generalized from Germany's federal [API authorization *Sicherheitsvorgaben*](https://gitlab.opencode.de/sachsen-anhalt/mid/foederale-api-autorisierungsinfrastruktur) into a standard-neutral form any API program — public or private — can adopt.\n\nOne of the [API Commons tools](https://apicommons.org/tools/), alongside [Spectral OWASP Ruleset](https://github.com/api-commons/spectral-owasp-ruleset), [Spectral Reporter](https://reporter.apicommons.org), [API Validator](https://validator.apicommons.org), and [Ruleset Commons](https://rulesets.apicommons.org).\n\n## Two lint targets, because the posture lives in two artifacts\n\nAn OpenAPI document can't carry the whole story. The FAPI-specific truth — DPoP, PAR, client-authentication methods, PKCE — lives in the authorization server's own metadata. So this package ships **two rulesets**, and you run each against the artifact it applies to:\n\n| Ruleset | Lint this artifact | Checks |\n|---|---|---|\n| `api-authorization-openapi.yaml` | your **OpenAPI** (3.x) | security scheme contract, global/operation `security`, declared scopes, transport, and the shape of OAuth flows (bans `implicit`/`password`) |\n| `api-authorization-oauth-metadata.yaml` | your **OAuth AS metadata** ([RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414) `/.well-known/oauth-authorization-server` or `/.well-known/openid-configuration`) | client auth (`private_key_jwt`/mTLS), sender-constraining (DPoP/mTLS), PAR, PKCE `S256`, response types, the mix-up `iss` parameter, signing algorithms, endpoint discovery |\n\n```sh\n# lint your OpenAPI\nspectral lint openapi.yaml -r api-authorization-openapi.yaml\n\n# lint your authorization server metadata\ncurl -s https://as.example.gov/.well-known/openid-configuration -o as-metadata.json\nspectral lint as-metadata.json -r api-authorization-oauth-metadata.yaml\n```\n\nAdopt by reference from [ruleset-commons](https://rulesets.apicommons.org) or npm and inherit updates instead of forking a frozen copy.\n\n## The floor — what this does NOT prove\n\nStatic conformance to this profile is **necessary, not sufficient**. Linting checks the **declared contract**, not the running system. It cannot verify a live DPoP proof, real token binding, a working PAR endpoint, that revocation actually revokes, or that object-/function-level authorization is correct (that is OWASP API1/API5 — use the [OWASP ruleset](https://github.com/api-commons/spectral-owasp-ruleset) alongside this one). A clean report means the contract is not leaving an obvious door open; the rest is owed to your code, your tests, and your gateway. Advertising `require_pushed_authorization_requests: true` in metadata is proof the server *claims* to require PAR — not proof it enforces it.\n\n## Tiers\n\nEvery rule is tagged `normal` or `high` in its description. `high` is a strict superset — every `normal` requirement also applies at `high`. The `high`-only rules are the FAPI-grade ones: code-only response types, the mix-up `iss` parameter, PKCE `S256`, strong client authentication, sender-constraining, PAR, and asymmetric-only signing. Run the full ruleset for a `high`-assurance API; for a `normal`-tier API, disable the `high` rules via a thin extending ruleset:\n\n```yaml\n# api-authorization-normal.yaml\nextends: [\"./api-authorization-oauth-metadata.yaml\"]\nrules:\n  authz-meta-response-types-code-only: off\n  authz-meta-iss-parameter: off\n  authz-meta-pkce-s256: off\n  authz-meta-client-auth-no-secret: off\n  authz-meta-client-auth-strong: off\n  authz-meta-sender-constraining: off\n  authz-meta-par-required: off\n  authz-meta-asym-signing: off\n```\n\n## Grounded, owned rules\n\nEvery rule carries its provenance, modelling what a governance rule *should* look like:\n\n- a stable **id** (e.g. `authz-meta-sender-constraining`)\n- a **description** naming the requirement (e.g. `SC-1 (high)`) and the risk\n- a **message** shown on each finding\n- a **severity** (`error` for MUST, `warn` for SHOULD)\n- a **documentationUrl** deep-linking the profile requirement\n\n### Rules\n\n**OpenAPI target** — `authz-transport-https-servers`, `authz-security-schemes-defined`, `authz-global-security-defined`, `authz-grant-no-implicit`, `authz-grant-no-password`, `authz-grant-types-allowed`, `authz-oauth2-https-urls`, `authz-oauth2-scopes-defined`.\n\n**OAuth AS Metadata target** — `authz-meta-issuer-https`, `authz-meta-endpoints-present`, `authz-meta-no-implicit-response-type`, `authz-meta-grant-no-password`, `authz-meta-response-types-code-only`, `authz-meta-iss-parameter`, `authz-meta-pkce-s256`, `authz-meta-client-auth-no-secret`, `authz-meta-client-auth-strong`, `authz-meta-sender-constraining`, `authz-meta-par-required`, `authz-meta-no-none-alg`, `authz-meta-asym-signing`.\n\nSee [the profile](https://apicommons.org/api-authorization) for each requirement's grounding clause (RFC / FAPI section).\n\n## Provenance\n\nRFC 9700 (OAuth 2.0 Security BCP), OAuth 2.1 (`draft-ietf-oauth-v2-1`), FAPI 2.0 Security Profile, RFC 8414 (AS Metadata), RFC 9449 (DPoP), RFC 8705 (mTLS), RFC 9126 (PAR), RFC 7636 (PKCE), RFC 9207 (`iss`), RFC 8725 (JWT BCP). Generalized from the German federal *Föderale API-Autorisierungsinfrastruktur*.\n\n## Test\n\n`npm test` lints the noncompliant + clean fixtures for both targets and asserts every expected rule fires on the noncompliant fixtures, the clean fixtures are silent, and no rule throws.\n\n## License\n\nApache-2.0 — Copyright 2026 API Commons (Kin Lane).\n","readmeFilename":"README.md","_rev":"1-ad399f92ad2f32a2fc5f21324e07112c"}