@atproto/oauth-provider 0.16.5 → 0.17.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 +32 -0
- package/dist/access-token/access-token-mode.js +2 -5
- package/dist/access-token/access-token-mode.js.map +1 -1
- package/dist/account/account-manager.js +25 -33
- package/dist/account/account-manager.js.map +1 -1
- package/dist/account/account-store.js +11 -32
- package/dist/account/account-store.js.map +1 -1
- package/dist/account/sign-in-data.js +9 -12
- package/dist/account/sign-in-data.js.map +1 -1
- package/dist/account/sign-up-input.js +14 -17
- package/dist/account/sign-up-input.js.map +1 -1
- package/dist/client/client-auth.js +1 -2
- package/dist/client/client-data.js +1 -2
- package/dist/client/client-id.js +2 -5
- package/dist/client/client-id.js.map +1 -1
- package/dist/client/client-info.js +1 -2
- package/dist/client/client-manager.js +86 -97
- package/dist/client/client-manager.js.map +1 -1
- package/dist/client/client-store.js +7 -26
- package/dist/client/client-store.js.map +1 -1
- package/dist/client/client-utils.js +10 -14
- package/dist/client/client-utils.js.map +1 -1
- package/dist/client/client.js +43 -53
- package/dist/client/client.js.map +1 -1
- package/dist/constants.js +28 -31
- package/dist/constants.js.map +1 -1
- package/dist/customization/branding.js +8 -11
- package/dist/customization/branding.js.map +1 -1
- package/dist/customization/build-customization-css.js +8 -11
- package/dist/customization/build-customization-css.js.map +1 -1
- package/dist/customization/build-customization-data.js +1 -4
- package/dist/customization/build-customization-data.js.map +1 -1
- package/dist/customization/colors.js +11 -14
- package/dist/customization/colors.js.map +1 -1
- package/dist/customization/customization.js +8 -11
- package/dist/customization/customization.js.map +1 -1
- package/dist/customization/links.js +7 -10
- package/dist/customization/links.js.map +1 -1
- package/dist/device/device-data.js +7 -10
- package/dist/device/device-data.js.map +1 -1
- package/dist/device/device-id.js +11 -16
- package/dist/device/device-id.js.map +1 -1
- package/dist/device/device-manager.js +32 -38
- package/dist/device/device-manager.js.map +1 -1
- package/dist/device/device-store.js +7 -25
- package/dist/device/device-store.js.map +1 -1
- package/dist/device/session-id.js +9 -13
- package/dist/device/session-id.js.map +1 -1
- package/dist/dpop/dpop-manager.d.ts +3 -3
- package/dist/dpop/dpop-manager.js +38 -43
- package/dist/dpop/dpop-manager.js.map +1 -1
- package/dist/dpop/dpop-nonce.d.ts +2 -2
- package/dist/dpop/dpop-nonce.d.ts.map +1 -1
- package/dist/dpop/dpop-nonce.js +14 -18
- package/dist/dpop/dpop-nonce.js.map +1 -1
- package/dist/dpop/dpop-proof.js +1 -2
- package/dist/errors/access-denied-error.js +2 -6
- package/dist/errors/access-denied-error.js.map +1 -1
- package/dist/errors/account-selection-required-error.js +2 -6
- package/dist/errors/account-selection-required-error.js.map +1 -1
- package/dist/errors/authorization-error.js +7 -12
- package/dist/errors/authorization-error.js.map +1 -1
- package/dist/errors/consent-required-error.js +2 -6
- package/dist/errors/consent-required-error.js.map +1 -1
- package/dist/errors/error-parser.js +14 -18
- package/dist/errors/error-parser.js.map +1 -1
- package/dist/errors/handle-unavailable-error.js +2 -7
- package/dist/errors/handle-unavailable-error.js.map +1 -1
- package/dist/errors/invalid-authorization-details-error.js +2 -6
- package/dist/errors/invalid-authorization-details-error.js.map +1 -1
- package/dist/errors/invalid-client-error.js +2 -6
- package/dist/errors/invalid-client-error.js.map +1 -1
- package/dist/errors/invalid-client-id-error.js +2 -6
- package/dist/errors/invalid-client-id-error.js.map +1 -1
- package/dist/errors/invalid-client-metadata-error.js +7 -11
- package/dist/errors/invalid-client-metadata-error.js.map +1 -1
- package/dist/errors/invalid-credentials-error.js +2 -7
- package/dist/errors/invalid-credentials-error.js.map +1 -1
- package/dist/errors/invalid-dpop-key-binding-error.js +2 -6
- package/dist/errors/invalid-dpop-key-binding-error.js.map +1 -1
- package/dist/errors/invalid-dpop-proof-error.js +2 -6
- package/dist/errors/invalid-dpop-proof-error.js.map +1 -1
- package/dist/errors/invalid-grant-error.js +2 -6
- package/dist/errors/invalid-grant-error.js.map +1 -1
- package/dist/errors/invalid-invite-code-error.d.ts +1 -1
- package/dist/errors/invalid-invite-code-error.d.ts.map +1 -1
- package/dist/errors/invalid-invite-code-error.js +2 -6
- package/dist/errors/invalid-invite-code-error.js.map +1 -1
- package/dist/errors/invalid-redirect-uri-error.js +2 -6
- package/dist/errors/invalid-redirect-uri-error.js.map +1 -1
- package/dist/errors/invalid-request-error.js +3 -7
- package/dist/errors/invalid-request-error.js.map +1 -1
- package/dist/errors/invalid-scope-error.js +2 -6
- package/dist/errors/invalid-scope-error.js.map +1 -1
- package/dist/errors/invalid-token-error.js +10 -15
- package/dist/errors/invalid-token-error.js.map +1 -1
- package/dist/errors/login-required-error.js +2 -6
- package/dist/errors/login-required-error.js.map +1 -1
- package/dist/errors/oauth-error.js +1 -9
- package/dist/errors/oauth-error.js.map +1 -1
- package/dist/errors/second-authentication-factor-required-error.js +2 -8
- package/dist/errors/second-authentication-factor-required-error.js.map +1 -1
- package/dist/errors/unauthorized-client-error.js +2 -6
- package/dist/errors/unauthorized-client-error.js.map +1 -1
- package/dist/errors/use-dpop-nonce-error.js +4 -8
- package/dist/errors/use-dpop-nonce-error.js.map +1 -1
- package/dist/errors/www-authenticate-error.js +4 -9
- package/dist/errors/www-authenticate-error.js.map +1 -1
- package/dist/index.js +14 -30
- package/dist/index.js.map +1 -1
- package/dist/lexicon/lexicon-data.js +1 -2
- package/dist/lexicon/lexicon-getter.js +6 -10
- package/dist/lexicon/lexicon-getter.js.map +1 -1
- package/dist/lexicon/lexicon-manager.js +10 -30
- package/dist/lexicon/lexicon-manager.js.map +1 -1
- package/dist/lexicon/lexicon-store.js +5 -10
- package/dist/lexicon/lexicon-store.js.map +1 -1
- package/dist/lib/csp/index.js +3 -8
- package/dist/lib/csp/index.js.map +1 -1
- package/dist/lib/hcaptcha.js +33 -43
- package/dist/lib/hcaptcha.js.map +1 -1
- package/dist/lib/html/build-document.js +19 -24
- package/dist/lib/html/build-document.js.map +1 -1
- package/dist/lib/html/escapers.js +10 -16
- package/dist/lib/html/escapers.js.map +1 -1
- package/dist/lib/html/html.js +1 -5
- package/dist/lib/html/html.js.map +1 -1
- package/dist/lib/html/hydration-data.js +6 -10
- package/dist/lib/html/hydration-data.js.map +1 -1
- package/dist/lib/html/index.js +3 -19
- package/dist/lib/html/index.js.map +1 -1
- package/dist/lib/html/tags.js +14 -23
- package/dist/lib/html/tags.js.map +1 -1
- package/dist/lib/html/util.js +1 -4
- package/dist/lib/html/util.js.map +1 -1
- package/dist/lib/http/accept.d.ts.map +1 -1
- package/dist/lib/http/accept.js +8 -8
- package/dist/lib/http/accept.js.map +1 -1
- package/dist/lib/http/context.js +1 -4
- package/dist/lib/http/context.js.map +1 -1
- package/dist/lib/http/headers.js +1 -4
- package/dist/lib/http/headers.js.map +1 -1
- package/dist/lib/http/index.js +10 -26
- package/dist/lib/http/index.js.map +1 -1
- package/dist/lib/http/method.js +1 -4
- package/dist/lib/http/method.js.map +1 -1
- package/dist/lib/http/middleware.js +11 -17
- package/dist/lib/http/middleware.js.map +1 -1
- package/dist/lib/http/parser.js +13 -20
- package/dist/lib/http/parser.js.map +1 -1
- package/dist/lib/http/path.js +1 -4
- package/dist/lib/http/path.js.map +1 -1
- package/dist/lib/http/request.d.ts.map +1 -1
- package/dist/lib/http/request.js +32 -47
- package/dist/lib/http/request.js.map +1 -1
- package/dist/lib/http/response.js +14 -27
- package/dist/lib/http/response.js.map +1 -1
- package/dist/lib/http/route.js +9 -12
- package/dist/lib/http/route.js.map +1 -1
- package/dist/lib/http/router.js +8 -13
- package/dist/lib/http/router.js.map +1 -1
- package/dist/lib/http/security-headers.js +10 -15
- package/dist/lib/http/security-headers.js.map +1 -1
- package/dist/lib/http/stream.js +12 -20
- package/dist/lib/http/stream.js.map +1 -1
- package/dist/lib/http/types.js +1 -2
- package/dist/lib/http/url.js +1 -4
- package/dist/lib/http/url.js.map +1 -1
- package/dist/lib/nsid.js +4 -8
- package/dist/lib/nsid.js.map +1 -1
- package/dist/lib/redis.js +4 -7
- package/dist/lib/redis.js.map +1 -1
- package/dist/lib/util/authorization-header.js +11 -15
- package/dist/lib/util/authorization-header.js.map +1 -1
- package/dist/lib/util/cast.js +3 -8
- package/dist/lib/util/cast.js.map +1 -1
- package/dist/lib/util/color.js +23 -32
- package/dist/lib/util/color.js.map +1 -1
- package/dist/lib/util/crypto.js +5 -10
- package/dist/lib/util/crypto.js.map +1 -1
- package/dist/lib/util/date.js +2 -6
- package/dist/lib/util/date.js.map +1 -1
- package/dist/lib/util/error.js +5 -8
- package/dist/lib/util/error.js.map +1 -1
- package/dist/lib/util/function.js +3 -8
- package/dist/lib/util/function.js.map +1 -1
- package/dist/lib/util/locale.js +3 -6
- package/dist/lib/util/locale.js.map +1 -1
- package/dist/lib/util/object.js +1 -4
- package/dist/lib/util/object.js.map +1 -1
- package/dist/lib/util/redirect-uri.js +3 -6
- package/dist/lib/util/redirect-uri.js.map +1 -1
- package/dist/lib/util/time.js +5 -9
- package/dist/lib/util/time.js.map +1 -1
- package/dist/lib/util/type.d.ts.map +1 -1
- package/dist/lib/util/type.js +1 -5
- package/dist/lib/util/type.js.map +1 -1
- package/dist/lib/util/ui8.js +3 -8
- package/dist/lib/util/ui8.js.map +1 -1
- package/dist/lib/util/well-known.js +1 -4
- package/dist/lib/util/well-known.js.map +1 -1
- package/dist/lib/util/zod-error.js +4 -8
- package/dist/lib/util/zod-error.js.map +1 -1
- package/dist/lib/write-form-redirect.js +9 -12
- package/dist/lib/write-form-redirect.js.map +1 -1
- package/dist/lib/write-html.js +12 -15
- package/dist/lib/write-html.js.map +1 -1
- package/dist/metadata/build-metadata.js +9 -12
- package/dist/metadata/build-metadata.js.map +1 -1
- package/dist/oauth-client.js +2 -18
- package/dist/oauth-client.js.map +1 -1
- package/dist/oauth-dpop.js +2 -18
- package/dist/oauth-dpop.js.map +1 -1
- package/dist/oauth-errors.js +24 -42
- package/dist/oauth-errors.js.map +1 -1
- package/dist/oauth-hooks.js +8 -15
- package/dist/oauth-hooks.js.map +1 -1
- package/dist/oauth-middleware.js +13 -16
- package/dist/oauth-middleware.js.map +1 -1
- package/dist/oauth-provider.js +108 -125
- package/dist/oauth-provider.js.map +1 -1
- package/dist/oauth-store.js +7 -23
- package/dist/oauth-store.js.map +1 -1
- package/dist/oauth-verifier.js +41 -53
- package/dist/oauth-verifier.js.map +1 -1
- package/dist/oidc/sub.js +2 -5
- package/dist/oidc/sub.js.map +1 -1
- package/dist/replay/replay-manager.js +6 -11
- package/dist/replay/replay-manager.js.map +1 -1
- package/dist/replay/replay-store-memory.js +5 -7
- package/dist/replay/replay-store-memory.js.map +1 -1
- package/dist/replay/replay-store-redis.js +3 -8
- package/dist/replay/replay-store-redis.js.map +1 -1
- package/dist/replay/replay-store.js +3 -8
- package/dist/replay/replay-store.js.map +1 -1
- package/dist/request/code.js +10 -15
- package/dist/request/code.js.map +1 -1
- package/dist/request/request-data.js +1 -5
- package/dist/request/request-data.js.map +1 -1
- package/dist/request/request-id.js +9 -13
- package/dist/request/request-id.js.map +1 -1
- package/dist/request/request-manager.js +61 -71
- package/dist/request/request-manager.js.map +1 -1
- package/dist/request/request-store.js +9 -27
- package/dist/request/request-store.js.map +1 -1
- package/dist/request/request-uri.js +17 -23
- package/dist/request/request-uri.js.map +1 -1
- package/dist/result/authorization-redirect-parameters.js +1 -2
- package/dist/result/authorization-result-authorize-page.js +1 -2
- package/dist/result/authorization-result-redirect.js +1 -2
- package/dist/router/assets/assets-manifest.d.ts.map +1 -1
- package/dist/router/assets/assets-manifest.js +14 -15
- package/dist/router/assets/assets-manifest.js.map +1 -1
- package/dist/router/assets/assets.d.ts.map +1 -1
- package/dist/router/assets/assets.js +25 -27
- package/dist/router/assets/assets.js.map +1 -1
- package/dist/router/assets/csrf.js +16 -25
- package/dist/router/assets/csrf.js.map +1 -1
- package/dist/router/assets/send-account-page.js +3 -6
- package/dist/router/assets/send-account-page.js.map +1 -1
- package/dist/router/assets/send-authorization-page.js +3 -6
- package/dist/router/assets/send-authorization-page.js.map +1 -1
- package/dist/router/assets/send-cookie-error-page.js +3 -6
- package/dist/router/assets/send-cookie-error-page.js.map +1 -1
- package/dist/router/assets/send-error-page.js +6 -9
- package/dist/router/assets/send-error-page.js.map +1 -1
- package/dist/router/assets/send-redirect.js +12 -20
- package/dist/router/assets/send-redirect.js.map +1 -1
- package/dist/router/create-account-page-middleware.js +11 -14
- package/dist/router/create-account-page-middleware.js.map +1 -1
- package/dist/router/create-api-middleware.js +83 -90
- package/dist/router/create-api-middleware.js.map +1 -1
- package/dist/router/create-authorization-page-middleware.js +43 -46
- package/dist/router/create-authorization-page-middleware.js.map +1 -1
- package/dist/router/create-oauth-middleware.js +31 -34
- package/dist/router/create-oauth-middleware.js.map +1 -1
- package/dist/router/error-handler.js +1 -2
- package/dist/router/middleware-options.js +1 -2
- package/dist/signer/access-token-payload.js +12 -15
- package/dist/signer/access-token-payload.js.map +1 -1
- package/dist/signer/api-token-payload.js +8 -11
- package/dist/signer/api-token-payload.js.map +1 -1
- package/dist/signer/signer.js +11 -17
- package/dist/signer/signer.js.map +1 -1
- package/dist/token/refresh-token.js +10 -15
- package/dist/token/refresh-token.js.map +1 -1
- package/dist/token/token-claims.js +1 -2
- package/dist/token/token-data.js +1 -2
- package/dist/token/token-id.js +10 -15
- package/dist/token/token-id.js.map +1 -1
- package/dist/token/token-manager.js +40 -51
- package/dist/token/token-manager.js.map +1 -1
- package/dist/token/token-store.js +7 -25
- package/dist/token/token-store.js.map +1 -1
- package/dist/types/authorization-response-error.js +8 -12
- package/dist/types/authorization-response-error.js.map +1 -1
- package/dist/types/color-hue.js +2 -5
- package/dist/types/color-hue.js.map +1 -1
- package/dist/types/email-otp.js +2 -5
- package/dist/types/email-otp.js.map +1 -1
- package/dist/types/email.js +6 -9
- package/dist/types/email.js.map +1 -1
- package/dist/types/handle.js +6 -9
- package/dist/types/handle.js.map +1 -1
- package/dist/types/invite-code.js +2 -5
- package/dist/types/invite-code.js.map +1 -1
- package/dist/types/par-response-error.js +5 -9
- package/dist/types/par-response-error.js.map +1 -1
- package/dist/types/password.js +3 -6
- package/dist/types/password.js.map +1 -1
- package/dist/types/rgb-color.js +7 -10
- package/dist/types/rgb-color.js.map +1 -1
- package/package.json +20 -22
- package/src/dpop/dpop-nonce.ts +1 -1
- package/src/errors/invalid-invite-code-error.ts +1 -1
- package/src/lib/http/accept.ts +4 -1
- package/src/lib/http/request.ts +4 -1
- package/src/lib/util/type.ts +0 -1
- package/src/router/assets/assets-manifest.ts +3 -1
- package/src/router/assets/assets.ts +2 -0
- package/tsconfig.build.tsbuildinfo +1 -1
package/dist/oauth-provider.js
CHANGED
|
@@ -1,72 +1,56 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const request_uri_js_1 = require("./request/request-uri.js");
|
|
41
|
-
const token_manager_js_1 = require("./token/token-manager.js");
|
|
42
|
-
const token_store_js_1 = require("./token/token-store.js");
|
|
43
|
-
const par_response_error_js_1 = require("./types/par-response-error.js");
|
|
44
|
-
class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
45
|
-
accessTokenMode;
|
|
46
|
-
hooks;
|
|
47
|
-
metadata;
|
|
48
|
-
customization;
|
|
49
|
-
authenticationMaxAge;
|
|
50
|
-
accountManager;
|
|
51
|
-
deviceManager;
|
|
52
|
-
clientManager;
|
|
53
|
-
lexiconManager;
|
|
54
|
-
requestManager;
|
|
55
|
-
tokenManager;
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { Keyset } from '@atproto/jwk';
|
|
3
|
+
import { LexResolver } from '@atproto/lex-resolver';
|
|
4
|
+
import { CLIENT_ASSERTION_TYPE_JWT_BEARER, atprotoLoopbackClientMetadata, oauthAuthorizationRequestParametersSchema, } from '@atproto/oauth-types';
|
|
5
|
+
import { safeFetchWrap } from '@atproto-labs/fetch-node';
|
|
6
|
+
import { SimpleStoreMemory } from '@atproto-labs/simple-store-memory';
|
|
7
|
+
import { AccessTokenMode } from './access-token/access-token-mode.js';
|
|
8
|
+
import { AccountManager } from './account/account-manager.js';
|
|
9
|
+
import { asAccountStore, } from './account/account-store.js';
|
|
10
|
+
import { ClientManager, } from './client/client-manager.js';
|
|
11
|
+
import { ifClientStore } from './client/client-store.js';
|
|
12
|
+
import { AUTHENTICATION_MAX_AGE, CONFIDENTIAL_CLIENT_REFRESH_LIFETIME, CONFIDENTIAL_CLIENT_SESSION_LIFETIME, PUBLIC_CLIENT_REFRESH_LIFETIME, PUBLIC_CLIENT_SESSION_LIFETIME, TOKEN_MAX_AGE, } from './constants.js';
|
|
13
|
+
import { customizationSchema, } from './customization/customization.js';
|
|
14
|
+
import { DeviceManager, } from './device/device-manager.js';
|
|
15
|
+
import { asDeviceStore } from './device/device-store.js';
|
|
16
|
+
import { AccountSelectionRequiredError } from './errors/account-selection-required-error.js';
|
|
17
|
+
import { AuthorizationError } from './errors/authorization-error.js';
|
|
18
|
+
import { ConsentRequiredError } from './errors/consent-required-error.js';
|
|
19
|
+
import { InvalidDpopKeyBindingError } from './errors/invalid-dpop-key-binding-error.js';
|
|
20
|
+
import { InvalidDpopProofError } from './errors/invalid-dpop-proof-error.js';
|
|
21
|
+
import { InvalidGrantError } from './errors/invalid-grant-error.js';
|
|
22
|
+
import { InvalidRequestError } from './errors/invalid-request-error.js';
|
|
23
|
+
import { LoginRequiredError } from './errors/login-required-error.js';
|
|
24
|
+
import { LexiconManager } from './lexicon/lexicon-manager.js';
|
|
25
|
+
import { asLexiconStore } from './lexicon/lexicon-store.js';
|
|
26
|
+
import { dateToRelativeSeconds } from './lib/util/date.js';
|
|
27
|
+
import { formatError } from './lib/util/error.js';
|
|
28
|
+
import { buildMetadata } from './metadata/build-metadata.js';
|
|
29
|
+
import { OAuthVerifier, } from './oauth-verifier.js';
|
|
30
|
+
import { ifReplayStore } from './replay/replay-store.js';
|
|
31
|
+
import { codeSchema } from './request/code.js';
|
|
32
|
+
import { RequestManager } from './request/request-manager.js';
|
|
33
|
+
import { asRequestStore } from './request/request-store.js';
|
|
34
|
+
import { parseRequestUri } from './request/request-uri.js';
|
|
35
|
+
import { TokenManager } from './token/token-manager.js';
|
|
36
|
+
import { asTokenStore, refreshTokenSchema, } from './token/token-store.js';
|
|
37
|
+
import { isPARResponseError } from './types/par-response-error.js';
|
|
38
|
+
export { AccessTokenMode, Keyset, LexResolver };
|
|
39
|
+
export class OAuthProvider extends OAuthVerifier {
|
|
56
40
|
constructor({
|
|
57
41
|
// OAuthProviderConfig
|
|
58
|
-
authenticationMaxAge =
|
|
59
|
-
lexResolver = new
|
|
42
|
+
authenticationMaxAge = AUTHENTICATION_MAX_AGE, tokenMaxAge = TOKEN_MAX_AGE, accessTokenMode = AccessTokenMode.stateless, metadata, safeFetch = safeFetchWrap(), store, // compound store implementation
|
|
43
|
+
lexResolver = new LexResolver({ fetch: safeFetch }),
|
|
60
44
|
// Required stores
|
|
61
|
-
accountStore =
|
|
45
|
+
accountStore = asAccountStore(store), deviceStore = asDeviceStore(store), lexiconStore = asLexiconStore(store), tokenStore = asTokenStore(store), requestStore = asRequestStore(store),
|
|
62
46
|
// Optional stores
|
|
63
|
-
clientStore =
|
|
47
|
+
clientStore = ifClientStore(store), replayStore = ifReplayStore(store), clientJwksCache = new SimpleStoreMemory({
|
|
64
48
|
maxSize: 50_000_000,
|
|
65
49
|
ttl: 600e3,
|
|
66
|
-
}), clientMetadataCache = new
|
|
50
|
+
}), clientMetadataCache = new SimpleStoreMemory({
|
|
67
51
|
maxSize: 50_000_000,
|
|
68
52
|
ttl: 600e3,
|
|
69
|
-
}), loopbackMetadata =
|
|
53
|
+
}), loopbackMetadata = atprotoLoopbackClientMetadata,
|
|
70
54
|
// OAuthHooks &
|
|
71
55
|
// OAuthVerifierOptions &
|
|
72
56
|
// DeviceManagerOptions &
|
|
@@ -81,9 +65,9 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
81
65
|
this.hooks = rest;
|
|
82
66
|
this.accessTokenMode = accessTokenMode;
|
|
83
67
|
this.authenticationMaxAge = authenticationMaxAge;
|
|
84
|
-
this.metadata =
|
|
85
|
-
this.customization =
|
|
86
|
-
this.deviceManager = new
|
|
68
|
+
this.metadata = buildMetadata(this.issuer, this.keyset, metadata);
|
|
69
|
+
this.customization = customizationSchema.parse(rest);
|
|
70
|
+
this.deviceManager = new DeviceManager(deviceStore, {
|
|
87
71
|
...rest,
|
|
88
72
|
cookie: {
|
|
89
73
|
...rest.cookie,
|
|
@@ -94,11 +78,11 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
94
78
|
secure: !this.issuer.startsWith('http:'),
|
|
95
79
|
},
|
|
96
80
|
});
|
|
97
|
-
this.accountManager = new
|
|
98
|
-
this.clientManager = new
|
|
99
|
-
this.lexiconManager = new
|
|
100
|
-
this.requestManager = new
|
|
101
|
-
this.tokenManager = new
|
|
81
|
+
this.accountManager = new AccountManager(this.issuer, accountStore, this.hooks, this.customization);
|
|
82
|
+
this.clientManager = new ClientManager(this.metadata, this.keyset, this.hooks, clientStore || null, loopbackMetadata || null, safeFetch, clientJwksCache, clientMetadataCache);
|
|
83
|
+
this.lexiconManager = new LexiconManager(lexiconStore, lexResolver);
|
|
84
|
+
this.requestManager = new RequestManager(requestStore, this.lexiconManager, this.signer, this.metadata, this.hooks);
|
|
85
|
+
this.tokenManager = new TokenManager(tokenStore, this.lexiconManager, this.signer, this.hooks, this.accessTokenMode, tokenMaxAge);
|
|
102
86
|
}
|
|
103
87
|
get jwks() {
|
|
104
88
|
return this.keyset.publicJwks;
|
|
@@ -130,10 +114,10 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
130
114
|
if (client.metadata.dpop_bound_access_tokens &&
|
|
131
115
|
!dpopProof &&
|
|
132
116
|
!options?.allowMissingDpopProof) {
|
|
133
|
-
throw new
|
|
117
|
+
throw new InvalidDpopProofError('DPoP proof required');
|
|
134
118
|
}
|
|
135
119
|
if (dpopProof && !client.metadata.dpop_bound_access_tokens) {
|
|
136
|
-
throw new
|
|
120
|
+
throw new InvalidDpopProofError('DPoP proof not allowed for this client');
|
|
137
121
|
}
|
|
138
122
|
const clientAuth = await client.authenticate(clientCredentials, {
|
|
139
123
|
authorizationServerIdentifier: this.issuer,
|
|
@@ -141,7 +125,7 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
141
125
|
if (clientAuth.method === 'private_key_jwt') {
|
|
142
126
|
// Clients MUST NOT use their client assertion key to sign DPoP proofs
|
|
143
127
|
if (dpopProof && clientAuth.jkt === dpopProof.jkt) {
|
|
144
|
-
throw new
|
|
128
|
+
throw new InvalidRequestError('The DPoP proof must be signed with a different key than the client assertion');
|
|
145
129
|
}
|
|
146
130
|
// https://www.rfc-editor.org/rfc/rfc7523.html#section-3
|
|
147
131
|
// > 7. [...] The authorization server MAY ensure that JWTs are not
|
|
@@ -150,7 +134,7 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
150
134
|
// > on the applicable "exp" instant.
|
|
151
135
|
const unique = await this.replayManager.uniqueAuth(clientAuth.jti, client.id, clientAuth.exp);
|
|
152
136
|
if (!unique) {
|
|
153
|
-
throw new
|
|
137
|
+
throw new InvalidGrantError(`${clientAuth.method} jti reused`);
|
|
154
138
|
}
|
|
155
139
|
}
|
|
156
140
|
return { client, clientAuth };
|
|
@@ -159,16 +143,16 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
159
143
|
const { payload } = await client.decodeRequestObject(input.request, this.issuer);
|
|
160
144
|
const { jti } = payload;
|
|
161
145
|
if (!jti) {
|
|
162
|
-
throw new
|
|
146
|
+
throw new InvalidRequestError('Request object payload must contain a "jti" claim');
|
|
163
147
|
}
|
|
164
148
|
if (!(await this.replayManager.uniqueJar(jti, client.id))) {
|
|
165
|
-
throw new
|
|
149
|
+
throw new InvalidRequestError('Request object was replayed');
|
|
166
150
|
}
|
|
167
|
-
const parameters = await
|
|
151
|
+
const parameters = await oauthAuthorizationRequestParametersSchema
|
|
168
152
|
.parseAsync(payload)
|
|
169
153
|
.catch((err) => {
|
|
170
|
-
const msg =
|
|
171
|
-
throw new
|
|
154
|
+
const msg = formatError(err, 'Invalid parameters in JAR');
|
|
155
|
+
throw new InvalidRequestError(msg, err);
|
|
172
156
|
});
|
|
173
157
|
return parameters;
|
|
174
158
|
}
|
|
@@ -199,18 +183,18 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
199
183
|
}
|
|
200
184
|
else {
|
|
201
185
|
if (!client.metadata.dpop_bound_access_tokens) {
|
|
202
|
-
throw new
|
|
186
|
+
throw new InvalidRequestError('DPoP bound access tokens are not enabled for this client');
|
|
203
187
|
}
|
|
204
188
|
// Proof is optional if the dpop_jkt is provided, but if it is provided,
|
|
205
189
|
// it must match the DPoP proof JKT.
|
|
206
190
|
if (dpopProof && dpopProof.jkt !== parameters.dpop_jkt) {
|
|
207
|
-
throw new
|
|
191
|
+
throw new InvalidDpopKeyBindingError();
|
|
208
192
|
}
|
|
209
193
|
}
|
|
210
194
|
const { requestUri, expiresAt } = await this.requestManager.createAuthorizationRequest(client, clientAuth, parameters, null);
|
|
211
195
|
return {
|
|
212
196
|
request_uri: requestUri,
|
|
213
|
-
expires_in:
|
|
197
|
+
expires_in: dateToRelativeSeconds(expiresAt),
|
|
214
198
|
};
|
|
215
199
|
}
|
|
216
200
|
catch (err) {
|
|
@@ -218,8 +202,8 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
218
202
|
// > Since initial processing of the pushed authorization request does not
|
|
219
203
|
// > involve resource owner interaction, error codes related to user
|
|
220
204
|
// > interaction, such as "access_denied", are never returned.
|
|
221
|
-
if (err instanceof
|
|
222
|
-
throw new
|
|
205
|
+
if (err instanceof AuthorizationError && !isPARResponseError(err.error)) {
|
|
206
|
+
throw new InvalidRequestError(err.error_description, err);
|
|
223
207
|
}
|
|
224
208
|
throw err;
|
|
225
209
|
}
|
|
@@ -227,7 +211,7 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
227
211
|
async processAuthorizationRequest(client, deviceId, query) {
|
|
228
212
|
// PAR
|
|
229
213
|
if ('request_uri' in query) {
|
|
230
|
-
const requestUri =
|
|
214
|
+
const requestUri = parseRequestUri(query.request_uri, {
|
|
231
215
|
path: ['query', 'request_uri'],
|
|
232
216
|
});
|
|
233
217
|
return this.requestManager.get(requestUri, deviceId, client.id);
|
|
@@ -261,7 +245,7 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
261
245
|
const throwAuthorizationError = 'redirect_uri' in query
|
|
262
246
|
? (err) => {
|
|
263
247
|
// https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-11#section-4.1.2.1
|
|
264
|
-
throw
|
|
248
|
+
throw AuthorizationError.from(query, err);
|
|
265
249
|
}
|
|
266
250
|
: null;
|
|
267
251
|
const client = await this.clientManager
|
|
@@ -287,7 +271,7 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
287
271
|
// > selection choice made by the End-User, it MUST return an error,
|
|
288
272
|
// > typically account_selection_required.
|
|
289
273
|
if (parameters.prompt === 'select_account' && !sessions.length) {
|
|
290
|
-
throw new
|
|
274
|
+
throw new AccountSelectionRequiredError(parameters);
|
|
291
275
|
}
|
|
292
276
|
// prompt=none
|
|
293
277
|
//
|
|
@@ -302,17 +286,17 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
302
286
|
if (parameters.prompt === 'none') {
|
|
303
287
|
const ssoSessions = sessions.filter(matchesHint, parameters);
|
|
304
288
|
if (ssoSessions.length > 1) {
|
|
305
|
-
throw new
|
|
289
|
+
throw new AccountSelectionRequiredError(parameters);
|
|
306
290
|
}
|
|
307
291
|
if (ssoSessions.length < 1) {
|
|
308
|
-
throw new
|
|
292
|
+
throw new LoginRequiredError(parameters);
|
|
309
293
|
}
|
|
310
294
|
const ssoSession = ssoSessions[0];
|
|
311
295
|
if (ssoSession.loginRequired) {
|
|
312
|
-
throw new
|
|
296
|
+
throw new LoginRequiredError(parameters);
|
|
313
297
|
}
|
|
314
298
|
if (ssoSession.consentRequired) {
|
|
315
|
-
throw new
|
|
299
|
+
throw new ConsentRequiredError(parameters);
|
|
316
300
|
}
|
|
317
301
|
const code = await this.requestManager.setAuthorized(requestUri, client, ssoSession.account, deviceId, deviceMetadata);
|
|
318
302
|
return { issuer, parameters, redirect: { code } };
|
|
@@ -342,7 +326,7 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
342
326
|
permissionSets: await this.lexiconManager
|
|
343
327
|
.getPermissionSetsFromScope(parameters.scope)
|
|
344
328
|
.catch((cause) => {
|
|
345
|
-
throw new
|
|
329
|
+
throw new AuthorizationError(parameters, 'Unable to retrieve permission sets', 'invalid_scope', cause);
|
|
346
330
|
}),
|
|
347
331
|
};
|
|
348
332
|
}
|
|
@@ -356,16 +340,16 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
356
340
|
// @TODO Maybe move this entire code to the /authorize endpoint
|
|
357
341
|
// (allowing to log this error)
|
|
358
342
|
}
|
|
359
|
-
throw
|
|
343
|
+
throw AuthorizationError.from(parameters, err);
|
|
360
344
|
}
|
|
361
345
|
}
|
|
362
346
|
async token(clientCredentials, clientMetadata, request, dpopProof) {
|
|
363
347
|
const { client, clientAuth } = await this.authenticateClient(clientCredentials, dpopProof);
|
|
364
348
|
if (!this.metadata.grant_types_supported?.includes(request.grant_type)) {
|
|
365
|
-
throw new
|
|
349
|
+
throw new InvalidGrantError(`Grant type "${request.grant_type}" is not supported by the server`);
|
|
366
350
|
}
|
|
367
351
|
if (!client.metadata.grant_types.includes(request.grant_type)) {
|
|
368
|
-
throw new
|
|
352
|
+
throw new InvalidGrantError(`"${request.grant_type}" grant type is not allowed for this client`);
|
|
369
353
|
}
|
|
370
354
|
if (request.grant_type === 'authorization_code') {
|
|
371
355
|
return this.authorizationCodeGrant(client, clientAuth, clientMetadata, request, dpopProof);
|
|
@@ -373,23 +357,23 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
373
357
|
if (request.grant_type === 'refresh_token') {
|
|
374
358
|
return this.refreshTokenGrant(client, clientAuth, clientMetadata, request, dpopProof);
|
|
375
359
|
}
|
|
376
|
-
throw new
|
|
360
|
+
throw new InvalidGrantError(`Grant type "${request.grant_type}" not supported`);
|
|
377
361
|
}
|
|
378
362
|
async compareClientAuth(client, clientAuth, dpopProof, initial) {
|
|
379
363
|
// Fool proofing, ensure that the client is authenticating using the right method
|
|
380
364
|
if (clientAuth.method !== client.metadata.token_endpoint_auth_method) {
|
|
381
|
-
throw new
|
|
365
|
+
throw new InvalidGrantError(`Client authentication method mismatch (expected ${client.metadata.token_endpoint_auth_method}, got ${clientAuth.method})`);
|
|
382
366
|
}
|
|
383
367
|
if (initial.clientId !== client.id) {
|
|
384
|
-
throw new
|
|
368
|
+
throw new InvalidGrantError(`Token was not issued to this client`);
|
|
385
369
|
}
|
|
386
370
|
const { parameters } = initial;
|
|
387
371
|
if (parameters.dpop_jkt) {
|
|
388
372
|
if (!dpopProof) {
|
|
389
|
-
throw new
|
|
373
|
+
throw new InvalidGrantError(`DPoP proof is required for this request`);
|
|
390
374
|
}
|
|
391
375
|
else if (parameters.dpop_jkt !== dpopProof.jkt) {
|
|
392
|
-
throw new
|
|
376
|
+
throw new InvalidGrantError(`DPoP proof does not match the expected JKT`);
|
|
393
377
|
}
|
|
394
378
|
}
|
|
395
379
|
if (!initial.clientAuth) {
|
|
@@ -402,15 +386,15 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
402
386
|
return;
|
|
403
387
|
}
|
|
404
388
|
switch (initial.clientAuth.method) {
|
|
405
|
-
case
|
|
389
|
+
case CLIENT_ASSERTION_TYPE_JWT_BEARER: // LEGACY
|
|
406
390
|
case 'private_key_jwt':
|
|
407
391
|
if (clientAuth.method !== 'private_key_jwt') {
|
|
408
|
-
throw new
|
|
392
|
+
throw new InvalidGrantError(`Client authentication method mismatch (expected ${initial.clientAuth.method})`);
|
|
409
393
|
}
|
|
410
394
|
if (clientAuth.kid !== initial.clientAuth.kid ||
|
|
411
395
|
clientAuth.alg !== initial.clientAuth.alg ||
|
|
412
396
|
clientAuth.jkt !== initial.clientAuth.jkt) {
|
|
413
|
-
throw new
|
|
397
|
+
throw new InvalidGrantError(`The session was initiated with a different key than the client assertion currently used`);
|
|
414
398
|
}
|
|
415
399
|
break;
|
|
416
400
|
case 'none':
|
|
@@ -418,17 +402,17 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
418
402
|
// the session was initially created without client authentication.
|
|
419
403
|
break;
|
|
420
404
|
default:
|
|
421
|
-
throw new
|
|
405
|
+
throw new InvalidGrantError(
|
|
422
406
|
// @ts-expect-error (future proof, backwards compatibility)
|
|
423
407
|
`Invalid method "${initial.clientAuth.method}"`);
|
|
424
408
|
}
|
|
425
409
|
}
|
|
426
410
|
async authorizationCodeGrant(client, clientAuth, clientMetadata, input, dpopProof) {
|
|
427
|
-
const code = await
|
|
411
|
+
const code = await codeSchema
|
|
428
412
|
.parseAsync(input.code, { path: ['code'] })
|
|
429
413
|
.catch((err) => {
|
|
430
|
-
const msg =
|
|
431
|
-
throw new
|
|
414
|
+
const msg = formatError(err, 'Invalid code');
|
|
415
|
+
throw new InvalidGrantError(msg, err);
|
|
432
416
|
});
|
|
433
417
|
const data = await this.requestManager
|
|
434
418
|
.consumeCode(code)
|
|
@@ -451,7 +435,7 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
451
435
|
}
|
|
452
436
|
}
|
|
453
437
|
}
|
|
454
|
-
throw
|
|
438
|
+
throw InvalidGrantError.from(err, `Invalid code`);
|
|
455
439
|
});
|
|
456
440
|
// @NOTE at this point, the request data was removed from the store and only
|
|
457
441
|
// exists in memory here (in the "data" variable). Because of this, any
|
|
@@ -471,29 +455,29 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
471
455
|
}
|
|
472
456
|
async validateCodeGrant(parameters, input) {
|
|
473
457
|
if (parameters.redirect_uri !== input.redirect_uri) {
|
|
474
|
-
throw new
|
|
458
|
+
throw new InvalidGrantError('The redirect_uri parameter must match the one used in the authorization request');
|
|
475
459
|
}
|
|
476
460
|
if (parameters.code_challenge) {
|
|
477
461
|
if (!input.code_verifier) {
|
|
478
|
-
throw new
|
|
462
|
+
throw new InvalidGrantError('code_verifier is required');
|
|
479
463
|
}
|
|
480
464
|
if (input.code_verifier.length < 43) {
|
|
481
|
-
throw new
|
|
465
|
+
throw new InvalidGrantError('code_verifier too short');
|
|
482
466
|
}
|
|
483
467
|
switch (parameters.code_challenge_method) {
|
|
484
468
|
case undefined: // default is "plain"
|
|
485
469
|
case 'plain':
|
|
486
470
|
if (parameters.code_challenge !== input.code_verifier) {
|
|
487
|
-
throw new
|
|
471
|
+
throw new InvalidGrantError('Invalid code_verifier');
|
|
488
472
|
}
|
|
489
473
|
break;
|
|
490
474
|
case 'S256': {
|
|
491
475
|
const inputChallenge = Buffer.from(parameters.code_challenge, 'base64');
|
|
492
|
-
const computedChallenge =
|
|
476
|
+
const computedChallenge = createHash('sha256')
|
|
493
477
|
.update(input.code_verifier)
|
|
494
478
|
.digest();
|
|
495
479
|
if (inputChallenge.compare(computedChallenge) !== 0) {
|
|
496
|
-
throw new
|
|
480
|
+
throw new InvalidGrantError('Invalid code_verifier');
|
|
497
481
|
}
|
|
498
482
|
break;
|
|
499
483
|
}
|
|
@@ -503,19 +487,19 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
503
487
|
}
|
|
504
488
|
const unique = await this.replayManager.uniqueCodeChallenge(parameters.code_challenge);
|
|
505
489
|
if (!unique) {
|
|
506
|
-
throw new
|
|
490
|
+
throw new InvalidGrantError('Code challenge already used');
|
|
507
491
|
}
|
|
508
492
|
}
|
|
509
493
|
else if (input.code_verifier !== undefined) {
|
|
510
|
-
throw new
|
|
494
|
+
throw new InvalidRequestError("code_challenge parameter wasn't provided");
|
|
511
495
|
}
|
|
512
496
|
}
|
|
513
497
|
async refreshTokenGrant(client, clientAuth, clientMetadata, input, dpopProof) {
|
|
514
|
-
const refreshToken = await
|
|
498
|
+
const refreshToken = await refreshTokenSchema
|
|
515
499
|
.parseAsync(input.refresh_token, { path: ['refresh_token'] })
|
|
516
500
|
.catch((err) => {
|
|
517
|
-
const msg =
|
|
518
|
-
throw new
|
|
501
|
+
const msg = formatError(err, 'Invalid refresh token');
|
|
502
|
+
throw new InvalidGrantError(msg, err);
|
|
519
503
|
});
|
|
520
504
|
const tokenInfo = await this.tokenManager.consumeRefreshToken(refreshToken);
|
|
521
505
|
try {
|
|
@@ -532,17 +516,17 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
532
516
|
async validateRefreshGrant(client, clientAuth, data) {
|
|
533
517
|
const [sessionLifetime, refreshLifetime] = clientAuth.method !== 'none' || client.info.isFirstParty
|
|
534
518
|
? [
|
|
535
|
-
|
|
536
|
-
|
|
519
|
+
CONFIDENTIAL_CLIENT_SESSION_LIFETIME,
|
|
520
|
+
CONFIDENTIAL_CLIENT_REFRESH_LIFETIME,
|
|
537
521
|
]
|
|
538
|
-
: [
|
|
522
|
+
: [PUBLIC_CLIENT_SESSION_LIFETIME, PUBLIC_CLIENT_REFRESH_LIFETIME];
|
|
539
523
|
const sessionAge = Date.now() - data.createdAt.getTime();
|
|
540
524
|
if (sessionAge > sessionLifetime) {
|
|
541
|
-
throw new
|
|
525
|
+
throw new InvalidGrantError(`Session expired`);
|
|
542
526
|
}
|
|
543
527
|
const refreshAge = Date.now() - data.updatedAt.getTime();
|
|
544
528
|
if (refreshAge > refreshLifetime) {
|
|
545
|
-
throw new
|
|
529
|
+
throw new InvalidGrantError(`Refresh token expired`);
|
|
546
530
|
}
|
|
547
531
|
}
|
|
548
532
|
/**
|
|
@@ -566,7 +550,7 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
566
550
|
}
|
|
567
551
|
async decodeToken(tokenType, token, dpopProof) {
|
|
568
552
|
const tokenPayload = await super.decodeToken(tokenType, token, dpopProof);
|
|
569
|
-
if (this.accessTokenMode !==
|
|
553
|
+
if (this.accessTokenMode !== AccessTokenMode.stateless) {
|
|
570
554
|
// @NOTE in non stateless mode, some claims can be omitted (most notably
|
|
571
555
|
// "scope"). We load the token claims here (allowing to ensure that the
|
|
572
556
|
// token is still valid, and to retrieve a (potentially updated) set of
|
|
@@ -577,7 +561,6 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
|
577
561
|
return tokenPayload;
|
|
578
562
|
}
|
|
579
563
|
}
|
|
580
|
-
exports.OAuthProvider = OAuthProvider;
|
|
581
564
|
function matchesHint({ account }) {
|
|
582
565
|
const hint = this.login_hint;
|
|
583
566
|
if (!hint)
|