Commit Graph

80 Commits

Author SHA1 Message Date
Matthieu Sieben 5d3e248c26 Fix /.well-known/change-password page (#4880)
* Fix /account/reset-password route

* changeset

* tidy

* improve error reporting

* messages

* name all providers
2026-04-23 17:58:22 +02:00
David Buchanan c531144d24 OAuth Hooks Enhancements (#4857)
* onSignInFailed oauth hook

* plumb Account through to onSignInFailed hook

* plumb client ids through to oauth hooks

* pass sub to InvalidCredentialsError, not full Account

* defensively downgrade InvalidCredentialsError to InvalidRequestError after delivering onSignInFailed hook

* changeset

* support InvalidCredentialsError in PDS oauth store, test for enumeration attacks

* changeset

* fix test

* slight simplification
2026-04-16 02:01:12 +01:00
Matthieu Sieben 0cfb16b2bf Disable COEP headers when hCaptcha is enabled (#4855) 2026-04-15 08:58:39 +02:00
Matthieu Sieben b3ce11ae2e OAuth provider UI unification (#4820)
* refactor

* tidy

* tidy
2026-04-14 16:46:18 +02:00
Matthieu Sieben fdbbff8543 Fix validation of oauth /authorize params (#4620) 2026-02-06 19:00:34 +01:00
Matthieu Sieben 78fee144ff Throw more detailed error upon CSRF login issue (#4606)
* Throw more detailed error upon CSRF login issue

* Add cookie support detection mechanism

* lint

* tidy

* Update packages/oauth/oauth-provider-ui/cookie-error-page.html

Co-authored-by: devin ivy <devinivy@gmail.com>

* review comments

* tidy

---------

Co-authored-by: devin ivy <devinivy@gmail.com>
2026-02-06 14:20:41 +01:00
Matthieu Sieben fa4ef5e815 Fix oauth response when using prompt=select_account with no sessions available (#4569)
* Fix oauth response when using `prompt=select_account` and no session are available

Fixes #4566

* allow the account to be pre-selected when `prompt=login`
2026-01-20 09:32:09 +01:00
Emelia Smith 5d8e7a6588 Support initiating user registration via OAuth flow with prompt=create (#4461)
* Add prompt_values_supported to Authorization Server Metadata

* Expose prompt_values_supported in Authorization Server Metadata

* Support selecting view in oauth-provider-ui based on prompt parameter

* Support initiating user registration via prompt=create

* Add support to OAuth Client Browser Example for prompt=create

* Add test coverage for prompt=create
2025-12-17 14:57:16 +01:00
Matthieu Sieben 8012627a12 Migrate OAuth libs to new @atproto/lex utils (#4383)
* Migrate Oauth libs to new @atproto/lex utils

* pnpm-lock

* tidy

* fix

* tidy

* tidy

* tidy

* tidy

* Implement lex resolution logging through hooks
2025-12-01 12:24:01 +01:00
Matthieu Sieben be8e6c1f25 Permission-sets pre-release changes (#4382)
* Remove ability to define `blob` permission in permission sets

* Disallow `rpc` permissions with specific `aud` in permission-sets

* Add `toScopes()` utility on `IncludeScope`

* tidy
2025-11-25 19:51:02 +01:00
Matthieu Sieben f496fa2c4d Set dark background on authorization pages <body> in dark mode (#4301)
* Set dark background on authorization pages `<body>` in dark mode

* tidy
2025-10-24 16:17:46 +02:00
Matthieu Sieben 8ff5ec4caa OAuth client validation improvements (#4289)
* OAuth client validation improvements

* Remove `isLocalHostname` export

* tidy
2025-10-24 12:53:03 +02:00
Matthieu Sieben 1e702ea675 Add account data in pwd reset hooks (#4265)
* Add account data in pwd reset hooks

* tidy

* tidy

* tidy
2025-10-24 12:50:34 +02:00
Matthieu Sieben 8c03d75b6c Remove un-implemented introspect endpoint from OAuth Server metadata (#4293)
Remove un-implemented `introspect` endpoint from OAuth Authorization Server metadata
2025-10-24 12:10:37 +02:00
Aaron Parecki dca500186e update links to ietf docs (#4273) 2025-10-14 14:43:01 -07:00
Matthieu Sieben e71d265dd4 Minor oauth jwk tweaks (#4256)
* Minor oauth jwk changes

* tidy
2025-10-06 15:45:05 +02:00
Matthieu Sieben 7351589a31 Add onResetPasswordRequest and onResetPasswordConfirm hooks (#4217) 2025-09-22 19:38:38 +02:00
Matthieu Sieben cf4117966c Fix call to onDecodeToken oauth verifier hook (#4191)
* Make `DpopProof` readonly

* Improve token verification error details

* Always log warnings when DPOP proof `htu` contains # or ?.

* Add missing initialization of `onDecodeToken` hook

* Add logging around scope dereferencing operations
2025-09-09 15:56:32 +02:00
Matthieu Sieben 8914f9abde Allow encoding scope claims of oauth access token JWT (#4149)
* Refactor token decoding

* Add scope decoder to pds

* tidy

* tidy

* tidy

* tidy

* review changes

* Add scope normzlization utility

* wording in lexicon

* Add specific error

* style

* tidy

* Update `AccessTokenMode` enum values to be more meaningful

* tidy

* Update .changeset/brown-boxes-bow.md

Co-authored-by: devin ivy <devinivy@gmail.com>

* Add retry strategy

* lint

* lint

---------

Co-authored-by: devin ivy <devinivy@gmail.com>
2025-09-09 12:13:34 +02:00
Matthieu Sieben d54d278abd Allow unexpected error to go through when fetching permission sets (#4155)
* Allow unexpected error to go through when fetching permission sets

* Log `cid` as string after succesful lexicon resolution

* Log `cid` and `uri` as string on successful lexicon resolution
2025-08-30 15:26:28 +02:00
Matthieu Sieben f9dc9aa4c9 Permission set (#4108)
* Export constants and type assertion utilities

* Add permission set support to oauth provider

* improve permission set parsing

* Rename `PermissionSet` to `ScopePermissions`

* Improve performance of NSID validation

* Add support for `permission-set` in lexicon document

* Validate NSID syntax using `@atproto/syntax`

* Export all types used in public interfaces (from `lexicon-resolver`)

* Small performance improvement

* Rework scope parsing utilities to work with Lexicon defined permissions

* file rename

* fixup! Rework scope parsing utilities to work with Lexicon defined permissions

* removed outdated comment

* removed outdated comment

* fix comment typo

* Improve `SimpleStore` api

* permission-set NSID auth scopes

* Remove dev dependency on dev-env

* fix build script

* pnpm-lock

* Improve fetch-node unicast protection

* Explicitly set the `redirect: "follow"` `fetch()` option

* Add delay when building oauth-provider-ui in watch mode

* Remove external dependencies from auth-scopes

* Add customizable lexicon authority to pds (for dev purposes)

* fix pds migration

* update permission-set icon

* Add support for `include:` syntax in scopes

* tidy

* Renaming of "resource" concept to better reflect the fact that not all oauth scope values are about resources

* changeset

* ui improvmeents

* i18n

* ui imporvements

* add `AtprotoAudience` type

* Enforce proper formatting of audience (atproto supported did + fragment part)

* tidy

* tidy

* tidy

* fix ci ?

* ci fix ?

* tidy ?

* Apply consistent outline around focusable items

* Use `inheritAud: true` to control `aud` inheritance

* Update packages/oauth/oauth-provider/src/lexicon/lexicon-manager.ts

Co-authored-by: devin ivy <devinivy@gmail.com>

* Review comments

* Add `nsid` property to `LexiconResolutionError`

* improve nsid validation

* i18n

* Improve oauth scope parsing

* Simplify lex scope parsing

* tidy

* docs

* tidy

* ci

* Code simplification

* tidy

* improve type safety

* improve deps graph

* naming

* Improve tests and package structure

* Improve error when resolving a non permission-set

* improve nsid parsing perfs

* benchmark

* Refactor ozone and lexicon into using a common service profile mechanism

* improve perfs

* ci fix (?)

* tidy

* Allow storage of valid lexicons in lexicon store

* Improve handling of lexicon resolution failures

* review comment

* Test both regexp and non regexp based nsid validation

* properly detect presence of port number in https did:web

* Re-enable logging of `safeFetch` requests

* tidy

---------

Co-authored-by: devin ivy <devinivy@gmail.com>
2025-08-29 12:19:19 +02:00
Matthieu Sieben 832866c33b Enforce stronger validation of jwks loaded through their own uri (#4100)
* Enforce stronger validation of jwks loaded through their own uri

* add some docs
2025-08-13 09:45:23 +02:00
Matthieu Sieben 1899b1fc16 OAuth scopes (#3806)
* style: prefix `id` and `uri` with `request` where applicable

* Dynamically validate OAuth scopes

* Allow configuring trusted OAuth clients

* Improve client validation

* Rework authorization to work with permissions

* Review changes

* fix permissions

* tidy

* Drop authorization result

* unused code cleanup

* fix preferences auth

* remove redundant check in `applyWrites`

* style

* Remove need to specify "scopes" in authorized auth strategy

* fixup! Remove need to specify "scopes" in authorized auth strategy

* split authorized and oauth auth methods

* Require explicit opt-in for takendown

* fix tests

* rollback redundant permissions mechanism

* tidy

* Fix tests

* tidy

* tidy

* pr changes

* remove hack allowing access to full preferences

* always specify authorize method

* Add OAuth scope parsing & matching

* tidy

* add support for oauth scopes in client

* review changes

* Small xrpc-server optimizations

* pr comments

* Review comments

* refactor: move oauth scopes parser & checker in own package

* code simplification

* Allow multiple collections in `repo` scopes.
Allow wildcard action in `repo` scopes.
Require action in `repo` scopes.

* Rename `emailUpdate` to `email-update` in `account` scope params.
Add wildcard (`*`) in `account` and `identity` scopes.

* tidy

* add oauth-scopes package to PDS Dockerfile

* unit tests

* Syntax rework

* adapt to latest scope definition

* Add missing tests

* Render scopes in UI

* fix build

* fixes and tests

* improve ui

* tidy

* tidy

* ui improvements

* tidy

* fr messages

* tidy

* improve consent screen ui

* fix test

* tidy

* improve dx

* Remove `transition:` scopes from `scopes_supported` authorization server metadata

* Hide blob scope if no repo scope present

* changeset

* Remove the `action` param from the `identity` scope

* fix html syntax

* simplified wording

* Make `account:email` scope optional (#4089)

* Make `account:email` scope optional

* tidy

* tidy

* tidy

* tidy

* fix

* tidy

* review comments

* tidy

* refactor: remove redundant tests for identity scope parsing and matching

* minor ui fixes

* fix "back" label not translated

* ui improvements

* fix tests
2025-08-12 13:13:14 +02:00
Matthieu Sieben f792b91938 Improve error reporting and logging (#3953)
* Improve error reporting and logging

* tidy

* tidy

* Improve zod error message extraction

* Properly serialize request in oauth logger

* Improve formatting of Zod errors

* Restore logging of refresh errors

* tidy

* Avoid double logging of errors

* tidy

* tidy

* revert merge changes

* tidy

* tidy

* more tidy
2025-06-23 19:49:10 +02:00
Matthieu Sieben 3a1e010e14 OAuth: Improve error reporting (#3973)
* Fix authorization error type name

* Refactor authorization error handling: replace AccessDeniedError with AuthorizationError and improve error reporting
2025-06-23 18:30:33 +02:00
Matthieu Sieben 90b4775fc9 Re-export all types & utilities needed to instantiate an OAuth client (#3976)
* Re-export all types & utilities needed to instantiate an OAuth client

* Add `jwkPrivateSchema` to ensure a key is private

* Return object instead of array as result of `findPrivateKey`

* Allow override of default `handleResolver` and `runtimeImplementation` options for NodeOAuthClient

* changeset

* Allow `OAuthClient` to be instantiated with custom `didResolver` instance
2025-06-19 19:27:38 +02:00
Matthieu Sieben 68c43a94bd Fix invalid use of invalid_client (#3967) 2025-06-18 15:46:32 +02:00
Matthieu Sieben 7d9808ca81 Allow HTTPS redirect_uris from any origin (#3811) 2025-06-14 14:30:24 +02:00
Matthieu Sieben e27d908454 Increase oauth session & refresh token lifetimes (#3883) 2025-06-14 14:25:11 +02:00
Matthieu Sieben 349b59175e Properly validate auth during refresh (#3847)
* Ensure that the credentials used during a refresh correspond to those used to create the OAuth tokens.

* tidy

* Bind the OAuth session to the kid that was used to authenticate the client (private_key_jwt)

* Store the whole authentication method in the client session store rather than the kid only

* tidy

* Improve error reporting in case an invalid `token_endpoint_auth_method` is used in the client metadata document.

* tidy

* tidy

* Improve JAR checks

* tidy

* changeset

* tidy

* Remove schema's `.optional()` modifier when a `.default()` is defined

* tidy

* verify client auth during code exchange

* tidy

* Minor naming improvement

* tidy

* Update .changeset/quiet-pans-fix.md

Co-authored-by: devin ivy <devinivy@gmail.com>

* Update packages/oauth/oauth-client/src/oauth-client-auth.ts

* Use `private_key_jwt` instead of incorrect `client_secret_jwt` as authentication method for confidential clients

* style

* code split

* dead code removal

* Represent missing client auth with a `null` instead of "none" when storing request data.

* Allow storing `null` in authorization_request's `clientAuth` json column

* document

* tidy

* Remove non-standard behavior that allowed client to authenticate through JAR

* Improved error messages

* Parse JSON encoded Authorization Request Parameters

* Use `application/x-www-form-urlencoded` content instead of JSON for OAuth requests

Fixes: #3723

* tidy

* tidy

* tidy

* tidy

* code style

* remove un-necessary checks

* tidy

* Pre-process number too

* improved type checking

* add missing exports

* fix merge conflict

* tidy

* Remove invalid default for `code_challenge_method` authorization request parameter

* tidy

* Delete inaccurate changeset

* PR comment

* tidy

* Update OAuth client credentials factory to return headers and payload separately.

* tidy

* Renamed `clientAuthCheck` to `validateClientAuth`

* Validate presence of DPoP proofs sooner when processing token requests.

Fixes: #3859

* Protect against concurrent use of request code

* tidy

* tidy

* Update packages/oauth/oauth-provider/src/client/client.ts

Co-authored-by: devin ivy <devinivy@gmail.com>

* Review comments

* Add missing `exp` claim in client attestation JWT

* fixup! Review comments

* Review comments

* Refactor: explicit optionality of unsigned JAR issuer & audience

* Use client attestation's `exp` claim to determine the life time of JWT's `jti` nonce.

* Fix PDS: consumeRequestCode should delete request data

* tidy

* tidy

* Unused code removal

* Restore "Native clients must authenticate using "none" method" check

* tidy

* tidy

* cleanup

* comment

* Allow missing DPoP header during PAR request if `dpop_jkt` is provided

* tidy

---------

Co-authored-by: devin ivy <devinivy@gmail.com>
2025-06-12 15:10:17 +02:00
Matthieu Sieben 192f3ab89c Improve login_hint handling (#3933)
* Return atproto handle in identity resolution result

* Use resolved handle or did instead of raw input as "login_hint"

* Normalize and validate `login_hint` in oauth request properties
2025-06-10 11:57:49 +02:00
Matthieu Sieben 3fa2ee3b6a Deprecate query & fragment in DPoP proof htu claim (#3879)
* Properly validate JWK `htu` claim by enforcing URL without query or fragment

* type fix

* Return DPoP validation result from `authenticateRequest`

* Log clients using invalid "htu" claim in DPoP proof

* review comments

* fix lint

* tidy

* rename dpop result to dpop proof
2025-06-05 14:46:51 +02:00
Matthieu Sieben 06bf684a4a Add max length limit to passwords (#3900)
* Add max length limit to passwords

* review changes
2025-05-29 14:15:45 +02:00
Johannes Andersen ba293da9fe feat: password reset discovery and sign-in/up autofill (#3888)
* feat: password reset discovery and sign-in/up autofill

* chore: update translation files
2025-05-26 13:42:54 +02:00
Matthieu Sieben 43861a452b Remove dependency on the Public Suffix List (#3818)
* Remove dependency on the Public Suffix List

* tidy
2025-05-20 14:01:10 +02:00
devin ivy d794b06763 Revert hcaptcha COEP requirements (#3783)
* Revert "Use more secure COEP header when hCaptcha is enabled (#3755)"

This reverts commit 96de2acb30.

* changeset
2025-04-18 17:12:54 -04:00
Matthieu Sieben 30f9b6690e OAuth Provider account page fixes (#3764)
* Allow `:` chars in url path parts

* Allow customizing contrast and hue colors

* Allow customizing contrast and hue colors

* Use white as primary contrast color

* Fix buttons alignment and labels in "My Devices" section

* Add a `<title>` tag to all pages

* Properly display the "lastSeenAt" date

* Improve display of clients & devices

* tidy

* code split

* Add definition for `ConventionalOAuthClientId`

* Remove hard coded `client_name` from loopback client metadata

* Code factorization

* Fix `<title>` of branding page
2025-04-18 11:04:34 +02:00
Matthieu Sieben 96de2acb30 Use more secure COEP header when hCaptcha is enabled (#3755)
Refs: https://github.com/hCaptcha/react-hcaptcha/issues/259
2025-04-17 11:02:32 +02:00
Matthieu Sieben 1e461eab03 Fix missing dist files from @atproto/oauth-provider-ui (#3754)
* Remove reference to missing "bin" executable

* Remove "dependency" on `rollup-plugin-bundle-manifest`

* Fix dependencies

* Explicit exported package `files`

* Update pnpm lock
2025-04-16 10:25:29 +02:00
Matthieu Sieben 371e04aad2 Account management page (#3659)
---------

Co-authored-by: Eric Bailey <git@esb.lol>
2025-04-15 17:15:27 +02:00
Matthieu Sieben 9b28184cb9 Expose hcaptcha tokens in hook and errors (#3690)
* Expose hcaptcha tokens in hook and errors

* remove hostname check in hcaptcha
2025-03-28 14:37:39 +01:00
Matthieu Sieben 98d8a677ca Add OAuth HCaptcha hooks (#3688) 2025-03-28 11:04:12 +01:00
Matthieu Sieben a5a760c1f0 Allow null hostname in hcaptcha result (#3681) 2025-03-27 16:46:21 +01:00
Johannes Andersen 42807cad56 fix(oauth-provider): hCaptcha error codes should be optional (#3656)
* fix(oauth-provider): hCaptcha error codes should be optional

* fix: hostname can be nullable

* fix: add changesets
2025-03-21 09:17:51 +01:00
Matthieu Sieben 49528e83da OAuth: Allow onSignedUp hook to access hcaptcha result data (#3645)
* OAuth: Allow `onSignedUp` hook to access hcaptcha result data

* OAuth hcatpcha fixes

* Update .changeset/slimy-flowers-punch.md

Co-authored-by: devin ivy <devinivy@gmail.com>

---------

Co-authored-by: devin ivy <devinivy@gmail.com>
2025-03-20 14:57:54 +01:00
Matthieu Sieben cc4122652e Split OAuth Provider's ui into its own package (#3640)
* Split OAuth Provider's ui into its own package

* Create distinct entry files for authorization and error pages
2025-03-19 09:19:27 +01:00
Matthieu Sieben 9332c0f315 Set COEP header to "unsafe-none" when hcaptcha is enabled (#3627)
* Set "Cross-Origin-Embedder-Policy" header to "unsafe-none" when hcaptcha is enabled

Fixes #3625

* tidy

* tidy
2025-03-11 13:32:53 -04:00
Matthieu Sieben 5ada66ceb9 OAuth sign-up fixes (#3621)
Allow invite codes in any format
2025-03-10 15:43:11 +01:00
Matthieu Sieben 9e3eace8f9 Validate OAuth sign-up handle using @atproto/syntax (#3622)
* Validate OAuth sign-up handle using @atproto/syntax

Fixes #3619

* Improve input validation
2025-03-10 14:58:35 +01:00
Matthieu Sieben 8827ff433a Improve parsing of colors (#3614)
* improve branding parsing

* Fix build

* tidy
2025-03-07 20:46:15 +01:00