Skip to content

feat: RFC 9728 §5.1 — emit resource_metadata parameter in WWW-Authenticate on 401  #165

Description

@rsharath

Summary

Complete RFC 9728 support by emitting the resource_metadata parameter in the WWW-Authenticate header that ZeroID returns on 401 from bearer-protected endpoints.

The cold-start UX without this: a stock OAuth client hits a 401, has no signpost pointing at the PRM document, and has to know the well-known URL out-of-band. With it, the client follows resource_metadata="…" → PRM → AS metadata per spec.

What needs to change

Every 401 ZeroID returns from a bearer-protected endpoint includes a WWW-Authenticate value of this shape:

WWW-Authenticate: Bearer error="invalid_token",
                  error_description="…",
                  resource_metadata="{Issuer}/.well-known/oauth-protected-resource"

The error and error_description parameters stay RFC 6750 §3.1-correct — invalid_request / invalid_token / insufficient_scope — keyed off whatever the middleware already determined. The PR's only job is to append resource_metadata to every 401's WWW-Authenticate.

Estimated scope

  1. internal/handler/routes.go — helper on the API struct (uses a.issuer after PR-163 merges):
    func (a *API) prmURL() string {
        return a.issuer + "/.well-known/oauth-protected-resource"
    }
  2. internal/middleware/auth*.go — central bearer-auth middleware emits a 401 with the appended parameter. Most of the work centralizes here.
  3. Direct 401 emission sites — grep http.StatusUnauthorized in handlers/services for sites that bypass the middleware (DPoP failures, JWT signature/expiry, introspection-side rejections). Each gets the same parameter.
  4. Flip the existing pin testTestRFC9728_S5_1_WWWAuthenticateResourceMetadataNotYetEmitted in tests/integration/prm_compliance_test.go is currently a negative-pin asserting NotContains "resource_metadata=". Rename to drop NotYetEmitted, flip to assert.Contains + URL match.
  5. Add a positive-shape compliance test — parse the WWW-Authenticate value, confirm resource_metadata URL equals {Issuer}/.well-known/oauth-protected-resource, confirm RFC 6750 error field still well-formed.
  6. README standards-table — RFC 9728 row description tightens (e.g. add "+ §5.1 breadcrumb").

Verification at merge time

  • Existing TestRFC9728_S5_1_* test now expects the breadcrumb (flipped assertion).
  • New positive-shape test parses the WWW-Authenticate value end-to-end.
  • Manual curl against a protected endpoint with a bogus token returns 401 with both error="invalid_token" and resource_metadata="…" parameters; the URL resolves to a real PRM document.

References

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions