64 Commits

Author SHA1 Message Date
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 96de2acb301683effe4313cb93d7747f87a73b5e.

* 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
Matthieu Sieben
c01d7f5d15
Make branding colors optional (#3611) 2025-03-07 14:08:52 -05:00
Matthieu Sieben
850e39843c
OAuth: Reset password & Sign-up (#2945)
* Adds "password reset" during OAuth flows
* Adds "Sign up" during OAuth flows
* Adds support for multiple languages in the OAuth flow
* Adds "fr" translation for the OAuth flow

Co-authored-by: devin ivy <devinivy@gmail.com>
Co-authored-by: Eric Bailey <git@esb.lol>
2025-03-07 09:41:06 +01:00
Matthieu Sieben
82d5a2d361
OAuthProvider: Update "trustProxy" options to allow function (#3557)
* OAuthProvider: Update "trustProxy" options to allow function

* DeviceManager options can now be passed as argument to the OAuthProvider constructor

* Only trust one level of proxying when computing IP during OAuthFlows

* Prevent invalid use of trustProxy config

* tidy

* make the code compliant with legacy behavior
2025-02-24 17:12:16 -05:00
Matthieu Sieben
bde6f71c4c
Mark "userAgent" as optional in RequestMetadata (#3538) 2025-02-14 14:20:18 +01:00
Matthieu Sieben
e69e89a037
Properly compute sleep time in contantTime util (#3514) 2025-02-14 09:53:53 +01:00
Matthieu Sieben
6ea9c961af
Rework of authorization request hooks (#3525)
* Rework of authorization request hooks

* add device details to `onAuthorized` hook

* Expose port number in DeviceDetails, allow passing options to DeviceManager

* tidy

* tidy

* tidy

* tidy

* changeset

* Expose client request metadata in hooks

* tidy

* tidy

* docs
2025-02-14 09:38:57 +01:00
Matthieu Sieben
61dc0d60e1
Add linting rule to sort imports (#3220)
* Add linting rule to sort imports

* remove spacing between import groups

* changeset

* changeset

* prettier config fine tuning

* forbid use of deprecated imports

* tidy
2025-02-05 15:06:58 +01:00
Matthieu Sieben
b04943191b
Add description for transition:* scopes (#3432) 2025-01-23 11:01:37 +01:00
Matthieu Sieben
c5a4cdb0a5
Improve error description in case invalid DPoP nonce is used (#3415) 2025-01-22 11:17:20 +01:00
Matthieu Sieben
2889c76995
Improve type safety and compatibility with Bun (#2879)
* jwk: Improve type safety and compatibility with Bun
* improve type safety of jwk keys
* improve typing of verifyAccessToken
* update @types/http-errors
* Better report invalid content-encoding errors
* Mark jwk key fields as readonly
2025-01-09 14:26:07 +01:00
Matthieu Sieben
6226546725
Improve messaging of client metadata loading errors (#3135)
* Improve messaging of client metadata loading errors

Fixes #3096

* Support parsing of more fetch() errors
2024-11-29 16:05:58 +01:00
Matthieu Sieben
5ddd51235c
OAuth url scheme validation (#3066)
* Improve message of OAuthResolverError in case of metadata validation error

* Use named export from zod

* docs

* Enforce use of http and https url where applicable

* Verify authorization_endpoint URL protocol

* fix pds tests for new oauth resource metadata check

* Allow non-https urls as resource metadata url

* Strong validation or redirect_uri

* Ensure that client-id is a web url

* explicit use of "url" schema as potentially dangerous

* changeset

* tidy

* simplify type

* prevent loopback hostname for https: redirect uris

* Forbid use of non https internet uris

* allow "localhost" for web uris

* tidy

* tidy

* tidy

---------

Co-authored-by: Devin Ivy <devinivy@gmail.com>
2024-11-25 01:51:33 -05:00
Matthieu Sieben
709ba30157
Properly negotiate response content-encoding (#2852)
* Properly negotiate response content-encoding

* negotiate acceptable encoding and type before building responses

* remove un-necessary async

* typo

* Remove response content-encoding logic

* Avoid using chunked encoding when writing a buffer to the response
2024-11-04 09:40:33 +01:00
David Wood
c36456f0ba
chore: add missing symbol in comment (#2913) 2024-10-28 08:59:49 +01:00
Matthieu Sieben
8f2b80a0dc
Better report invalid content-encoding errors (#2902) 2024-10-21 14:22:29 +02:00
Matthieu Sieben
9d40ccbb69
Various OAuth related fixes (#2871)
* wip

* tidy

* tidy

* tidy

* Update packages/oauth/oauth-client/src/session-getter.ts

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

* fix combineSignals

* tidy

* tidy

* improve typing of atprotoScopeSchema

* stronger typings

* tidy

* ci

* Fix cors error

* downgrade ioredis dependency

* fix ioredis version

* tidy

---------

Co-authored-by: devin ivy <devinivy@gmail.com>
2024-10-18 20:23:33 +02:00