diff --git a/.changeset/oauth-confidential-clients.md b/.changeset/oauth-confidential-clients.md deleted file mode 100644 index c340f55..0000000 --- a/.changeset/oauth-confidential-clients.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -'@pdsjs/core': minor ---- - -Support confidential OAuth clients (`private_key_jwt`). - -The authorization server previously only supported public clients — its metadata -advertised `token_endpoint_auth_methods_supported: ['none']` and it never -authenticated a client. Most real atproto apps (Tangled, statusphere, …) are -confidential clients that authenticate with a `client_assertion` JWT, so they -rejected the server at metadata validation. - -The AS metadata now advertises `private_key_jwt` (with -`token_endpoint_auth_signing_alg_values_supported: ['ES256']`) and -`require_pushed_authorization_requests: true`, matching the atproto profile. The -`client_assertion` is verified per RFC 7523 at PAR, the authorization_code token -exchange, and refresh: the client's key is resolved from its published `jwks` or -`jwks_uri`, the ES256 signature is checked, and `iss`/`sub` must be the -`client_id`, `aud` must name this server, the assertion must be unexpired and -recent, carry a `kid`, and present a `jti` that has not been replayed. Public -clients (`none`) are unchanged — PKCE and DPoP carry them. diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 0a6a81f..ea7cfbb 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -46,6 +46,20 @@ domain must already resolve to the DID via a `_atproto` DNS TXT record or the HTTPS well-known before it is adopted. +- bd768b9: Support confidential OAuth clients (`private_key_jwt`). + + The authorization server previously only supported public clients, so + confidential atproto apps (Tangled, statusphere, …) that authenticate with a + `client_assertion` JWT rejected it at metadata validation. The AS metadata now + advertises `private_key_jwt` (with ES256) and + `require_pushed_authorization_requests: true`, matching the atproto profile, and + the `client_assertion` is verified per RFC 7523 at PAR, the authorization_code + token exchange, and refresh: the client's key is resolved from its `jwks` or + `jwks_uri`, the ES256 signature is checked, and `iss`/`sub` must be the + `client_id`, `aud` must name this server, and the assertion must be unexpired, + recent, carry a `kid`, and present a non-replayed `jti`. Public clients keep + working on PKCE + DPoP. + ## 2.0.0 ### Minor Changes