feat: add token revocation (RFC 7009) - #51
Conversation
🦋 Changeset detectedLatest commit: bd6c767 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
18194af to
aeef196
Compare
aeef196 to
7927cad
Compare
| import GermConvenience | ||
| import HTTPTypes | ||
|
|
||
| extension HTTPDataResponse { |
There was a problem hiding this comment.
@germ-mark this should probably be lifted up to GermConvenience, but I didn't want to tie up this work with a change upstream
There was a problem hiding this comment.
we're about to gin up a release for germ-network/GermConvenience#32 so let's put it where it belongs
|
Huh, interesting: Bluesky's atproto codebase does use DPoP for token revocation, despite this not explicitly being in either spec. https://github.com/bluesky-social/atproto/blob/f792b919386341d0dc4dcf873506f088af61ae16/packages/oauth/oauth-provider/src/router/create-oauth-middleware.ts#L163 |
germ-mark
left a comment
There was a problem hiding this comment.
looks good, we can move the successOrThrow up to GermConvenience
… enum (RFC 7009) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
0.3.0 makes BundledHTTPRequest.request private(set) and body let, so the checks in its init cannot be undone after construction. The three sites that assigned header fields in place move to settingHeader(_:for:), which is the narrow API that replaces them. Behaviour is unchanged - each one only ever added a header. The floor bump and the migration have to land together: 0.3.0 is what breaks in-place mutation, so neither builds without the other. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Drops the local successOrThrow copy now that it lives upstream, and collapses the hand-rolled .result/.error switches in the PAR and token-endpoint paths. Verified against released 0.3.0 with a throwaway harness over PAR, the token endpoint, discovery and settingHeader: the four unchanged behaviours hold, and the two that 0.3.0 changes improve - a malformed token response now reports its own DecodingError instead of Errors.invalidRequest, and a non-OAuth error body keeps its status and bytes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ests The silent no-op when the server advertises no revocation endpoint was stated in the PR description but not in code - both public overloads now document it, along with revocation never touching local session state and refresh-token revocation being the way to end a whole grant (RFC 7009 2.1). RevocableToken is public API and now Sendable; public types get no implicit synthesis. First tests for the feature, using GermConvenienceMocks - which exists for exactly this. Covers the RFC 7009 wire format for both hints, OAuth error mapping, non-OAuth error bodies preserving status and bytes (the 0.3.0 contract), and the documented no-endpoint no-op. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
e0375d1 to
bd6c767
Compare
Summary
revocationRequest(authServerMetadata:token:)extension methods onClientAuth.Authenticablefor bothAccessTokenandRefreshTokenOAuth.RevocableTokenenum bundling the token value with itstoken_type_hint— prevents mismatched type/hint pairsTest plan
token_type_hint=refresh_tokenis sent