@atproto/oauth-provider 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/dist/metadata/build-metadata.d.ts +1 -0
- package/dist/metadata/build-metadata.d.ts.map +1 -1
- package/dist/metadata/build-metadata.js +9 -0
- package/dist/metadata/build-metadata.js.map +1 -1
- package/dist/request/request-manager.d.ts +2 -2
- package/dist/request/request-manager.d.ts.map +1 -1
- package/dist/request/request-manager.js +5 -2
- package/dist/request/request-manager.js.map +1 -1
- package/dist/router/assets/send-authorization-page.d.ts.map +1 -1
- package/dist/router/assets/send-authorization-page.js +1 -0
- package/dist/router/assets/send-authorization-page.js.map +1 -1
- package/package.json +10 -10
- package/src/metadata/build-metadata.ts +10 -0
- package/src/request/request-manager.ts +5 -2
- package/src/router/assets/send-authorization-page.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @atproto/oauth-provider
|
|
2
2
|
|
|
3
|
+
## 0.15.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#4461](https://github.com/bluesky-social/atproto/pull/4461) [`5d8e7a6`](https://github.com/bluesky-social/atproto/commit/5d8e7a6588fc9e57e15d83d47bb45103205e3e41) Thanks [@ThisIsMissEm](https://github.com/ThisIsMissEm)! - Expose prompt_values_supported in Authorization Server Metadata
|
|
8
|
+
|
|
9
|
+
- [#4461](https://github.com/bluesky-social/atproto/pull/4461) [`5d8e7a6`](https://github.com/bluesky-social/atproto/commit/5d8e7a6588fc9e57e15d83d47bb45103205e3e41) Thanks [@ThisIsMissEm](https://github.com/ThisIsMissEm)! - Support initiating user registration via prompt=create
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [[`95ef3c2`](https://github.com/bluesky-social/atproto/commit/95ef3c24e8072e9d49412950b033cb8607764ee0), [`5d8e7a6`](https://github.com/bluesky-social/atproto/commit/5d8e7a6588fc9e57e15d83d47bb45103205e3e41), [`5d8e7a6`](https://github.com/bluesky-social/atproto/commit/5d8e7a6588fc9e57e15d83d47bb45103205e3e41)]:
|
|
14
|
+
- @atproto/oauth-types@0.6.0
|
|
15
|
+
- @atproto/oauth-provider-ui@0.4.0
|
|
16
|
+
- @atproto/lex-resolver@0.0.6
|
|
17
|
+
- @atproto/common@0.5.4
|
|
18
|
+
- @atproto/lex-document@0.0.6
|
|
19
|
+
- @atproto/oauth-provider-api@0.3.5
|
|
20
|
+
- @atproto/oauth-provider-frontend@0.2.6
|
|
21
|
+
|
|
22
|
+
## 0.14.1
|
|
23
|
+
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- Updated dependencies [[`d551b0e`](https://github.com/bluesky-social/atproto/commit/d551b0e3527714c111c3ec6e4c90ad7f46369fab)]:
|
|
27
|
+
- @atproto/lex-document@0.0.5
|
|
28
|
+
- @atproto/common@0.5.3
|
|
29
|
+
- @atproto/lex-resolver@0.0.5
|
|
30
|
+
|
|
3
31
|
## 0.14.0
|
|
4
32
|
|
|
5
33
|
### Minor Changes
|
|
@@ -7,6 +7,7 @@ export type CustomMetadata = {
|
|
|
7
7
|
/**
|
|
8
8
|
* @see {@link https://datatracker.ietf.org/doc/html/rfc8414#section-2}
|
|
9
9
|
* @see {@link https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata}
|
|
10
|
+
* @see {@link https://openid.net/specs/openid-connect-prompt-create-1_0.html}
|
|
10
11
|
*/
|
|
11
12
|
export declare function buildMetadata(issuer: OAuthIssuerIdentifier, keyset: Keyset, customMetadata?: CustomMetadata): OAuthAuthorizationServerMetadata;
|
|
12
13
|
//# sourceMappingURL=build-metadata.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-metadata.d.ts","sourceRoot":"","sources":["../../src/metadata/build-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AACrC,OAAO,EACL,gCAAgC,EAChC,qBAAqB,EAEtB,MAAM,sBAAsB,CAAA;AAI7B,MAAM,MAAM,cAAc,GAAG;IAC3B,qCAAqC,CAAC,EAAE,MAAM,EAAE,CAAA;IAChD,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC/B,CAAA;AAED
|
|
1
|
+
{"version":3,"file":"build-metadata.d.ts","sourceRoot":"","sources":["../../src/metadata/build-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AACrC,OAAO,EACL,gCAAgC,EAChC,qBAAqB,EAEtB,MAAM,sBAAsB,CAAA;AAI7B,MAAM,MAAM,cAAc,GAAG;IAC3B,qCAAqC,CAAC,EAAE,MAAM,EAAE,CAAA;IAChD,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC/B,CAAA;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,qBAAqB,EAC7B,MAAM,EAAE,MAAM,EACd,cAAc,CAAC,EAAE,cAAc,GAC9B,gCAAgC,CAqHlC"}
|
|
@@ -7,6 +7,7 @@ const crypto_js_1 = require("../lib/util/crypto.js");
|
|
|
7
7
|
/**
|
|
8
8
|
* @see {@link https://datatracker.ietf.org/doc/html/rfc8414#section-2}
|
|
9
9
|
* @see {@link https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata}
|
|
10
|
+
* @see {@link https://openid.net/specs/openid-connect-prompt-create-1_0.html}
|
|
10
11
|
*/
|
|
11
12
|
function buildMetadata(issuer, keyset, customMetadata) {
|
|
12
13
|
return oauth_types_1.oauthAuthorizationServerMetadataValidator.parse({
|
|
@@ -66,6 +67,14 @@ function buildMetadata(issuer, keyset, customMetadata) {
|
|
|
66
67
|
'touch',
|
|
67
68
|
// 'wap', LoL
|
|
68
69
|
],
|
|
70
|
+
// https://openid.net/specs/openid-connect-prompt-create-1_0.html
|
|
71
|
+
prompt_values_supported: [
|
|
72
|
+
'none',
|
|
73
|
+
'login',
|
|
74
|
+
'consent',
|
|
75
|
+
'select_account',
|
|
76
|
+
'create',
|
|
77
|
+
],
|
|
69
78
|
// https://datatracker.ietf.org/doc/html/rfc9207
|
|
70
79
|
authorization_response_iss_parameter_supported: true,
|
|
71
80
|
// https://datatracker.ietf.org/doc/html/rfc9101#section-4
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-metadata.js","sourceRoot":"","sources":["../../src/metadata/build-metadata.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"build-metadata.js","sourceRoot":"","sources":["../../src/metadata/build-metadata.ts"],"names":[],"mappings":";;AAmBA,sCAyHC;AA3ID,sDAI6B;AAC7B,mDAA4C;AAC5C,qDAAoD;AAOpD;;;;GAIG;AACH,SAAgB,aAAa,CAC3B,MAA6B,EAC7B,MAAc,EACd,cAA+B;IAE/B,OAAO,uDAAyC,CAAC,KAAK,CAAC;QACrD,MAAM;QAEN,gBAAgB,EAAE;YAChB,SAAS;YAET,yEAAyE;YACzE,kCAAkC;YAClC,kBAAkB;YAClB,oBAAoB;YACpB,sBAAsB;YAEtB,gEAAgE;SACjE;QACD,uBAAuB,EAAE;YACvB,EAAE;YACF,QAAQ,EAAE,6CAA6C;YACvD,+DAA+D;SAChE;QACD,wBAAwB,EAAE;YACxB,QAAQ;YACR,MAAM;YACN,WAAW;YAEX,SAAS;YACT,UAAU;YACV,yBAAyB;YACzB,mBAAmB;YACnB,gBAAgB;YAChB,oBAAoB;YACpB,cAAc;SACf;QACD,wBAAwB,EAAE;YACxB,mFAAmF;YACnF,OAAO;YACP,UAAU;YACV,0FAA0F;YAC1F,WAAW;SACZ;QACD,qBAAqB,EAAE;YACrB,EAAE;YACF,oBAAoB;YACpB,eAAe;SAChB;QACD,gCAAgC,EAAE;YAChC,sGAAsG;YACtG,MAAM;YAEN,iCAAiC;YACjC,WAAW;SACZ;QACD,oBAAoB,EAAE;YACpB,EAAE;YACF,OAAO;SACR;QACD,wBAAwB,EAAE;YACxB,EAAE;YACF,MAAM;YACN,OAAO;YACP,OAAO;YACP,aAAa;SACd;QAED,iEAAiE;QACjE,uBAAuB,EAAE;YACvB,MAAM;YACN,OAAO;YACP,SAAS;YACT,gBAAgB;YAChB,QAAQ;SACT;QAED,gDAAgD;QAChD,8CAA8C,EAAE,IAAI;QAEpD,0DAA0D;QAC1D,2CAA2C,EAAE,CAAC,GAAG,wBAAY,EAAE,MAAM,CAAC;QACtE,8CAA8C,EAAE,EAAE,EAAE,OAAO;QAC3D,8CAA8C,EAAE,EAAE,EAAE,OAAO;QAE3D,2BAA2B,EAAE,IAAI;QACjC,+BAA+B,EAAE,IAAI;QACrC,gCAAgC,EAAE,IAAI;QAEtC,QAAQ,EAAE,IAAI,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,IAAI;QAE7C,sBAAsB,EAAE,IAAI,GAAG,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC,IAAI;QAEhE,cAAc,EAAE,IAAI,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,IAAI;QACpD,qCAAqC,EAAE,CAAC,GAAG,kBAAM,CAAC,sBAAsB,CAAC;QACzE,gDAAgD,EAAE,CAAC,GAAG,wBAAY,CAAC;QAEnE,mBAAmB,EAAE,IAAI,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,IAAI;QAE1D,6CAA6C;QAC7C,qEAAqE;QACrE,+DAA+D;QAE/D,0DAA0D;QAC1D,qCAAqC,EAAE,IAAI,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,IAAI;QAEzE,qCAAqC,EAAE,IAAI;QAE3C,4DAA4D;QAC5D,iCAAiC,EAAE,CAAC,GAAG,wBAAY,CAAC;QAEpD,6DAA6D;QAC7D,qCAAqC,EACnC,cAAc,EAAE,qCAAqC;QAEvD,wDAAwD;QACxD,mBAAmB,EAAE,cAAc,EAAE,mBAAmB;QAExD,uFAAuF;QACvF,qCAAqC,EAAE,IAAI;KAC5C,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import { Keyset } from '@atproto/jwk'\nimport {\n OAuthAuthorizationServerMetadata,\n OAuthIssuerIdentifier,\n oauthAuthorizationServerMetadataValidator,\n} from '@atproto/oauth-types'\nimport { Client } from '../client/client.js'\nimport { VERIFY_ALGOS } from '../lib/util/crypto.js'\n\nexport type CustomMetadata = {\n authorization_details_types_supported?: string[]\n protected_resources?: string[]\n}\n\n/**\n * @see {@link https://datatracker.ietf.org/doc/html/rfc8414#section-2}\n * @see {@link https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata}\n * @see {@link https://openid.net/specs/openid-connect-prompt-create-1_0.html}\n */\nexport function buildMetadata(\n issuer: OAuthIssuerIdentifier,\n keyset: Keyset,\n customMetadata?: CustomMetadata,\n): OAuthAuthorizationServerMetadata {\n return oauthAuthorizationServerMetadataValidator.parse({\n issuer,\n\n scopes_supported: [\n 'atproto',\n\n // These serve as hint that this server supports the transitional scopes.\n // This is not a specced behavior.\n 'transition:email',\n 'transition:generic',\n 'transition:chat.bsky',\n\n // Other atproto scopes can't be enumerated as they are dynamic.\n ],\n subject_types_supported: [\n //\n 'public', // The same \"sub\" is returned for all clients\n // 'pairwise', // A different \"sub\" is returned for each client\n ],\n response_types_supported: [\n // OAuth\n 'code',\n // 'token',\n\n // OpenID\n // 'none',\n // 'code id_token token',\n // 'code id_token',\n // 'code token',\n // 'id_token token',\n // 'id_token',\n ],\n response_modes_supported: [\n // https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html#ResponseModes\n 'query',\n 'fragment',\n // https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html#FormPostResponseMode\n 'form_post',\n ],\n grant_types_supported: [\n //\n 'authorization_code',\n 'refresh_token',\n ],\n code_challenge_methods_supported: [\n // https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#pkce-code-challenge-method\n 'S256',\n\n // atproto does not allow \"plain\"\n // 'plain',\n ],\n ui_locales_supported: [\n //\n 'en-US',\n ],\n display_values_supported: [\n //\n 'page',\n 'popup',\n 'touch',\n // 'wap', LoL\n ],\n\n // https://openid.net/specs/openid-connect-prompt-create-1_0.html\n prompt_values_supported: [\n 'none',\n 'login',\n 'consent',\n 'select_account',\n 'create',\n ],\n\n // https://datatracker.ietf.org/doc/html/rfc9207\n authorization_response_iss_parameter_supported: true,\n\n // https://datatracker.ietf.org/doc/html/rfc9101#section-4\n request_object_signing_alg_values_supported: [...VERIFY_ALGOS, 'none'],\n request_object_encryption_alg_values_supported: [], // None\n request_object_encryption_enc_values_supported: [], // None\n\n request_parameter_supported: true,\n request_uri_parameter_supported: true,\n require_request_uri_registration: true,\n\n jwks_uri: new URL('/oauth/jwks', issuer).href,\n\n authorization_endpoint: new URL('/oauth/authorize', issuer).href,\n\n token_endpoint: new URL('/oauth/token', issuer).href,\n token_endpoint_auth_methods_supported: [...Client.AUTH_METHODS_SUPPORTED],\n token_endpoint_auth_signing_alg_values_supported: [...VERIFY_ALGOS],\n\n revocation_endpoint: new URL('/oauth/revoke', issuer).href,\n\n // @TODO Should we implement these endpoints?\n // introspection_endpoint: new URL('/oauth/introspect', issuer).href,\n // end_session_endpoint: new URL('/oauth/logout', issuer).href,\n\n // https://datatracker.ietf.org/doc/html/rfc9126#section-5\n pushed_authorization_request_endpoint: new URL('/oauth/par', issuer).href,\n\n require_pushed_authorization_requests: true,\n\n // https://datatracker.ietf.org/doc/html/rfc9449#section-5.1\n dpop_signing_alg_values_supported: [...VERIFY_ALGOS],\n\n // https://datatracker.ietf.org/doc/html/rfc9396#section-14.4\n authorization_details_types_supported:\n customMetadata?.authorization_details_types_supported,\n\n // https://www.rfc-editor.org/rfc/rfc9728.html#section-4\n protected_resources: customMetadata?.protected_resources,\n\n // https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html\n client_id_metadata_document_supported: true,\n })\n}\n"]}
|
|
@@ -53,7 +53,7 @@ export declare class RequestManager {
|
|
|
53
53
|
ui_locales?: string | undefined;
|
|
54
54
|
id_token_hint?: `${string}.${string}.${string}` | undefined;
|
|
55
55
|
display?: "page" | "popup" | "touch" | "wap" | undefined;
|
|
56
|
-
prompt?: "none" | "login" | "consent" | "select_account" | undefined;
|
|
56
|
+
prompt?: "none" | "login" | "consent" | "select_account" | "create" | undefined;
|
|
57
57
|
}>;
|
|
58
58
|
}>;
|
|
59
59
|
protected validate(client: Client, clientAuth: null | ClientAuth, parameters: Readonly<OAuthAuthorizationRequestParameters>): Promise<Readonly<OAuthAuthorizationRequestParameters>>;
|
|
@@ -89,7 +89,7 @@ export declare class RequestManager {
|
|
|
89
89
|
ui_locales?: string | undefined;
|
|
90
90
|
id_token_hint?: `${string}.${string}.${string}` | undefined;
|
|
91
91
|
display?: "page" | "popup" | "touch" | "wap" | undefined;
|
|
92
|
-
prompt?: "none" | "login" | "consent" | "select_account" | undefined;
|
|
92
|
+
prompt?: "none" | "login" | "consent" | "select_account" | "create" | undefined;
|
|
93
93
|
}>;
|
|
94
94
|
clientId: string;
|
|
95
95
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-manager.d.ts","sourceRoot":"","sources":["../../src/request/request-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AAE1D,OAAO,EACL,mCAAmC,EACnC,gCAAgC,EACjC,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAO5C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAQjD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAC5C,OAAO,EAAE,IAAI,EAAgB,MAAM,WAAW,CAAA;AAC9C,OAAO,EACL,qBAAqB,EAEtB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,YAAY,EAAqB,MAAM,oBAAoB,CAAA;AACpE,OAAO,EACL,UAAU,EAGX,MAAM,kBAAkB,CAAA;AAEzB,qBAAa,cAAc;IAEvB,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,YAAY;IACtC,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,cAAc;IACjD,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACjC,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,gCAAgC;IAC7D,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,UAAU;IACpC,SAAS,CAAC,QAAQ,CAAC,WAAW;gBALX,KAAK,EAAE,YAAY,EACnB,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,gCAAgC,EAC1C,KAAK,EAAE,UAAU,EACjB,WAAW,SAAgB;IAGhD,SAAS,CAAC,iBAAiB;IAIrB,0BAA0B,CAC9B,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,IAAI,GAAG,UAAU,EAC7B,KAAK,EAAE,QAAQ,CAAC,mCAAmC,CAAC,EACpD,QAAQ,EAAE,IAAI,GAAG,QAAQ;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"request-manager.d.ts","sourceRoot":"","sources":["../../src/request/request-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AAE1D,OAAO,EACL,mCAAmC,EACnC,gCAAgC,EACjC,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAO5C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAQjD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAC5C,OAAO,EAAE,IAAI,EAAgB,MAAM,WAAW,CAAA;AAC9C,OAAO,EACL,qBAAqB,EAEtB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,YAAY,EAAqB,MAAM,oBAAoB,CAAA;AACpE,OAAO,EACL,UAAU,EAGX,MAAM,kBAAkB,CAAA;AAEzB,qBAAa,cAAc;IAEvB,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,YAAY;IACtC,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,cAAc;IACjD,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACjC,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,gCAAgC;IAC7D,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,UAAU;IACpC,SAAS,CAAC,QAAQ,CAAC,WAAW;gBALX,KAAK,EAAE,YAAY,EACnB,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,gCAAgC,EAC1C,KAAK,EAAE,UAAU,EACjB,WAAW,SAAgB;IAGhD,SAAS,CAAC,iBAAiB;IAIrB,0BAA0B,CAC9B,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,IAAI,GAAG,UAAU,EAC7B,KAAK,EAAE,QAAQ,CAAC,mCAAmC,CAAC,EACpD,QAAQ,EAAE,IAAI,GAAG,QAAQ;;;;;;;;;;yBAqGV,CAAA;uBACqB,CAAC;yBAarC,CAVD;0BAA0C,CAAC;0BAU1C,CATD;;;;;;;;;;qBAY6C,CAAC;sBACvB,CAAC;yBACjB,CAAC;;;;;;;;;cA7FO,QAAQ,CACtB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,IAAI,GAAG,UAAU,EAC7B,UAAU,EAAE,QAAQ,CAAC,mCAAmC,CAAC,GACxD,OAAO,CAAC,QAAQ,CAAC,mCAAmC,CAAC,CAAC;IAkOnD,GAAG,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,QAAQ;;;;;;;;;;yBA5JxD,CAAA;uBACqB,CAAC;yBAarC,CAVD;0BAA0C,CAAC;0BAU1C,CATD;;;;;;;;;;qBAY6C,CAAC;sBACvB,CAAC;yBACjB,CAAC;;;;;;;;;;IAmMH,aAAa,CACjB,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,QAAQ,EAClB,cAAc,EAAE,eAAe,EAC/B,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC;IAiFhB;;;OAGG;IACU,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,qBAAqB,CAAC;IA2B9D,MAAM,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CAIpD"}
|
|
@@ -175,8 +175,11 @@ class RequestManager {
|
|
|
175
175
|
if (parameters.prompt === 'none') {
|
|
176
176
|
throw new consent_required_error_js_1.ConsentRequiredError(parameters, 'Public clients are not allowed to use silent-sign-on');
|
|
177
177
|
}
|
|
178
|
-
// force "consent" for unauthenticated
|
|
179
|
-
|
|
178
|
+
// force "consent" for unauthenticated third party clients, unless they
|
|
179
|
+
// are trying to create accounts:
|
|
180
|
+
if (parameters.prompt !== 'create') {
|
|
181
|
+
parameters = { ...parameters, prompt: 'consent' };
|
|
182
|
+
}
|
|
180
183
|
}
|
|
181
184
|
// atproto extension: ensure that the login_hint is a valid handle or DID
|
|
182
185
|
// @NOTE we to allow invalid case here, which is not spec'd anywhere.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-manager.js","sourceRoot":"","sources":["../../src/request/request-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { isAtprotoDid } from '@atproto/did'\nimport { LexResolverError } from '@atproto/lex-resolver'\nimport type { Account } from '@atproto/oauth-provider-api'\nimport { isAtprotoOauthScope } from '@atproto/oauth-scopes'\nimport {\n OAuthAuthorizationRequestParameters,\n OAuthAuthorizationServerMetadata,\n} from '@atproto/oauth-types'\nimport { isValidHandle } from '@atproto/syntax'\nimport { ClientAuth } from '../client/client-auth.js'\nimport { ClientId } from '../client/client-id.js'\nimport { Client } from '../client/client.js'\nimport {\n AUTHORIZATION_INACTIVITY_TIMEOUT,\n NODE_ENV,\n PAR_EXPIRES_IN,\n TOKEN_MAX_AGE,\n} from '../constants.js'\nimport { DeviceId } from '../device/device-id.js'\nimport { AccessDeniedError } from '../errors/access-denied-error.js'\nimport { AuthorizationError } from '../errors/authorization-error.js'\nimport { ConsentRequiredError } from '../errors/consent-required-error.js'\nimport { InvalidAuthorizationDetailsError } from '../errors/invalid-authorization-details-error.js'\nimport { InvalidGrantError } from '../errors/invalid-grant-error.js'\nimport { InvalidRequestError } from '../errors/invalid-request-error.js'\nimport { InvalidScopeError } from '../errors/invalid-scope-error.js'\nimport { LexiconManager } from '../lexicon/lexicon-manager.js'\nimport { RequestMetadata } from '../lib/http/request.js'\nimport { OAuthHooks } from '../oauth-hooks.js'\nimport { Signer } from '../signer/signer.js'\nimport { Code, generateCode } from './code.js'\nimport {\n RequestDataAuthorized,\n isRequestDataAuthorized,\n} from './request-data.js'\nimport { generateRequestId } from './request-id.js'\nimport { RequestStore, UpdateRequestData } from './request-store.js'\nimport {\n RequestUri,\n decodeRequestUri,\n encodeRequestUri,\n} from './request-uri.js'\n\nexport class RequestManager {\n constructor(\n protected readonly store: RequestStore,\n protected readonly lexiconManager: LexiconManager,\n protected readonly signer: Signer,\n protected readonly metadata: OAuthAuthorizationServerMetadata,\n protected readonly hooks: OAuthHooks,\n protected readonly tokenMaxAge = TOKEN_MAX_AGE,\n ) {}\n\n protected createTokenExpiry() {\n return new Date(Date.now() + this.tokenMaxAge)\n }\n\n async createAuthorizationRequest(\n client: Client,\n clientAuth: null | ClientAuth,\n input: Readonly<OAuthAuthorizationRequestParameters>,\n deviceId: null | DeviceId,\n ) {\n const parameters = await this.validate(client, clientAuth, input)\n\n await this.hooks.onAuthorizationRequest?.call(null, {\n client,\n clientAuth,\n parameters,\n })\n\n const expiresAt = new Date(Date.now() + PAR_EXPIRES_IN)\n const requestId = await generateRequestId()\n\n await this.store.createRequest(requestId, {\n clientId: client.id,\n clientAuth,\n parameters,\n expiresAt,\n deviceId,\n sub: null,\n code: null,\n })\n\n const requestUri = encodeRequestUri(requestId)\n return { requestUri, expiresAt, parameters }\n }\n\n protected async validate(\n client: Client,\n clientAuth: null | ClientAuth,\n parameters: Readonly<OAuthAuthorizationRequestParameters>,\n ): Promise<Readonly<OAuthAuthorizationRequestParameters>> {\n // -------------------------------\n // Validate unsupported parameters\n // -------------------------------\n\n for (const k of [\n // Known unsupported OIDC parameters\n 'claims',\n 'id_token_hint',\n 'nonce', // note that OIDC \"nonce\" is redundant with PKCE\n ] as const) {\n if (parameters[k] !== undefined) {\n throw new AuthorizationError(parameters, `Unsupported \"${k}\" parameter`)\n }\n }\n\n // -----------------------\n // Validate against server\n // -----------------------\n\n if (\n !this.metadata.response_types_supported?.includes(\n parameters.response_type,\n )\n ) {\n throw new AuthorizationError(\n parameters,\n `Unsupported response_type \"${parameters.response_type}\"`,\n 'unsupported_response_type',\n )\n }\n\n if (\n parameters.response_type === 'code' &&\n !this.metadata.grant_types_supported?.includes('authorization_code')\n ) {\n throw new AuthorizationError(\n parameters,\n `Unsupported grant_type \"authorization_code\"`,\n 'invalid_request',\n )\n }\n\n if (parameters.authorization_details) {\n for (const detail of parameters.authorization_details) {\n if (\n !this.metadata.authorization_details_types_supported?.includes(\n detail.type,\n )\n ) {\n throw new InvalidAuthorizationDetailsError(\n parameters,\n `Unsupported \"authorization_details\" type \"${detail.type}\"`,\n )\n }\n }\n }\n\n // -----------------------\n // Validate against client\n // -----------------------\n\n parameters = client.validateRequest(parameters)\n\n // -------------------\n // Validate parameters\n // -------------------\n\n if (!parameters.redirect_uri) {\n // Should already be ensured by client.validateRequest(). Adding here for\n // clarity & extra safety.\n throw new AuthorizationError(parameters, 'Missing \"redirect_uri\"')\n }\n\n // https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-10#section-1.4.1\n // > The authorization server MAY fully or partially ignore the scope\n // > requested by the client, based on the authorization server policy or\n // > the resource owner's instructions. If the issued access token scope is\n // > different from the one requested by the client, the authorization\n // > server MUST include the scope response parameter in the token response\n // > (Section 3.2.3) to inform the client of the actual scope granted.\n\n // Let's make sure the scopes are unique (to reduce the token & storage\n // size).\n const scopes = new Set(parameters.scope?.split(' '))\n\n // @NOTE An app requesting a not yet supported list of scopes will need to\n // re-authenticate the user once the scopes are supported. This is due to\n // the fact that the AS does not know how to properly display those scopes\n // to the user, so it cannot properly ask for consent.\n const scope =\n Array.from(scopes).filter(isAtprotoOauthScope).join(' ') || undefined\n parameters = { ...parameters, scope }\n\n if (parameters.code_challenge) {\n switch (parameters.code_challenge_method) {\n case undefined:\n // https://datatracker.ietf.org/doc/html/rfc7636#section-4.3\n parameters = { ...parameters, code_challenge_method: 'plain' }\n // falls through\n case 'plain':\n case 'S256':\n break\n default: {\n throw new AuthorizationError(\n parameters,\n `Unsupported code_challenge_method \"${parameters.code_challenge_method}\"`,\n )\n }\n }\n } else {\n if (parameters.code_challenge_method) {\n // https://datatracker.ietf.org/doc/html/rfc7636#section-4.4.1\n throw new AuthorizationError(\n parameters,\n 'code_challenge is required when code_challenge_method is provided',\n )\n }\n\n // https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-11#section-4.1.2.1\n //\n // > An AS MUST reject requests without a code_challenge from public\n // > clients, and MUST reject such requests from other clients unless\n // > there is reasonable assurance that the client mitigates\n // > authorization code injection in other ways. See Section 7.5.1 for\n // > details.\n //\n // > [...] In the specific deployment and the specific request, there is\n // > reasonable assurance by the authorization server that the client\n // > implements the OpenID Connect nonce mechanism properly.\n //\n // atproto does not implement the OpenID Connect nonce mechanism, so we\n // require the use of PKCE for all clients.\n\n throw new AuthorizationError(parameters, 'Use of PKCE is required')\n }\n\n // -----------------\n // atproto extension\n // -----------------\n\n if (parameters.response_type !== 'code') {\n throw new AuthorizationError(\n parameters,\n 'atproto only supports the \"code\" response_type',\n )\n }\n\n if (!scopes.has('atproto')) {\n throw new InvalidScopeError(parameters, 'The \"atproto\" scope is required')\n } else if (scopes.has('openid')) {\n throw new InvalidScopeError(\n parameters,\n 'OpenID Connect is not compatible with atproto',\n )\n }\n\n if (parameters.code_challenge_method !== 'S256') {\n throw new AuthorizationError(\n parameters,\n 'atproto requires use of \"S256\" code_challenge_method',\n )\n }\n\n // atproto extension: if the client is not trusted, and not authenticated,\n // force users to consent to authorization requests. We do this to avoid\n // unauthenticated clients from being able to silently re-authenticate\n // users.\n if (\n !client.info.isTrusted &&\n !client.info.isFirstParty &&\n client.metadata.token_endpoint_auth_method === 'none'\n ) {\n if (parameters.prompt === 'none') {\n throw new ConsentRequiredError(\n parameters,\n 'Public clients are not allowed to use silent-sign-on',\n )\n }\n\n // force \"consent\" for unauthenticated, third party clients\n parameters = { ...parameters, prompt: 'consent' }\n }\n\n // atproto extension: ensure that the login_hint is a valid handle or DID\n // @NOTE we to allow invalid case here, which is not spec'd anywhere.\n const hint = parameters.login_hint?.toLowerCase()\n if (hint) {\n if (!isAtprotoDid(hint) && !isValidHandle(hint)) {\n throw new AuthorizationError(parameters, `Invalid login_hint \"${hint}\"`)\n }\n\n // @TODO: ensure that the account actually exists on this server (there is\n // no point in showing the UI to the user if the account does not exist).\n\n // Update the parameters to ensure the right case is used\n parameters = { ...parameters, login_hint: hint }\n }\n\n // Make sure that every nsid in the scope resolves to a valid permission set\n // lexicon\n if (parameters.scope) {\n try {\n await this.lexiconManager.getPermissionSetsFromScope(parameters.scope)\n } catch (err) {\n // Parse expected errors\n if (err instanceof LexResolverError) {\n throw new AuthorizationError(\n parameters,\n err.message,\n 'invalid_scope',\n err,\n )\n }\n\n // Unexpected error\n throw err\n }\n }\n\n return parameters\n }\n\n async get(requestUri: RequestUri, deviceId: DeviceId, clientId?: ClientId) {\n const requestId = decodeRequestUri(requestUri)\n\n const data = await this.store.readRequest(requestId)\n if (!data) throw new InvalidRequestError('Unknown request_uri')\n\n const updates: UpdateRequestData = {}\n\n try {\n if (data.sub || data.code) {\n // If an account was linked to the request, the next step is to exchange\n // the code for a token.\n throw new AccessDeniedError(\n data.parameters,\n 'This request was already authorized',\n )\n }\n\n if (data.expiresAt < new Date()) {\n throw new AccessDeniedError(data.parameters, 'This request has expired')\n } else {\n updates.expiresAt = new Date(\n Date.now() + AUTHORIZATION_INACTIVITY_TIMEOUT,\n )\n }\n\n if (clientId != null && data.clientId !== clientId) {\n throw new AccessDeniedError(\n data.parameters,\n 'This request was initiated for another client',\n )\n }\n\n if (!data.deviceId) {\n updates.deviceId = deviceId\n } else if (data.deviceId !== deviceId) {\n throw new AccessDeniedError(\n data.parameters,\n 'This request was initiated from another device',\n )\n }\n } catch (err) {\n await this.store.deleteRequest(requestId)\n throw err\n }\n\n if (Object.keys(updates).length > 0) {\n await this.store.updateRequest(requestId, updates)\n }\n\n return {\n requestUri,\n expiresAt: updates.expiresAt || data.expiresAt,\n parameters: data.parameters,\n clientId: data.clientId,\n }\n }\n\n async setAuthorized(\n requestUri: RequestUri,\n client: Client,\n account: Account,\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n scopeOverride?: string,\n ): Promise<Code> {\n const requestId = decodeRequestUri(requestUri)\n\n const data = await this.store.readRequest(requestId)\n if (!data) throw new InvalidRequestError('Unknown request_uri')\n\n let { parameters } = data\n\n try {\n if (data.expiresAt < new Date()) {\n throw new AccessDeniedError(parameters, 'This request has expired')\n }\n if (!data.deviceId) {\n throw new AccessDeniedError(\n parameters,\n 'This request was not initiated',\n )\n }\n if (data.deviceId !== deviceId) {\n throw new AccessDeniedError(\n parameters,\n 'This request was initiated from another device',\n )\n }\n if (data.sub || data.code) {\n throw new AccessDeniedError(\n parameters,\n 'This request was already authorized',\n )\n }\n\n // If a new scope value is provided, update the parameters by ensuring\n // that every existing scope in the parameters is also present in the\n // override value. This allows the user to remove scopes from the request,\n // but not to add new ones.\n if (scopeOverride != null) {\n const allowedScopes = new Set(scopeOverride.split(' '))\n const existingScopes = parameters.scope?.split(' ')\n\n // Compute the intersection of the existing scopes and the overrides.\n const newScopes = existingScopes?.filter((s) => allowedScopes.has(s))\n\n // Validate: make sure the new scopes are valid\n if (!newScopes?.includes('atproto')) {\n throw new AccessDeniedError(\n parameters,\n 'The \"atproto\" scope is required',\n )\n }\n\n parameters = { ...parameters, scope: newScopes.join(' ') }\n }\n\n // Only response_type=code is supported\n const code = await generateCode()\n\n // Bind the request to the account, preventing it from being used again.\n await this.store.updateRequest(requestId, {\n sub: account.sub,\n code,\n // Allow the client to exchange the code for a token within the next 60 seconds.\n expiresAt: new Date(Date.now() + AUTHORIZATION_INACTIVITY_TIMEOUT),\n parameters,\n })\n\n await this.hooks.onAuthorized?.call(null, {\n client,\n account,\n parameters,\n deviceId,\n deviceMetadata,\n requestId,\n })\n\n return code\n } catch (err) {\n await this.store.deleteRequest(requestId)\n throw err\n }\n }\n\n /**\n * @note If this method throws an error, any token previously generated from\n * the same `code` **must** me revoked.\n */\n public async consumeCode(code: Code): Promise<RequestDataAuthorized> {\n const result = await this.store.consumeRequestCode(code)\n if (!result) throw new InvalidGrantError('Invalid code')\n\n const { requestId, data } = result\n\n // Fool-proofing the store implementation against code replay attacks (in\n // case consumeRequestCode() does not delete the request).\n if (NODE_ENV !== 'production') {\n const result = await this.store.readRequest(requestId)\n if (result) {\n throw new Error('Invalid store implementation: request not deleted')\n }\n }\n\n if (!isRequestDataAuthorized(data) || data.code !== code) {\n // Should never happen: maybe the store implementation is faulty ?\n throw new Error('Unexpected request state')\n }\n\n if (data.expiresAt < new Date()) {\n throw new InvalidGrantError('This code has expired')\n }\n\n return data\n }\n\n async delete(requestUri: RequestUri): Promise<void> {\n const requestId = decodeRequestUri(requestUri)\n await this.store.deleteRequest(requestId)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"request-manager.js","sourceRoot":"","sources":["../../src/request/request-manager.ts"],"names":[],"mappings":";;;AAAA,sCAA2C;AAC3C,wDAAwD;AAExD,wDAA2D;AAK3D,4CAA+C;AAI/C,kDAKwB;AAExB,6EAAoE;AACpE,6EAAqE;AACrE,mFAA0E;AAC1E,6GAAmG;AACnG,6EAAoE;AACpE,iFAAwE;AACxE,6EAAoE;AAKpE,uCAA8C;AAC9C,uDAG0B;AAC1B,mDAAmD;AAEnD,qDAIyB;AAEzB,MAAa,cAAc;IAEJ;IACA;IACA;IACA;IACA;IACA;IANrB,YACqB,KAAmB,EACnB,cAA8B,EAC9B,MAAc,EACd,QAA0C,EAC1C,KAAiB,EACjB,cAAc,4BAAa;QAL3B,UAAK,GAAL,KAAK,CAAc;QACnB,mBAAc,GAAd,cAAc,CAAgB;QAC9B,WAAM,GAAN,MAAM,CAAQ;QACd,aAAQ,GAAR,QAAQ,CAAkC;QAC1C,UAAK,GAAL,KAAK,CAAY;QACjB,gBAAW,GAAX,WAAW,CAAgB;IAC7C,CAAC;IAEM,iBAAiB;QACzB,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,CAAA;IAChD,CAAC;IAED,KAAK,CAAC,0BAA0B,CAC9B,MAAc,EACd,UAA6B,EAC7B,KAAoD,EACpD,QAAyB;QAEzB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,CAAA;QAEjE,MAAM,IAAI,CAAC,KAAK,CAAC,sBAAsB,EAAE,IAAI,CAAC,IAAI,EAAE;YAClD,MAAM;YACN,UAAU;YACV,UAAU;SACX,CAAC,CAAA;QAEF,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,6BAAc,CAAC,CAAA;QACvD,MAAM,SAAS,GAAG,MAAM,IAAA,iCAAiB,GAAE,CAAA;QAE3C,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,EAAE;YACxC,QAAQ,EAAE,MAAM,CAAC,EAAE;YACnB,UAAU;YACV,UAAU;YACV,SAAS;YACT,QAAQ;YACR,GAAG,EAAE,IAAI;YACT,IAAI,EAAE,IAAI;SACX,CAAC,CAAA;QAEF,MAAM,UAAU,GAAG,IAAA,iCAAgB,EAAC,SAAS,CAAC,CAAA;QAC9C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,CAAA;IAC9C,CAAC;IAES,KAAK,CAAC,QAAQ,CACtB,MAAc,EACd,UAA6B,EAC7B,UAAyD;QAEzD,kCAAkC;QAClC,kCAAkC;QAClC,kCAAkC;QAElC,KAAK,MAAM,CAAC,IAAI;YACd,oCAAoC;YACpC,QAAQ;YACR,eAAe;YACf,OAAO,EAAE,gDAAgD;SACjD,EAAE,CAAC;YACX,IAAI,UAAU,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;gBAChC,MAAM,IAAI,2CAAkB,CAAC,UAAU,EAAE,gBAAgB,CAAC,aAAa,CAAC,CAAA;YAC1E,CAAC;QACH,CAAC;QAED,0BAA0B;QAC1B,0BAA0B;QAC1B,0BAA0B;QAE1B,IACE,CAAC,IAAI,CAAC,QAAQ,CAAC,wBAAwB,EAAE,QAAQ,CAC/C,UAAU,CAAC,aAAa,CACzB,EACD,CAAC;YACD,MAAM,IAAI,2CAAkB,CAC1B,UAAU,EACV,8BAA8B,UAAU,CAAC,aAAa,GAAG,EACzD,2BAA2B,CAC5B,CAAA;QACH,CAAC;QAED,IACE,UAAU,CAAC,aAAa,KAAK,MAAM;YACnC,CAAC,IAAI,CAAC,QAAQ,CAAC,qBAAqB,EAAE,QAAQ,CAAC,oBAAoB,CAAC,EACpE,CAAC;YACD,MAAM,IAAI,2CAAkB,CAC1B,UAAU,EACV,6CAA6C,EAC7C,iBAAiB,CAClB,CAAA;QACH,CAAC;QAED,IAAI,UAAU,CAAC,qBAAqB,EAAE,CAAC;YACrC,KAAK,MAAM,MAAM,IAAI,UAAU,CAAC,qBAAqB,EAAE,CAAC;gBACtD,IACE,CAAC,IAAI,CAAC,QAAQ,CAAC,qCAAqC,EAAE,QAAQ,CAC5D,MAAM,CAAC,IAAI,CACZ,EACD,CAAC;oBACD,MAAM,IAAI,yEAAgC,CACxC,UAAU,EACV,6CAA6C,MAAM,CAAC,IAAI,GAAG,CAC5D,CAAA;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,0BAA0B;QAC1B,0BAA0B;QAC1B,0BAA0B;QAE1B,UAAU,GAAG,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAA;QAE/C,sBAAsB;QACtB,sBAAsB;QACtB,sBAAsB;QAEtB,IAAI,CAAC,UAAU,CAAC,YAAY,EAAE,CAAC;YAC7B,yEAAyE;YACzE,0BAA0B;YAC1B,MAAM,IAAI,2CAAkB,CAAC,UAAU,EAAE,wBAAwB,CAAC,CAAA;QACpE,CAAC;QAED,+EAA+E;QAC/E,qEAAqE;QACrE,yEAAyE;QACzE,2EAA2E;QAC3E,sEAAsE;QACtE,2EAA2E;QAC3E,sEAAsE;QAEtE,uEAAuE;QACvE,SAAS;QACT,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAA;QAEpD,0EAA0E;QAC1E,yEAAyE;QACzE,0EAA0E;QAC1E,sDAAsD;QACtD,MAAM,KAAK,GACT,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,kCAAmB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,SAAS,CAAA;QACvE,UAAU,GAAG,EAAE,GAAG,UAAU,EAAE,KAAK,EAAE,CAAA;QAErC,IAAI,UAAU,CAAC,cAAc,EAAE,CAAC;YAC9B,QAAQ,UAAU,CAAC,qBAAqB,EAAE,CAAC;gBACzC,KAAK,SAAS;oBACZ,4DAA4D;oBAC5D,UAAU,GAAG,EAAE,GAAG,UAAU,EAAE,qBAAqB,EAAE,OAAO,EAAE,CAAA;gBAChE,gBAAgB;gBAChB,KAAK,OAAO,CAAC;gBACb,KAAK,MAAM;oBACT,MAAK;gBACP,OAAO,CAAC,CAAC,CAAC;oBACR,MAAM,IAAI,2CAAkB,CAC1B,UAAU,EACV,sCAAsC,UAAU,CAAC,qBAAqB,GAAG,CAC1E,CAAA;gBACH,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,UAAU,CAAC,qBAAqB,EAAE,CAAC;gBACrC,8DAA8D;gBAC9D,MAAM,IAAI,2CAAkB,CAC1B,UAAU,EACV,mEAAmE,CACpE,CAAA;YACH,CAAC;YAED,iFAAiF;YACjF,EAAE;YACF,oEAAoE;YACpE,qEAAqE;YACrE,4DAA4D;YAC5D,sEAAsE;YACtE,aAAa;YACb,EAAE;YACF,wEAAwE;YACxE,qEAAqE;YACrE,4DAA4D;YAC5D,EAAE;YACF,uEAAuE;YACvE,2CAA2C;YAE3C,MAAM,IAAI,2CAAkB,CAAC,UAAU,EAAE,yBAAyB,CAAC,CAAA;QACrE,CAAC;QAED,oBAAoB;QACpB,oBAAoB;QACpB,oBAAoB;QAEpB,IAAI,UAAU,CAAC,aAAa,KAAK,MAAM,EAAE,CAAC;YACxC,MAAM,IAAI,2CAAkB,CAC1B,UAAU,EACV,gDAAgD,CACjD,CAAA;QACH,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,0CAAiB,CAAC,UAAU,EAAE,iCAAiC,CAAC,CAAA;QAC5E,CAAC;aAAM,IAAI,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,0CAAiB,CACzB,UAAU,EACV,+CAA+C,CAChD,CAAA;QACH,CAAC;QAED,IAAI,UAAU,CAAC,qBAAqB,KAAK,MAAM,EAAE,CAAC;YAChD,MAAM,IAAI,2CAAkB,CAC1B,UAAU,EACV,sDAAsD,CACvD,CAAA;QACH,CAAC;QAED,0EAA0E;QAC1E,wEAAwE;QACxE,sEAAsE;QACtE,SAAS;QACT,IACE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS;YACtB,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY;YACzB,MAAM,CAAC,QAAQ,CAAC,0BAA0B,KAAK,MAAM,EACrD,CAAC;YACD,IAAI,UAAU,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBACjC,MAAM,IAAI,gDAAoB,CAC5B,UAAU,EACV,sDAAsD,CACvD,CAAA;YACH,CAAC;YAED,uEAAuE;YACvE,iCAAiC;YACjC,IAAI,UAAU,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;gBACnC,UAAU,GAAG,EAAE,GAAG,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,CAAA;YACnD,CAAC;QACH,CAAC;QAED,yEAAyE;QACzE,qEAAqE;QACrE,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,EAAE,WAAW,EAAE,CAAA;QACjD,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,IAAA,kBAAY,EAAC,IAAI,CAAC,IAAI,CAAC,IAAA,sBAAa,EAAC,IAAI,CAAC,EAAE,CAAC;gBAChD,MAAM,IAAI,2CAAkB,CAAC,UAAU,EAAE,uBAAuB,IAAI,GAAG,CAAC,CAAA;YAC1E,CAAC;YAED,0EAA0E;YAC1E,yEAAyE;YAEzE,yDAAyD;YACzD,UAAU,GAAG,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,CAAA;QAClD,CAAC;QAED,4EAA4E;QAC5E,UAAU;QACV,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;YACrB,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,cAAc,CAAC,0BAA0B,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;YACxE,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,wBAAwB;gBACxB,IAAI,GAAG,YAAY,+BAAgB,EAAE,CAAC;oBACpC,MAAM,IAAI,2CAAkB,CAC1B,UAAU,EACV,GAAG,CAAC,OAAO,EACX,eAAe,EACf,GAAG,CACJ,CAAA;gBACH,CAAC;gBAED,mBAAmB;gBACnB,MAAM,GAAG,CAAA;YACX,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAA;IACnB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,UAAsB,EAAE,QAAkB,EAAE,QAAmB;QACvE,MAAM,SAAS,GAAG,IAAA,iCAAgB,EAAC,UAAU,CAAC,CAAA;QAE9C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAA;QACpD,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,8CAAmB,CAAC,qBAAqB,CAAC,CAAA;QAE/D,MAAM,OAAO,GAAsB,EAAE,CAAA;QAErC,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC1B,wEAAwE;gBACxE,wBAAwB;gBACxB,MAAM,IAAI,0CAAiB,CACzB,IAAI,CAAC,UAAU,EACf,qCAAqC,CACtC,CAAA;YACH,CAAC;YAED,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC;gBAChC,MAAM,IAAI,0CAAiB,CAAC,IAAI,CAAC,UAAU,EAAE,0BAA0B,CAAC,CAAA;YAC1E,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,SAAS,GAAG,IAAI,IAAI,CAC1B,IAAI,CAAC,GAAG,EAAE,GAAG,+CAAgC,CAC9C,CAAA;YACH,CAAC;YAED,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBACnD,MAAM,IAAI,0CAAiB,CACzB,IAAI,CAAC,UAAU,EACf,+CAA+C,CAChD,CAAA;YACH,CAAC;YAED,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACnB,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAA;YAC7B,CAAC;iBAAM,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBACtC,MAAM,IAAI,0CAAiB,CACzB,IAAI,CAAC,UAAU,EACf,gDAAgD,CACjD,CAAA;YACH,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,CAAA;YACzC,MAAM,GAAG,CAAA;QACX,CAAC;QAED,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;QACpD,CAAC;QAED,OAAO;YACL,UAAU;YACV,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS;YAC9C,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAA;IACH,CAAC;IAED,KAAK,CAAC,aAAa,CACjB,UAAsB,EACtB,MAAc,EACd,OAAgB,EAChB,QAAkB,EAClB,cAA+B,EAC/B,aAAsB;QAEtB,MAAM,SAAS,GAAG,IAAA,iCAAgB,EAAC,UAAU,CAAC,CAAA;QAE9C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAA;QACpD,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,8CAAmB,CAAC,qBAAqB,CAAC,CAAA;QAE/D,IAAI,EAAE,UAAU,EAAE,GAAG,IAAI,CAAA;QAEzB,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC;gBAChC,MAAM,IAAI,0CAAiB,CAAC,UAAU,EAAE,0BAA0B,CAAC,CAAA;YACrE,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACnB,MAAM,IAAI,0CAAiB,CACzB,UAAU,EACV,gCAAgC,CACjC,CAAA;YACH,CAAC;YACD,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBAC/B,MAAM,IAAI,0CAAiB,CACzB,UAAU,EACV,gDAAgD,CACjD,CAAA;YACH,CAAC;YACD,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC1B,MAAM,IAAI,0CAAiB,CACzB,UAAU,EACV,qCAAqC,CACtC,CAAA;YACH,CAAC;YAED,sEAAsE;YACtE,qEAAqE;YACrE,0EAA0E;YAC1E,2BAA2B;YAC3B,IAAI,aAAa,IAAI,IAAI,EAAE,CAAC;gBAC1B,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAA;gBACvD,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAA;gBAEnD,qEAAqE;gBACrE,MAAM,SAAS,GAAG,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;gBAErE,+CAA+C;gBAC/C,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;oBACpC,MAAM,IAAI,0CAAiB,CACzB,UAAU,EACV,iCAAiC,CAClC,CAAA;gBACH,CAAC;gBAED,UAAU,GAAG,EAAE,GAAG,UAAU,EAAE,KAAK,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAA;YAC5D,CAAC;YAED,uCAAuC;YACvC,MAAM,IAAI,GAAG,MAAM,IAAA,sBAAY,GAAE,CAAA;YAEjC,wEAAwE;YACxE,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,EAAE;gBACxC,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,IAAI;gBACJ,gFAAgF;gBAChF,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,+CAAgC,CAAC;gBAClE,UAAU;aACX,CAAC,CAAA;YAEF,MAAM,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,IAAI,CAAC,IAAI,EAAE;gBACxC,MAAM;gBACN,OAAO;gBACP,UAAU;gBACV,QAAQ;gBACR,cAAc;gBACd,SAAS;aACV,CAAC,CAAA;YAEF,OAAO,IAAI,CAAA;QACb,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,CAAA;YACzC,MAAM,GAAG,CAAA;QACX,CAAC;IACH,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,WAAW,CAAC,IAAU;QACjC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAA;QACxD,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,0CAAiB,CAAC,cAAc,CAAC,CAAA;QAExD,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,MAAM,CAAA;QAElC,yEAAyE;QACzE,0DAA0D;QAC1D,IAAI,uBAAQ,KAAK,YAAY,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAA;YACtD,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAA;YACtE,CAAC;QACH,CAAC;QAED,IAAI,CAAC,IAAA,yCAAuB,EAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YACzD,kEAAkE;YAClE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;QAC7C,CAAC;QAED,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC;YAChC,MAAM,IAAI,0CAAiB,CAAC,uBAAuB,CAAC,CAAA;QACtD,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,UAAsB;QACjC,MAAM,SAAS,GAAG,IAAA,iCAAgB,EAAC,UAAU,CAAC,CAAA;QAC9C,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,CAAA;IAC3C,CAAC;CACF;AAxcD,wCAwcC","sourcesContent":["import { isAtprotoDid } from '@atproto/did'\nimport { LexResolverError } from '@atproto/lex-resolver'\nimport type { Account } from '@atproto/oauth-provider-api'\nimport { isAtprotoOauthScope } from '@atproto/oauth-scopes'\nimport {\n OAuthAuthorizationRequestParameters,\n OAuthAuthorizationServerMetadata,\n} from '@atproto/oauth-types'\nimport { isValidHandle } from '@atproto/syntax'\nimport { ClientAuth } from '../client/client-auth.js'\nimport { ClientId } from '../client/client-id.js'\nimport { Client } from '../client/client.js'\nimport {\n AUTHORIZATION_INACTIVITY_TIMEOUT,\n NODE_ENV,\n PAR_EXPIRES_IN,\n TOKEN_MAX_AGE,\n} from '../constants.js'\nimport { DeviceId } from '../device/device-id.js'\nimport { AccessDeniedError } from '../errors/access-denied-error.js'\nimport { AuthorizationError } from '../errors/authorization-error.js'\nimport { ConsentRequiredError } from '../errors/consent-required-error.js'\nimport { InvalidAuthorizationDetailsError } from '../errors/invalid-authorization-details-error.js'\nimport { InvalidGrantError } from '../errors/invalid-grant-error.js'\nimport { InvalidRequestError } from '../errors/invalid-request-error.js'\nimport { InvalidScopeError } from '../errors/invalid-scope-error.js'\nimport { LexiconManager } from '../lexicon/lexicon-manager.js'\nimport { RequestMetadata } from '../lib/http/request.js'\nimport { OAuthHooks } from '../oauth-hooks.js'\nimport { Signer } from '../signer/signer.js'\nimport { Code, generateCode } from './code.js'\nimport {\n RequestDataAuthorized,\n isRequestDataAuthorized,\n} from './request-data.js'\nimport { generateRequestId } from './request-id.js'\nimport { RequestStore, UpdateRequestData } from './request-store.js'\nimport {\n RequestUri,\n decodeRequestUri,\n encodeRequestUri,\n} from './request-uri.js'\n\nexport class RequestManager {\n constructor(\n protected readonly store: RequestStore,\n protected readonly lexiconManager: LexiconManager,\n protected readonly signer: Signer,\n protected readonly metadata: OAuthAuthorizationServerMetadata,\n protected readonly hooks: OAuthHooks,\n protected readonly tokenMaxAge = TOKEN_MAX_AGE,\n ) {}\n\n protected createTokenExpiry() {\n return new Date(Date.now() + this.tokenMaxAge)\n }\n\n async createAuthorizationRequest(\n client: Client,\n clientAuth: null | ClientAuth,\n input: Readonly<OAuthAuthorizationRequestParameters>,\n deviceId: null | DeviceId,\n ) {\n const parameters = await this.validate(client, clientAuth, input)\n\n await this.hooks.onAuthorizationRequest?.call(null, {\n client,\n clientAuth,\n parameters,\n })\n\n const expiresAt = new Date(Date.now() + PAR_EXPIRES_IN)\n const requestId = await generateRequestId()\n\n await this.store.createRequest(requestId, {\n clientId: client.id,\n clientAuth,\n parameters,\n expiresAt,\n deviceId,\n sub: null,\n code: null,\n })\n\n const requestUri = encodeRequestUri(requestId)\n return { requestUri, expiresAt, parameters }\n }\n\n protected async validate(\n client: Client,\n clientAuth: null | ClientAuth,\n parameters: Readonly<OAuthAuthorizationRequestParameters>,\n ): Promise<Readonly<OAuthAuthorizationRequestParameters>> {\n // -------------------------------\n // Validate unsupported parameters\n // -------------------------------\n\n for (const k of [\n // Known unsupported OIDC parameters\n 'claims',\n 'id_token_hint',\n 'nonce', // note that OIDC \"nonce\" is redundant with PKCE\n ] as const) {\n if (parameters[k] !== undefined) {\n throw new AuthorizationError(parameters, `Unsupported \"${k}\" parameter`)\n }\n }\n\n // -----------------------\n // Validate against server\n // -----------------------\n\n if (\n !this.metadata.response_types_supported?.includes(\n parameters.response_type,\n )\n ) {\n throw new AuthorizationError(\n parameters,\n `Unsupported response_type \"${parameters.response_type}\"`,\n 'unsupported_response_type',\n )\n }\n\n if (\n parameters.response_type === 'code' &&\n !this.metadata.grant_types_supported?.includes('authorization_code')\n ) {\n throw new AuthorizationError(\n parameters,\n `Unsupported grant_type \"authorization_code\"`,\n 'invalid_request',\n )\n }\n\n if (parameters.authorization_details) {\n for (const detail of parameters.authorization_details) {\n if (\n !this.metadata.authorization_details_types_supported?.includes(\n detail.type,\n )\n ) {\n throw new InvalidAuthorizationDetailsError(\n parameters,\n `Unsupported \"authorization_details\" type \"${detail.type}\"`,\n )\n }\n }\n }\n\n // -----------------------\n // Validate against client\n // -----------------------\n\n parameters = client.validateRequest(parameters)\n\n // -------------------\n // Validate parameters\n // -------------------\n\n if (!parameters.redirect_uri) {\n // Should already be ensured by client.validateRequest(). Adding here for\n // clarity & extra safety.\n throw new AuthorizationError(parameters, 'Missing \"redirect_uri\"')\n }\n\n // https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-10#section-1.4.1\n // > The authorization server MAY fully or partially ignore the scope\n // > requested by the client, based on the authorization server policy or\n // > the resource owner's instructions. If the issued access token scope is\n // > different from the one requested by the client, the authorization\n // > server MUST include the scope response parameter in the token response\n // > (Section 3.2.3) to inform the client of the actual scope granted.\n\n // Let's make sure the scopes are unique (to reduce the token & storage\n // size).\n const scopes = new Set(parameters.scope?.split(' '))\n\n // @NOTE An app requesting a not yet supported list of scopes will need to\n // re-authenticate the user once the scopes are supported. This is due to\n // the fact that the AS does not know how to properly display those scopes\n // to the user, so it cannot properly ask for consent.\n const scope =\n Array.from(scopes).filter(isAtprotoOauthScope).join(' ') || undefined\n parameters = { ...parameters, scope }\n\n if (parameters.code_challenge) {\n switch (parameters.code_challenge_method) {\n case undefined:\n // https://datatracker.ietf.org/doc/html/rfc7636#section-4.3\n parameters = { ...parameters, code_challenge_method: 'plain' }\n // falls through\n case 'plain':\n case 'S256':\n break\n default: {\n throw new AuthorizationError(\n parameters,\n `Unsupported code_challenge_method \"${parameters.code_challenge_method}\"`,\n )\n }\n }\n } else {\n if (parameters.code_challenge_method) {\n // https://datatracker.ietf.org/doc/html/rfc7636#section-4.4.1\n throw new AuthorizationError(\n parameters,\n 'code_challenge is required when code_challenge_method is provided',\n )\n }\n\n // https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-11#section-4.1.2.1\n //\n // > An AS MUST reject requests without a code_challenge from public\n // > clients, and MUST reject such requests from other clients unless\n // > there is reasonable assurance that the client mitigates\n // > authorization code injection in other ways. See Section 7.5.1 for\n // > details.\n //\n // > [...] In the specific deployment and the specific request, there is\n // > reasonable assurance by the authorization server that the client\n // > implements the OpenID Connect nonce mechanism properly.\n //\n // atproto does not implement the OpenID Connect nonce mechanism, so we\n // require the use of PKCE for all clients.\n\n throw new AuthorizationError(parameters, 'Use of PKCE is required')\n }\n\n // -----------------\n // atproto extension\n // -----------------\n\n if (parameters.response_type !== 'code') {\n throw new AuthorizationError(\n parameters,\n 'atproto only supports the \"code\" response_type',\n )\n }\n\n if (!scopes.has('atproto')) {\n throw new InvalidScopeError(parameters, 'The \"atproto\" scope is required')\n } else if (scopes.has('openid')) {\n throw new InvalidScopeError(\n parameters,\n 'OpenID Connect is not compatible with atproto',\n )\n }\n\n if (parameters.code_challenge_method !== 'S256') {\n throw new AuthorizationError(\n parameters,\n 'atproto requires use of \"S256\" code_challenge_method',\n )\n }\n\n // atproto extension: if the client is not trusted, and not authenticated,\n // force users to consent to authorization requests. We do this to avoid\n // unauthenticated clients from being able to silently re-authenticate\n // users.\n if (\n !client.info.isTrusted &&\n !client.info.isFirstParty &&\n client.metadata.token_endpoint_auth_method === 'none'\n ) {\n if (parameters.prompt === 'none') {\n throw new ConsentRequiredError(\n parameters,\n 'Public clients are not allowed to use silent-sign-on',\n )\n }\n\n // force \"consent\" for unauthenticated third party clients, unless they\n // are trying to create accounts:\n if (parameters.prompt !== 'create') {\n parameters = { ...parameters, prompt: 'consent' }\n }\n }\n\n // atproto extension: ensure that the login_hint is a valid handle or DID\n // @NOTE we to allow invalid case here, which is not spec'd anywhere.\n const hint = parameters.login_hint?.toLowerCase()\n if (hint) {\n if (!isAtprotoDid(hint) && !isValidHandle(hint)) {\n throw new AuthorizationError(parameters, `Invalid login_hint \"${hint}\"`)\n }\n\n // @TODO: ensure that the account actually exists on this server (there is\n // no point in showing the UI to the user if the account does not exist).\n\n // Update the parameters to ensure the right case is used\n parameters = { ...parameters, login_hint: hint }\n }\n\n // Make sure that every nsid in the scope resolves to a valid permission set\n // lexicon\n if (parameters.scope) {\n try {\n await this.lexiconManager.getPermissionSetsFromScope(parameters.scope)\n } catch (err) {\n // Parse expected errors\n if (err instanceof LexResolverError) {\n throw new AuthorizationError(\n parameters,\n err.message,\n 'invalid_scope',\n err,\n )\n }\n\n // Unexpected error\n throw err\n }\n }\n\n return parameters\n }\n\n async get(requestUri: RequestUri, deviceId: DeviceId, clientId?: ClientId) {\n const requestId = decodeRequestUri(requestUri)\n\n const data = await this.store.readRequest(requestId)\n if (!data) throw new InvalidRequestError('Unknown request_uri')\n\n const updates: UpdateRequestData = {}\n\n try {\n if (data.sub || data.code) {\n // If an account was linked to the request, the next step is to exchange\n // the code for a token.\n throw new AccessDeniedError(\n data.parameters,\n 'This request was already authorized',\n )\n }\n\n if (data.expiresAt < new Date()) {\n throw new AccessDeniedError(data.parameters, 'This request has expired')\n } else {\n updates.expiresAt = new Date(\n Date.now() + AUTHORIZATION_INACTIVITY_TIMEOUT,\n )\n }\n\n if (clientId != null && data.clientId !== clientId) {\n throw new AccessDeniedError(\n data.parameters,\n 'This request was initiated for another client',\n )\n }\n\n if (!data.deviceId) {\n updates.deviceId = deviceId\n } else if (data.deviceId !== deviceId) {\n throw new AccessDeniedError(\n data.parameters,\n 'This request was initiated from another device',\n )\n }\n } catch (err) {\n await this.store.deleteRequest(requestId)\n throw err\n }\n\n if (Object.keys(updates).length > 0) {\n await this.store.updateRequest(requestId, updates)\n }\n\n return {\n requestUri,\n expiresAt: updates.expiresAt || data.expiresAt,\n parameters: data.parameters,\n clientId: data.clientId,\n }\n }\n\n async setAuthorized(\n requestUri: RequestUri,\n client: Client,\n account: Account,\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n scopeOverride?: string,\n ): Promise<Code> {\n const requestId = decodeRequestUri(requestUri)\n\n const data = await this.store.readRequest(requestId)\n if (!data) throw new InvalidRequestError('Unknown request_uri')\n\n let { parameters } = data\n\n try {\n if (data.expiresAt < new Date()) {\n throw new AccessDeniedError(parameters, 'This request has expired')\n }\n if (!data.deviceId) {\n throw new AccessDeniedError(\n parameters,\n 'This request was not initiated',\n )\n }\n if (data.deviceId !== deviceId) {\n throw new AccessDeniedError(\n parameters,\n 'This request was initiated from another device',\n )\n }\n if (data.sub || data.code) {\n throw new AccessDeniedError(\n parameters,\n 'This request was already authorized',\n )\n }\n\n // If a new scope value is provided, update the parameters by ensuring\n // that every existing scope in the parameters is also present in the\n // override value. This allows the user to remove scopes from the request,\n // but not to add new ones.\n if (scopeOverride != null) {\n const allowedScopes = new Set(scopeOverride.split(' '))\n const existingScopes = parameters.scope?.split(' ')\n\n // Compute the intersection of the existing scopes and the overrides.\n const newScopes = existingScopes?.filter((s) => allowedScopes.has(s))\n\n // Validate: make sure the new scopes are valid\n if (!newScopes?.includes('atproto')) {\n throw new AccessDeniedError(\n parameters,\n 'The \"atproto\" scope is required',\n )\n }\n\n parameters = { ...parameters, scope: newScopes.join(' ') }\n }\n\n // Only response_type=code is supported\n const code = await generateCode()\n\n // Bind the request to the account, preventing it from being used again.\n await this.store.updateRequest(requestId, {\n sub: account.sub,\n code,\n // Allow the client to exchange the code for a token within the next 60 seconds.\n expiresAt: new Date(Date.now() + AUTHORIZATION_INACTIVITY_TIMEOUT),\n parameters,\n })\n\n await this.hooks.onAuthorized?.call(null, {\n client,\n account,\n parameters,\n deviceId,\n deviceMetadata,\n requestId,\n })\n\n return code\n } catch (err) {\n await this.store.deleteRequest(requestId)\n throw err\n }\n }\n\n /**\n * @note If this method throws an error, any token previously generated from\n * the same `code` **must** me revoked.\n */\n public async consumeCode(code: Code): Promise<RequestDataAuthorized> {\n const result = await this.store.consumeRequestCode(code)\n if (!result) throw new InvalidGrantError('Invalid code')\n\n const { requestId, data } = result\n\n // Fool-proofing the store implementation against code replay attacks (in\n // case consumeRequestCode() does not delete the request).\n if (NODE_ENV !== 'production') {\n const result = await this.store.readRequest(requestId)\n if (result) {\n throw new Error('Invalid store implementation: request not deleted')\n }\n }\n\n if (!isRequestDataAuthorized(data) || data.code !== code) {\n // Should never happen: maybe the store implementation is faulty ?\n throw new Error('Unexpected request state')\n }\n\n if (data.expiresAt < new Date()) {\n throw new InvalidGrantError('This code has expired')\n }\n\n return data\n }\n\n async delete(requestUri: RequestUri): Promise<void> {\n const requestId = decodeRequestUri(requestUri)\n await this.store.deleteRequest(requestId)\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"send-authorization-page.d.ts","sourceRoot":"","sources":["../../../src/router/assets/send-authorization-page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAGhE,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAA;AAMpE,OAAO,EAAE,gCAAgC,EAAE,MAAM,qDAAqD,CAAA;AAItG,wBAAgB,wBAAwB,CAAC,aAAa,EAAE,aAAa,IAgBjE,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,MAAM,gCAAgC,KACrC,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"send-authorization-page.d.ts","sourceRoot":"","sources":["../../../src/router/assets/send-authorization-page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAGhE,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAA;AAMpE,OAAO,EAAE,gCAAgC,EAAE,MAAM,qDAAqD,CAAA;AAItG,wBAAgB,wBAAwB,CAAC,aAAa,EAAE,aAAa,IAgBjE,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,MAAM,gCAAgC,KACrC,OAAO,CAAC,IAAI,CAAC,CAkCjB"}
|
|
@@ -34,6 +34,7 @@ function sendAuthorizePageFactory(customization) {
|
|
|
34
34
|
scope: data.parameters.scope,
|
|
35
35
|
uiLocales: data.parameters.ui_locales,
|
|
36
36
|
loginHint: data.parameters.login_hint,
|
|
37
|
+
promptMode: data.parameters.prompt,
|
|
37
38
|
permissionSets: Object.fromEntries(data.permissionSets),
|
|
38
39
|
},
|
|
39
40
|
__sessions: data.sessions,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"send-authorization-page.js","sourceRoot":"","sources":["../../../src/router/assets/send-authorization-page.ts"],"names":[],"mappings":";;AAaA,
|
|
1
|
+
{"version":3,"file":"send-authorization-page.js","sourceRoot":"","sources":["../../../src/router/assets/send-authorization-page.ts"],"names":[],"mappings":";;AAaA,4DAqDC;AAjED,+FAAsF;AACtF,iGAAwF;AAExF,qDAAiD;AACjD,wEAAuE;AACvE,sDAAuD;AACvD,4EAA8E;AAC9E,iEAAwD;AAExD,2CAA6E;AAC7E,uCAA0C;AAE1C,SAAgB,wBAAwB,CAAC,aAA4B;IACnE,wBAAwB;IACxB,MAAM,iBAAiB,GAAG,IAAA,oDAAsB,EAAC,aAAa,CAAC,CAAA;IAC/D,MAAM,gBAAgB,GAAG,IAAA,kBAAO,EAAC,IAAA,kDAAqB,EAAC,aAAa,CAAC,CAAC,CAAA;IACtE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAA,qBAAS,EAAC,oBAAoB,CAAC,CAAA;IAC3D,MAAM,GAAG,GAAG,IAAA,mBAAQ,EAClB,mBAAO,EACP,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC,wBAAY,CAAC,CAAC,CAAC,SAAS,CACnD,CAAA;IACD,MAAM,IAAI,GAAG,aAAa,EAAE,QAAQ;QAClC,CAAC,CAAC,wDAAwD;YACxD,wEAAwE;YACxE,+CAAyB,CAAC,UAAU;QACtC,CAAC,CAAC,+CAAyB,CAAC,cAAc,CAAA;IAE5C,OAAO,KAAK,UAAU,iBAAiB,CACrC,GAAoB,EACpB,GAAmB,EACnB,IAAsC;QAEtC,MAAM,IAAA,wBAAc,EAAC,GAAG,EAAE,GAAG,CAAC,CAAA;QAE9B,MAAM,MAAM,GAAG,IAAA,wCAAoB,EAAsC;YACvE,mBAAmB,EAAE,iBAAiB;YACtC,eAAe,EAAE;gBACf,UAAU,EAAE,IAAI,CAAC,UAAU;gBAE3B,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE;gBACxB,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;gBACpC,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS;gBACzC,gBAAgB,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY;gBAE/C,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK;gBAC5B,SAAS,EAAE,IAAI,CAAC,UAAU,CAAC,UAAU;gBACrC,SAAS,EAAE,IAAI,CAAC,UAAU,CAAC,UAAU;gBACrC,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,MAAM;gBAClC,cAAc,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,cAAc,CAAC;aACxD;YACD,UAAU,EAAE,IAAI,CAAC,QAAQ;SAC1B,CAAC,CAAA;QAEF,OAAO,IAAA,8BAAW,EAAC,GAAG,EAAE;YACtB,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;YAC9C,IAAI,EAAE,IAAA,eAAI,EAAA,uBAAuB;YACjC,SAAS,EAAE;gBACT,KAAK,EAAE,+DAA+D;aACvE;YACD,GAAG;YACH,IAAI;YACJ,OAAO,EAAE,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC;YAC7B,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,gBAAgB,CAAC;SACtC,CAAC,CAAA;IACJ,CAAC,CAAA;AACH,CAAC","sourcesContent":["import type { IncomingMessage, ServerResponse } from 'node:http'\nimport { buildCustomizationCss } from '../../customization/build-customization-css.js'\nimport { buildCustomizationData } from '../../customization/build-customization-data.js'\nimport { Customization } from '../../customization/customization.js'\nimport { mergeCsp } from '../../lib/csp/index.js'\nimport { declareHydrationData } from '../../lib/html/hydration-data.js'\nimport { cssCode, html } from '../../lib/html/index.js'\nimport { CrossOriginEmbedderPolicy } from '../../lib/http/security-headers.js'\nimport { sendWebPage } from '../../lib/send-web-page.js'\nimport { AuthorizationResultAuthorizePage } from '../../result/authorization-result-authorize-page.js'\nimport { HCAPTCHA_CSP, HydrationData, SPA_CSP, getAssets } from './assets.js'\nimport { setupCsrfToken } from './csrf.js'\n\nexport function sendAuthorizePageFactory(customization: Customization) {\n // Pre-computed options:\n const customizationData = buildCustomizationData(customization)\n const customizationCss = cssCode(buildCustomizationCss(customization))\n const { scripts, styles } = getAssets('authorization-page')\n const csp = mergeCsp(\n SPA_CSP,\n customization?.hcaptcha ? HCAPTCHA_CSP : undefined,\n )\n const coep = customization?.hcaptcha\n ? // https://github.com/hCaptcha/react-hcaptcha/issues/259\n // @TODO Remove the use of `unsafeNone` once the issue above is resolved\n CrossOriginEmbedderPolicy.unsafeNone\n : CrossOriginEmbedderPolicy.credentialless\n\n return async function sendAuthorizePage(\n req: IncomingMessage,\n res: ServerResponse,\n data: AuthorizationResultAuthorizePage,\n ): Promise<void> {\n await setupCsrfToken(req, res)\n\n const script = declareHydrationData<HydrationData['authorization-page']>({\n __customizationData: customizationData,\n __authorizeData: {\n requestUri: data.requestUri,\n\n clientId: data.client.id,\n clientMetadata: data.client.metadata,\n clientTrusted: data.client.info.isTrusted,\n clientFirstParty: data.client.info.isFirstParty,\n\n scope: data.parameters.scope,\n uiLocales: data.parameters.ui_locales,\n loginHint: data.parameters.login_hint,\n promptMode: data.parameters.prompt,\n permissionSets: Object.fromEntries(data.permissionSets),\n },\n __sessions: data.sessions,\n })\n\n return sendWebPage(res, {\n meta: [{ name: 'robots', content: 'noindex' }],\n body: html`<div id=\"root\"></div>`,\n bodyAttrs: {\n class: 'bg-white text-slate-900 dark:bg-slate-900 dark:text-slate-100',\n },\n csp,\n coep,\n scripts: [script, ...scripts],\n styles: [...styles, customizationCss],\n })\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/oauth-provider",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Generic OAuth2 and OpenID Connect provider for Node.js. Currently only supports features needed for Atproto.",
|
|
6
6
|
"keywords": [
|
|
@@ -44,21 +44,21 @@
|
|
|
44
44
|
"zod": "^3.23.8",
|
|
45
45
|
"@atproto-labs/fetch": "0.2.3",
|
|
46
46
|
"@atproto-labs/fetch-node": "0.2.0",
|
|
47
|
-
"@atproto-labs/pipe": "0.1.1",
|
|
48
47
|
"@atproto-labs/simple-store": "0.3.0",
|
|
49
48
|
"@atproto-labs/simple-store-memory": "0.1.4",
|
|
50
|
-
"@atproto/
|
|
49
|
+
"@atproto-labs/pipe": "0.1.1",
|
|
51
50
|
"@atproto/did": "0.2.3",
|
|
52
51
|
"@atproto/jwk": "0.6.0",
|
|
53
52
|
"@atproto/jwk-jose": "0.1.11",
|
|
54
|
-
"@atproto/lex-document": "0.0.
|
|
55
|
-
"@atproto/lex-resolver": "0.0.
|
|
56
|
-
"@atproto/oauth-types": "0.
|
|
57
|
-
"@atproto/oauth-provider-api": "0.3.
|
|
58
|
-
"@atproto/oauth-provider-frontend": "0.2.
|
|
59
|
-
"@atproto/oauth-provider-ui": "0.
|
|
53
|
+
"@atproto/lex-document": "0.0.6",
|
|
54
|
+
"@atproto/lex-resolver": "0.0.6",
|
|
55
|
+
"@atproto/oauth-types": "0.6.0",
|
|
56
|
+
"@atproto/oauth-provider-api": "0.3.5",
|
|
57
|
+
"@atproto/oauth-provider-frontend": "0.2.6",
|
|
58
|
+
"@atproto/oauth-provider-ui": "0.4.0",
|
|
60
59
|
"@atproto/oauth-scopes": "0.3.0",
|
|
61
|
-
"@atproto/syntax": "0.4.2"
|
|
60
|
+
"@atproto/syntax": "0.4.2",
|
|
61
|
+
"@atproto/common": "^0.5.4"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@types/cookie": "^0.6.0",
|
|
@@ -15,6 +15,7 @@ export type CustomMetadata = {
|
|
|
15
15
|
/**
|
|
16
16
|
* @see {@link https://datatracker.ietf.org/doc/html/rfc8414#section-2}
|
|
17
17
|
* @see {@link https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata}
|
|
18
|
+
* @see {@link https://openid.net/specs/openid-connect-prompt-create-1_0.html}
|
|
18
19
|
*/
|
|
19
20
|
export function buildMetadata(
|
|
20
21
|
issuer: OAuthIssuerIdentifier,
|
|
@@ -84,6 +85,15 @@ export function buildMetadata(
|
|
|
84
85
|
// 'wap', LoL
|
|
85
86
|
],
|
|
86
87
|
|
|
88
|
+
// https://openid.net/specs/openid-connect-prompt-create-1_0.html
|
|
89
|
+
prompt_values_supported: [
|
|
90
|
+
'none',
|
|
91
|
+
'login',
|
|
92
|
+
'consent',
|
|
93
|
+
'select_account',
|
|
94
|
+
'create',
|
|
95
|
+
],
|
|
96
|
+
|
|
87
97
|
// https://datatracker.ietf.org/doc/html/rfc9207
|
|
88
98
|
authorization_response_iss_parameter_supported: true,
|
|
89
99
|
|
|
@@ -270,8 +270,11 @@ export class RequestManager {
|
|
|
270
270
|
)
|
|
271
271
|
}
|
|
272
272
|
|
|
273
|
-
// force "consent" for unauthenticated
|
|
274
|
-
|
|
273
|
+
// force "consent" for unauthenticated third party clients, unless they
|
|
274
|
+
// are trying to create accounts:
|
|
275
|
+
if (parameters.prompt !== 'create') {
|
|
276
|
+
parameters = { ...parameters, prompt: 'consent' }
|
|
277
|
+
}
|
|
275
278
|
}
|
|
276
279
|
|
|
277
280
|
// atproto extension: ensure that the login_hint is a valid handle or DID
|
|
@@ -46,6 +46,7 @@ export function sendAuthorizePageFactory(customization: Customization) {
|
|
|
46
46
|
scope: data.parameters.scope,
|
|
47
47
|
uiLocales: data.parameters.ui_locales,
|
|
48
48
|
loginHint: data.parameters.login_hint,
|
|
49
|
+
promptMode: data.parameters.prompt,
|
|
49
50
|
permissionSets: Object.fromEntries(data.permissionSets),
|
|
50
51
|
},
|
|
51
52
|
__sessions: data.sessions,
|