@atproto/oauth-provider 0.19.9 → 0.20.1
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 +55 -0
- package/dist/account/account-manager.d.ts +11 -11
- package/dist/account/account-manager.d.ts.map +1 -1
- package/dist/account/account-manager.js.map +1 -1
- package/dist/account/account-store.d.ts +5 -10
- package/dist/account/account-store.d.ts.map +1 -1
- package/dist/account/account-store.js +0 -5
- package/dist/account/account-store.js.map +1 -1
- package/dist/client/client-auth.d.ts +1 -1
- package/dist/client/client-auth.d.ts.map +1 -1
- package/dist/client/client-auth.js.map +1 -1
- package/dist/client/client-data.d.ts +2 -2
- package/dist/client/client-data.d.ts.map +1 -1
- package/dist/client/client-data.js.map +1 -1
- package/dist/client/client-id.d.ts +1 -1
- package/dist/client/client-id.d.ts.map +1 -1
- package/dist/client/client-id.js.map +1 -1
- package/dist/client/client-manager.d.ts +8 -8
- package/dist/client/client-manager.d.ts.map +1 -1
- package/dist/client/client-manager.js +1 -1
- package/dist/client/client-manager.js.map +1 -1
- package/dist/client/client-store.d.ts +4 -6
- package/dist/client/client-store.d.ts.map +1 -1
- package/dist/client/client-store.js +0 -3
- package/dist/client/client-store.js.map +1 -1
- package/dist/client/client-utils.d.ts +1 -1
- package/dist/client/client-utils.d.ts.map +1 -1
- package/dist/client/client-utils.js.map +1 -1
- package/dist/client/client.d.ts +6 -6
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +1 -1
- package/dist/client/client.js.map +1 -1
- package/dist/customization/branding.d.ts +1 -1
- package/dist/customization/branding.d.ts.map +1 -1
- package/dist/customization/branding.js.map +1 -1
- package/dist/customization/build-customization-css.d.ts +1 -1
- package/dist/customization/build-customization-css.d.ts.map +1 -1
- package/dist/customization/build-customization-css.js.map +1 -1
- package/dist/customization/customization.d.ts +1 -1
- package/dist/customization/customization.d.ts.map +1 -1
- package/dist/customization/customization.js.map +1 -1
- package/dist/device/device-data.d.ts +2 -0
- package/dist/device/device-data.d.ts.map +1 -1
- package/dist/device/device-data.js.map +1 -1
- package/dist/device/device-id.js +1 -1
- package/dist/device/device-id.js.map +1 -1
- package/dist/device/device-manager.d.ts +3 -3
- package/dist/device/device-manager.d.ts.map +1 -1
- package/dist/device/device-manager.js +1 -1
- package/dist/device/device-manager.js.map +1 -1
- package/dist/device/device-store.d.ts +5 -7
- package/dist/device/device-store.d.ts.map +1 -1
- package/dist/device/device-store.js +0 -4
- package/dist/device/device-store.js.map +1 -1
- package/dist/device/session-id.d.ts.map +1 -1
- package/dist/device/session-id.js +1 -1
- package/dist/device/session-id.js.map +1 -1
- package/dist/dpop/dpop-manager.d.ts +2 -2
- package/dist/dpop/dpop-manager.d.ts.map +1 -1
- package/dist/dpop/dpop-manager.js +1 -1
- package/dist/dpop/dpop-manager.js.map +1 -1
- package/dist/dpop/dpop-nonce.js +1 -1
- package/dist/dpop/dpop-nonce.js.map +1 -1
- package/dist/errors/access-denied-error.d.ts +1 -1
- package/dist/errors/access-denied-error.d.ts.map +1 -1
- package/dist/errors/access-denied-error.js.map +1 -1
- package/dist/errors/account-selection-required-error.d.ts +1 -1
- package/dist/errors/account-selection-required-error.d.ts.map +1 -1
- package/dist/errors/account-selection-required-error.js.map +1 -1
- package/dist/errors/authorization-error.d.ts +2 -2
- package/dist/errors/authorization-error.d.ts.map +1 -1
- package/dist/errors/authorization-error.js.map +1 -1
- package/dist/errors/consent-required-error.d.ts +1 -1
- package/dist/errors/consent-required-error.d.ts.map +1 -1
- package/dist/errors/consent-required-error.js.map +1 -1
- package/dist/errors/handle-unavailable-error.d.ts +1 -1
- package/dist/errors/handle-unavailable-error.d.ts.map +1 -1
- package/dist/errors/handle-unavailable-error.js.map +1 -1
- package/dist/errors/invalid-authorization-details-error.d.ts +1 -1
- package/dist/errors/invalid-authorization-details-error.d.ts.map +1 -1
- package/dist/errors/invalid-authorization-details-error.js.map +1 -1
- package/dist/errors/invalid-client-metadata-error.js +1 -1
- package/dist/errors/invalid-client-metadata-error.js.map +1 -1
- package/dist/errors/invalid-credentials-error.d.ts +1 -1
- package/dist/errors/invalid-credentials-error.d.ts.map +1 -1
- package/dist/errors/invalid-credentials-error.js.map +1 -1
- package/dist/errors/invalid-scope-error.d.ts +1 -1
- package/dist/errors/invalid-scope-error.d.ts.map +1 -1
- package/dist/errors/invalid-scope-error.js.map +1 -1
- package/dist/errors/login-required-error.d.ts +1 -1
- package/dist/errors/login-required-error.d.ts.map +1 -1
- package/dist/errors/login-required-error.js.map +1 -1
- package/dist/lexicon/lexicon-data.d.ts +1 -1
- package/dist/lexicon/lexicon-data.d.ts.map +1 -1
- package/dist/lexicon/lexicon-data.js.map +1 -1
- package/dist/lexicon/lexicon-getter.d.ts +3 -3
- package/dist/lexicon/lexicon-getter.d.ts.map +1 -1
- package/dist/lexicon/lexicon-getter.js +1 -1
- package/dist/lexicon/lexicon-getter.js.map +1 -1
- package/dist/lexicon/lexicon-manager.d.ts +4 -4
- package/dist/lexicon/lexicon-manager.d.ts.map +1 -1
- package/dist/lexicon/lexicon-manager.js.map +1 -1
- package/dist/lexicon/lexicon-store.d.ts +4 -3
- package/dist/lexicon/lexicon-store.d.ts.map +1 -1
- package/dist/lexicon/lexicon-store.js.map +1 -1
- package/dist/lib/csp/index.d.ts +1 -1
- package/dist/lib/csp/index.d.ts.map +1 -1
- package/dist/lib/csp/index.js.map +1 -1
- package/dist/lib/hcaptcha.d.ts +1 -1
- package/dist/lib/hcaptcha.d.ts.map +1 -1
- package/dist/lib/hcaptcha.js +1 -1
- package/dist/lib/hcaptcha.js.map +1 -1
- package/dist/lib/html/build-document.d.ts +1 -1
- package/dist/lib/html/build-document.d.ts.map +1 -1
- package/dist/lib/html/build-document.js.map +1 -1
- package/dist/lib/html/escapers.d.ts +1 -1
- package/dist/lib/html/escapers.d.ts.map +1 -1
- package/dist/lib/html/escapers.js.map +1 -1
- package/dist/lib/html/tags.d.ts +1 -1
- package/dist/lib/html/tags.d.ts.map +1 -1
- package/dist/lib/html/tags.js +1 -0
- package/dist/lib/html/tags.js.map +1 -1
- package/dist/lib/http/accept.d.ts +2 -2
- package/dist/lib/http/accept.d.ts.map +1 -1
- package/dist/lib/http/accept.js.map +1 -1
- package/dist/lib/http/middleware.d.ts +1 -1
- package/dist/lib/http/middleware.d.ts.map +1 -1
- package/dist/lib/http/middleware.js.map +1 -1
- package/dist/lib/http/request.d.ts +2 -2
- package/dist/lib/http/request.d.ts.map +1 -1
- package/dist/lib/http/request.js.map +1 -1
- package/dist/lib/http/response.d.ts +1 -1
- package/dist/lib/http/response.d.ts.map +1 -1
- package/dist/lib/http/response.js.map +1 -1
- package/dist/lib/http/route.d.ts +4 -4
- package/dist/lib/http/route.d.ts.map +1 -1
- package/dist/lib/http/route.js.map +1 -1
- package/dist/lib/http/router.d.ts +5 -5
- package/dist/lib/http/router.d.ts.map +1 -1
- package/dist/lib/http/router.js.map +1 -1
- package/dist/lib/http/stream.d.ts +2 -2
- package/dist/lib/http/stream.d.ts.map +1 -1
- package/dist/lib/http/stream.js.map +1 -1
- package/dist/lib/util/time.d.ts +1 -1
- package/dist/lib/util/time.d.ts.map +1 -1
- package/dist/lib/util/time.js.map +1 -1
- package/dist/lib/util/zod-error.d.ts +1 -1
- package/dist/lib/util/zod-error.d.ts.map +1 -1
- package/dist/lib/util/zod-error.js.map +1 -1
- package/dist/lib/write-form-redirect.d.ts +1 -1
- package/dist/lib/write-form-redirect.d.ts.map +1 -1
- package/dist/lib/write-form-redirect.js.map +1 -1
- package/dist/lib/write-html.d.ts +3 -3
- package/dist/lib/write-html.d.ts.map +1 -1
- package/dist/lib/write-html.js.map +1 -1
- package/dist/metadata/build-metadata.d.ts +2 -2
- package/dist/metadata/build-metadata.d.ts.map +1 -1
- package/dist/metadata/build-metadata.js.map +1 -1
- package/dist/{constants.d.ts → oauth-constants.d.ts} +1 -1
- package/dist/oauth-constants.d.ts.map +1 -0
- package/dist/{constants.js → oauth-constants.js} +1 -1
- package/dist/oauth-constants.js.map +1 -0
- package/dist/oauth-errors.d.ts +2 -3
- package/dist/oauth-errors.d.ts.map +1 -1
- package/dist/oauth-errors.js +4 -4
- package/dist/oauth-errors.js.map +1 -1
- package/dist/oauth-hooks.d.ts +20 -24
- package/dist/oauth-hooks.d.ts.map +1 -1
- package/dist/oauth-hooks.js +1 -8
- package/dist/oauth-hooks.js.map +1 -1
- package/dist/oauth-middleware.d.ts +4 -4
- package/dist/oauth-middleware.d.ts.map +1 -1
- package/dist/oauth-middleware.js.map +1 -1
- package/dist/oauth-provider.d.ts +46 -37
- package/dist/oauth-provider.d.ts.map +1 -1
- package/dist/oauth-provider.js +17 -8
- package/dist/oauth-provider.js.map +1 -1
- package/dist/oauth-store.d.ts +0 -4
- package/dist/oauth-store.d.ts.map +1 -1
- package/dist/oauth-store.js +0 -4
- package/dist/oauth-store.js.map +1 -1
- package/dist/oauth-utils.d.ts +14 -0
- package/dist/oauth-utils.d.ts.map +1 -0
- package/dist/oauth-utils.js +5 -0
- package/dist/oauth-utils.js.map +1 -0
- package/dist/oauth-verifier.d.ts +6 -6
- package/dist/oauth-verifier.d.ts.map +1 -1
- package/dist/oauth-verifier.js.map +1 -1
- package/dist/replay/replay-manager.d.ts +2 -2
- package/dist/replay/replay-manager.d.ts.map +1 -1
- package/dist/replay/replay-manager.js +1 -1
- package/dist/replay/replay-manager.js.map +1 -1
- package/dist/replay/replay-store-redis.d.ts +1 -1
- package/dist/replay/replay-store-redis.d.ts.map +1 -1
- package/dist/replay/replay-store-redis.js.map +1 -1
- package/dist/replay/replay-store.d.ts +1 -1
- package/dist/replay/replay-store.d.ts.map +1 -1
- package/dist/replay/replay-store.js.map +1 -1
- package/dist/request/code.js +1 -1
- package/dist/request/code.js.map +1 -1
- package/dist/request/request-data.d.ts +7 -7
- package/dist/request/request-data.d.ts.map +1 -1
- package/dist/request/request-data.js.map +1 -1
- package/dist/request/request-id.d.ts.map +1 -1
- package/dist/request/request-id.js +1 -1
- package/dist/request/request-id.js.map +1 -1
- package/dist/request/request-manager.d.ts +13 -13
- package/dist/request/request-manager.d.ts.map +1 -1
- package/dist/request/request-manager.js +1 -1
- package/dist/request/request-manager.js.map +1 -1
- package/dist/request/request-store.d.ts +6 -8
- package/dist/request/request-store.d.ts.map +1 -1
- package/dist/request/request-store.js +0 -4
- package/dist/request/request-store.js.map +1 -1
- package/dist/request/request-uri.d.ts +1 -1
- package/dist/request/request-uri.d.ts.map +1 -1
- package/dist/request/request-uri.js.map +1 -1
- package/dist/result/authorization-redirect-parameters.d.ts +2 -2
- package/dist/result/authorization-redirect-parameters.d.ts.map +1 -1
- package/dist/result/authorization-redirect-parameters.js.map +1 -1
- package/dist/result/authorization-result-redirect.d.ts +2 -2
- package/dist/result/authorization-result-redirect.d.ts.map +1 -1
- package/dist/result/authorization-result-redirect.js.map +1 -1
- package/dist/router/assets/assets-manifest.d.ts +2 -2
- package/dist/router/assets/assets-manifest.d.ts.map +1 -1
- package/dist/router/assets/assets-manifest.js.map +1 -1
- package/dist/router/assets/assets.d.ts +4 -4
- package/dist/router/assets/assets.d.ts.map +1 -1
- package/dist/router/assets/assets.js.map +1 -1
- package/dist/router/assets/csrf.js.map +1 -1
- package/dist/router/assets/send-account-page.d.ts +2 -2
- package/dist/router/assets/send-account-page.d.ts.map +1 -1
- package/dist/router/assets/send-account-page.js.map +1 -1
- package/dist/router/assets/send-authorization-page.d.ts +3 -3
- package/dist/router/assets/send-authorization-page.d.ts.map +1 -1
- package/dist/router/assets/send-authorization-page.js.map +1 -1
- package/dist/router/assets/send-cookie-error-page.d.ts +2 -2
- package/dist/router/assets/send-cookie-error-page.d.ts.map +1 -1
- package/dist/router/assets/send-cookie-error-page.js.map +1 -1
- package/dist/router/assets/send-error-page.d.ts +2 -2
- package/dist/router/assets/send-error-page.d.ts.map +1 -1
- package/dist/router/assets/send-error-page.js.map +1 -1
- package/dist/router/assets/send-redirect.d.ts +4 -4
- package/dist/router/assets/send-redirect.d.ts.map +1 -1
- package/dist/router/assets/send-redirect.js.map +1 -1
- package/dist/router/create-account-page-middleware.d.ts +1 -1
- package/dist/router/create-account-page-middleware.d.ts.map +1 -1
- package/dist/router/create-account-page-middleware.js.map +1 -1
- package/dist/router/create-api-middleware.d.ts +2 -2
- package/dist/router/create-api-middleware.d.ts.map +1 -1
- package/dist/router/create-api-middleware.js +1 -1
- package/dist/router/create-api-middleware.js.map +1 -1
- package/dist/router/create-authorization-page-middleware.d.ts +1 -1
- package/dist/router/create-authorization-page-middleware.d.ts.map +1 -1
- package/dist/router/create-authorization-page-middleware.js.map +1 -1
- package/dist/router/create-oauth-middleware.d.ts +1 -1
- package/dist/router/create-oauth-middleware.d.ts.map +1 -1
- package/dist/router/create-oauth-middleware.js +1 -1
- package/dist/router/create-oauth-middleware.js.map +1 -1
- package/dist/signer/api-token-payload.d.ts +1 -1
- package/dist/signer/api-token-payload.d.ts.map +1 -1
- package/dist/signer/api-token-payload.js +1 -1
- package/dist/signer/api-token-payload.js.map +1 -1
- package/dist/signer/signer.d.ts +4 -4
- package/dist/signer/signer.d.ts.map +1 -1
- package/dist/signer/signer.js +2 -2
- package/dist/signer/signer.js.map +1 -1
- package/dist/token/refresh-token.js +1 -1
- package/dist/token/refresh-token.js.map +1 -1
- package/dist/token/token-claims.d.ts +4 -4
- package/dist/token/token-claims.d.ts.map +1 -1
- package/dist/token/token-claims.js.map +1 -1
- package/dist/token/token-data.d.ts +7 -7
- package/dist/token/token-data.d.ts.map +1 -1
- package/dist/token/token-data.js.map +1 -1
- package/dist/token/token-id.js +1 -1
- package/dist/token/token-id.js.map +1 -1
- package/dist/token/token-manager.d.ts +14 -14
- package/dist/token/token-manager.d.ts.map +1 -1
- package/dist/token/token-manager.js +1 -1
- package/dist/token/token-manager.js.map +1 -1
- package/dist/token/token-store.d.ts +7 -9
- package/dist/token/token-store.d.ts.map +1 -1
- package/dist/token/token-store.js +0 -4
- package/dist/token/token-store.js.map +1 -1
- package/dist/types/handle.js.map +1 -1
- package/dist/types/rgb-color.d.ts +1 -1
- package/dist/types/rgb-color.d.ts.map +1 -1
- package/dist/types/rgb-color.js.map +1 -1
- package/package.json +47 -20
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js.map +0 -1
- package/dist/errors/invalid-invite-code-error.d.ts +0 -5
- package/dist/errors/invalid-invite-code-error.d.ts.map +0 -1
- package/dist/errors/invalid-invite-code-error.js +0 -7
- package/dist/errors/invalid-invite-code-error.js.map +0 -1
- package/dist/index.d.ts +0 -15
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -16
- package/dist/index.js.map +0 -1
- package/dist/oauth-client.d.ts +0 -4
- package/dist/oauth-client.d.ts.map +0 -1
- package/dist/oauth-client.js +0 -3
- package/dist/oauth-client.js.map +0 -1
- package/dist/oauth-dpop.d.ts +0 -3
- package/dist/oauth-dpop.d.ts.map +0 -1
- package/dist/oauth-dpop.js +0 -3
- package/dist/oauth-dpop.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-provider.js","sourceRoot":"","sources":["../src/oauth-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from 'node:crypto'\nimport type { Redis, RedisOptions } from 'ioredis'\nimport { Jwks, Keyset } from '@atproto/jwk'\nimport { LexResolver } from '@atproto/lex-resolver'\nimport type { Account } from '@atproto/oauth-provider-api'\nimport {\n CLIENT_ASSERTION_TYPE_JWT_BEARER,\n OAuthAccessToken,\n OAuthAuthorizationCodeGrantTokenRequest,\n OAuthAuthorizationRequestJar,\n OAuthAuthorizationRequestPar,\n OAuthAuthorizationRequestParameters,\n OAuthAuthorizationRequestQuery,\n OAuthAuthorizationServerMetadata,\n OAuthClientCredentials,\n OAuthClientMetadata,\n OAuthParResponse,\n OAuthRefreshTokenGrantTokenRequest,\n OAuthTokenIdentification,\n OAuthTokenRequest,\n OAuthTokenResponse,\n OAuthTokenType,\n atprotoLoopbackClientMetadata,\n oauthAuthorizationRequestParametersSchema,\n} from '@atproto/oauth-types'\nimport { safeFetchWrap } from '@atproto-labs/fetch-node'\nimport { SimpleStore } from '@atproto-labs/simple-store'\nimport { SimpleStoreMemory } from '@atproto-labs/simple-store-memory'\nimport { AccessTokenMode } from './access-token/access-token-mode.js'\nimport { AccountManager } from './account/account-manager.js'\nimport {\n AccountStore,\n AuthorizedClientData,\n DeviceAccount,\n asAccountStore,\n} from './account/account-store.js'\nimport { ClientAuth, ClientAuthLegacy } from './client/client-auth.js'\nimport { ClientId } from './client/client-id.js'\nimport {\n ClientManager,\n LoopbackMetadataGetter,\n} from './client/client-manager.js'\nimport { ClientStore, ifClientStore } from './client/client-store.js'\nimport { Client } from './client/client.js'\nimport {\n AUTHENTICATION_MAX_AGE,\n CONFIDENTIAL_CLIENT_REFRESH_LIFETIME,\n CONFIDENTIAL_CLIENT_SESSION_LIFETIME,\n PUBLIC_CLIENT_REFRESH_LIFETIME,\n PUBLIC_CLIENT_SESSION_LIFETIME,\n TOKEN_MAX_AGE,\n} from './constants.js'\nimport { Branding, BrandingInput } from './customization/branding.js'\nimport {\n Customization,\n CustomizationInput,\n customizationSchema,\n} from './customization/customization.js'\nimport { DeviceId } from './device/device-id.js'\nimport {\n DeviceInfo,\n DeviceManager,\n DeviceManagerOptions,\n} from './device/device-manager.js'\nimport { DeviceStore, asDeviceStore } from './device/device-store.js'\nimport { AccountSelectionRequiredError } from './errors/account-selection-required-error.js'\nimport { AuthorizationError } from './errors/authorization-error.js'\nimport { ConsentRequiredError } from './errors/consent-required-error.js'\nimport { InvalidDpopKeyBindingError } from './errors/invalid-dpop-key-binding-error.js'\nimport { InvalidDpopProofError } from './errors/invalid-dpop-proof-error.js'\nimport { InvalidGrantError } from './errors/invalid-grant-error.js'\nimport { InvalidRequestError } from './errors/invalid-request-error.js'\nimport { LoginRequiredError } from './errors/login-required-error.js'\nimport { LexiconManager } from './lexicon/lexicon-manager.js'\nimport { LexiconStore, asLexiconStore } from './lexicon/lexicon-store.js'\nimport { HcaptchaConfig } from './lib/hcaptcha.js'\nimport { RequestMetadata } from './lib/http/request.js'\nimport { dateToRelativeSeconds } from './lib/util/date.js'\nimport { formatError } from './lib/util/error.js'\nimport { MultiLangString } from './lib/util/locale.js'\nimport { CustomMetadata, buildMetadata } from './metadata/build-metadata.js'\nimport { OAuthHooks } from './oauth-hooks.js'\nimport {\n DpopProof,\n OAuthVerifier,\n OAuthVerifierOptions,\n VerifyTokenPayloadOptions,\n} from './oauth-verifier.js'\nimport { ReplayStore, ifReplayStore } from './replay/replay-store.js'\nimport { codeSchema } from './request/code.js'\nimport { RequestManager } from './request/request-manager.js'\nimport { RequestStore, asRequestStore } from './request/request-store.js'\nimport { parseRequestUri } from './request/request-uri.js'\nimport { AuthorizationRedirectParameters } from './result/authorization-redirect-parameters.js'\nimport { AuthorizationResultAuthorizePage } from './result/authorization-result-authorize-page.js'\nimport { AuthorizationResultRedirect } from './result/authorization-result-redirect.js'\nimport { ErrorHandler } from './router/error-handler.js'\nimport { AccessTokenPayload } from './signer/access-token-payload.js'\nimport { TokenData } from './token/token-data.js'\nimport { TokenManager } from './token/token-manager.js'\nimport {\n TokenStore,\n asTokenStore,\n refreshTokenSchema,\n} from './token/token-store.js'\nimport { isPARResponseError } from './types/par-response-error.js'\n\nexport { AccessTokenMode, Keyset, LexResolver }\nexport type {\n AccessTokenPayload,\n AuthorizationRedirectParameters,\n AuthorizationResultAuthorizePage as AuthorizationResultAuthorize,\n AuthorizationResultRedirect,\n Branding,\n BrandingInput,\n CustomMetadata,\n Customization,\n CustomizationInput,\n ErrorHandler,\n HcaptchaConfig,\n MultiLangString,\n OAuthAuthorizationServerMetadata,\n VerifyTokenPayloadOptions,\n}\n\ntype OAuthProviderConfig = {\n /**\n * Maximum age a device/account session can be before requiring\n * re-authentication.\n */\n authenticationMaxAge?: number\n\n /**\n * Maximum age access & id tokens can be before requiring a refresh.\n */\n tokenMaxAge?: number\n\n /**\n * If set to {@link AccessTokenMode.stateless}, the generated access tokens\n * will contain all the necessary information to validate the token without\n * needing to query the database. This is useful for cases where the Resource\n * Server is on a different host/server than the Authorization Server.\n *\n * When set to {@link AccessTokenMode.light}, the access tokens will contain\n * only the necessary information to validate the token, but the token id\n * will need to be queried from the database to retrieve the full token\n * information (scope, audience, etc.)\n *\n * @see {@link AccessTokenMode}\n * @default {AccessTokenMode.stateless}\n */\n accessTokenMode?: AccessTokenMode\n\n /**\n * Additional metadata to be included in the discovery document.\n */\n metadata?: CustomMetadata\n\n /**\n * A Lexicon resolver instance to use for fetching lexicon schemas.\n */\n lexResolver?: LexResolver\n\n /**\n * A custom fetch function that can be used to fetch the client metadata from\n * the internet. By default, the fetch function is a safeFetchWrap() function\n * that protects against SSRF attacks, large responses & known bad domains. If\n * you want to disable all protections, you can provide `globalThis.fetch` as\n * fetch function.\n */\n safeFetch?: typeof globalThis.fetch\n\n /**\n * A redis instance to use for replay protection. If not provided, replay\n * protection will use memory storage.\n */\n redis?: Redis | RedisOptions | string\n\n /**\n * This will be used as the default store for all the stores. If a store is\n * not provided, this store will be used instead. If the `store` does not\n * implement a specific store, a runtime error will be thrown. Make sure that\n * this store implements all the interfaces not provided in the other\n * `<name>Store` options.\n */\n store?: Partial<\n AccountStore &\n ClientStore &\n DeviceStore &\n LexiconStore &\n ReplayStore &\n RequestStore &\n TokenStore\n >\n\n accountStore?: AccountStore\n clientStore?: ClientStore\n deviceStore?: DeviceStore\n lexiconStore?: LexiconStore\n replayStore?: ReplayStore\n requestStore?: RequestStore\n tokenStore?: TokenStore\n\n /**\n * In order to speed up the client fetching process, you can provide a cache\n * to store HTTP responses.\n *\n * @note the cached entries should automatically expire after a certain time (typically 10 minutes)\n */\n clientJwksCache?: SimpleStore<string, Jwks>\n\n /**\n * In order to speed up the client fetching process, you can provide a cache\n * to store HTTP responses.\n *\n * @note the cached entries should automatically expire after a certain time (typically 10 minutes)\n */\n clientMetadataCache?: SimpleStore<string, OAuthClientMetadata>\n\n /**\n * In order to enable loopback clients, you can provide a function that\n * returns the client metadata for a given loopback URL. This is useful for\n * development and testing purposes. This function is not called for internet\n * clients.\n *\n * @default is as specified by ATPROTO\n */\n loopbackMetadata?: null | false | LoopbackMetadataGetter\n}\n\nexport type OAuthProviderOptions = OAuthProviderConfig &\n OAuthVerifierOptions &\n OAuthHooks &\n DeviceManagerOptions &\n CustomizationInput\n\nexport class OAuthProvider extends OAuthVerifier {\n protected readonly accessTokenMode: AccessTokenMode\n protected readonly hooks: OAuthHooks\n\n public readonly metadata: OAuthAuthorizationServerMetadata\n public readonly customization: Customization\n\n public readonly authenticationMaxAge: number\n\n public readonly accountManager: AccountManager\n public readonly deviceManager: DeviceManager\n public readonly clientManager: ClientManager\n public readonly lexiconManager: LexiconManager\n public readonly requestManager: RequestManager\n public readonly tokenManager: TokenManager\n\n public constructor({\n // OAuthProviderConfig\n authenticationMaxAge = AUTHENTICATION_MAX_AGE,\n tokenMaxAge = TOKEN_MAX_AGE,\n accessTokenMode = AccessTokenMode.stateless,\n\n metadata,\n\n safeFetch = safeFetchWrap(),\n store, // compound store implementation\n lexResolver = new LexResolver({ fetch: safeFetch }),\n\n // Required stores\n accountStore = asAccountStore(store),\n deviceStore = asDeviceStore(store),\n lexiconStore = asLexiconStore(store),\n tokenStore = asTokenStore(store),\n requestStore = asRequestStore(store),\n\n // Optional stores\n clientStore = ifClientStore(store),\n replayStore = ifReplayStore(store),\n\n clientJwksCache = new SimpleStoreMemory({\n maxSize: 50_000_000,\n ttl: 600e3,\n }),\n clientMetadataCache = new SimpleStoreMemory({\n maxSize: 50_000_000,\n ttl: 600e3,\n }),\n\n loopbackMetadata = atprotoLoopbackClientMetadata,\n\n // OAuthHooks &\n // OAuthVerifierOptions &\n // DeviceManagerOptions &\n // Customization\n ...rest\n }: OAuthProviderOptions) {\n super({ replayStore, ...rest })\n\n // @NOTE: hooks don't really need a type parser, as all zod can actually\n // check at runtime is the fact that the values are functions. The only way\n // we would benefit from zod here would be to wrap the functions with a\n // validator for the provided function's return types, which we don't\n // really need if types are respected.\n this.hooks = rest\n\n this.accessTokenMode = accessTokenMode\n this.authenticationMaxAge = authenticationMaxAge\n this.metadata = buildMetadata(this.issuer, this.keyset, metadata)\n this.customization = customizationSchema.parse(rest)\n\n this.deviceManager = new DeviceManager(deviceStore, {\n ...rest,\n cookie: {\n ...rest.cookie,\n // \"secure\" defaults to \"true\" in DeviceManager. For the oauth routes to\n // work from localhost on Safari, we need to explicitly set secure to\n // false for localhost usage. This is not really an issue with Chrome\n // and Firefox, but Safari enforces it strictly.\n secure: !this.issuer.startsWith('http:'),\n },\n })\n this.accountManager = new AccountManager(\n this.issuer,\n accountStore,\n this.hooks,\n this.customization,\n )\n this.clientManager = new ClientManager(\n this.metadata,\n this.keyset,\n this.hooks,\n clientStore || null,\n loopbackMetadata || null,\n safeFetch,\n clientJwksCache,\n clientMetadataCache,\n )\n this.lexiconManager = new LexiconManager(lexiconStore, lexResolver)\n this.requestManager = new RequestManager(\n requestStore,\n this.lexiconManager,\n this.signer,\n this.metadata,\n this.hooks,\n )\n this.tokenManager = new TokenManager(\n tokenStore,\n this.lexiconManager,\n this.signer,\n this.hooks,\n this.accessTokenMode,\n tokenMaxAge,\n )\n }\n\n get jwks() {\n return this.keyset.publicJwks\n }\n\n /**\n * @returns true if the user's consent is required for the requested scopes\n */\n public checkConsentRequired(\n parameters: OAuthAuthorizationRequestParameters,\n clientData?: AuthorizedClientData,\n ) {\n // Client was never authorized before\n if (!clientData) return true\n\n // Client explicitly asked for consent\n if (parameters.prompt === 'consent') return true\n\n // No scope requested, and client is known by user, no consent required\n const requestedScopes = parameters.scope?.split(' ')\n if (requestedScopes == null) return false\n\n // Ensure that all requested scopes were previously authorized by the user\n const { authorizedScopes } = clientData\n return !requestedScopes.every((scope) => authorizedScopes.includes(scope))\n }\n\n public checkLoginRequired(deviceAccount: DeviceAccount) {\n const authAge = Date.now() - deviceAccount.updatedAt.getTime()\n return authAge > this.authenticationMaxAge\n }\n\n protected async authenticateClient(\n clientCredentials: OAuthClientCredentials,\n dpopProof: null | DpopProof,\n options?: {\n allowMissingDpopProof?: boolean\n },\n ): Promise<{\n client: Client\n clientAuth: ClientAuth\n }> {\n const client = await this.clientManager.getClient(\n clientCredentials.client_id,\n )\n\n if (\n client.metadata.dpop_bound_access_tokens &&\n !dpopProof &&\n !options?.allowMissingDpopProof\n ) {\n throw new InvalidDpopProofError('DPoP proof required')\n }\n\n if (dpopProof && !client.metadata.dpop_bound_access_tokens) {\n throw new InvalidDpopProofError('DPoP proof not allowed for this client')\n }\n\n const clientAuth = await client.authenticate(clientCredentials, {\n authorizationServerIdentifier: this.issuer,\n })\n\n if (clientAuth.method === 'private_key_jwt') {\n // Clients MUST NOT use their client assertion key to sign DPoP proofs\n if (dpopProof && clientAuth.jkt === dpopProof.jkt) {\n throw new InvalidRequestError(\n 'The DPoP proof must be signed with a different key than the client assertion',\n )\n }\n\n // https://www.rfc-editor.org/rfc/rfc7523.html#section-3\n // > 7. [...] The authorization server MAY ensure that JWTs are not\n // > replayed by maintaining the set of used \"jti\" values for the\n // > length of time for which the JWT would be considered valid based\n // > on the applicable \"exp\" instant.\n\n const unique = await this.replayManager.uniqueAuth(\n clientAuth.jti,\n client.id,\n clientAuth.exp,\n )\n if (!unique) {\n throw new InvalidGrantError(`${clientAuth.method} jti reused`)\n }\n }\n\n return { client, clientAuth }\n }\n\n async decodeJAR(\n client: Client,\n input: OAuthAuthorizationRequestJar,\n ): Promise<OAuthAuthorizationRequestParameters> {\n const { payload } = await client.decodeRequestObject(\n input.request,\n this.issuer,\n )\n\n const { jti } = payload\n if (!jti) {\n throw new InvalidRequestError(\n 'Request object payload must contain a \"jti\" claim',\n )\n }\n if (!(await this.replayManager.uniqueJar(jti, client.id))) {\n throw new InvalidRequestError('Request object was replayed')\n }\n\n const parameters = await oauthAuthorizationRequestParametersSchema\n .parseAsync(payload)\n .catch((err) => {\n const msg = formatError(err, 'Invalid parameters in JAR')\n throw new InvalidRequestError(msg, err)\n })\n\n return parameters\n }\n\n /**\n * @see {@link https://datatracker.ietf.org/doc/html/rfc9126}\n */\n public async pushedAuthorizationRequest(\n credentials: OAuthClientCredentials,\n authorizationRequest: OAuthAuthorizationRequestPar,\n dpopProof: null | DpopProof,\n ): Promise<OAuthParResponse> {\n try {\n const { client, clientAuth } = await this.authenticateClient(\n credentials,\n dpopProof,\n // Allow missing DPoP header for PAR requests as rfc9449 allows it\n // (though the dpop_jkt parameter must be present in that case, see\n // check bellow).\n { allowMissingDpopProof: true },\n )\n\n const parameters =\n 'request' in authorizationRequest // Handle JAR\n ? await this.decodeJAR(client, authorizationRequest)\n : authorizationRequest\n\n if (!parameters.dpop_jkt) {\n if (client.metadata.dpop_bound_access_tokens) {\n if (dpopProof) parameters.dpop_jkt = dpopProof.jkt\n else {\n // @NOTE When both PAR and DPoP are used, either the DPoP header, or\n // the dpop_jkt parameter must be present. We do not enforce this\n // for legacy reasons.\n // https://datatracker.ietf.org/doc/html/rfc9449#section-10.1\n }\n }\n } else {\n if (!client.metadata.dpop_bound_access_tokens) {\n throw new InvalidRequestError(\n 'DPoP bound access tokens are not enabled for this client',\n )\n }\n\n // Proof is optional if the dpop_jkt is provided, but if it is provided,\n // it must match the DPoP proof JKT.\n if (dpopProof && dpopProof.jkt !== parameters.dpop_jkt) {\n throw new InvalidDpopKeyBindingError()\n }\n }\n\n const { requestUri, expiresAt } =\n await this.requestManager.createAuthorizationRequest(\n client,\n clientAuth,\n parameters,\n null,\n )\n\n return {\n request_uri: requestUri,\n expires_in: dateToRelativeSeconds(expiresAt),\n }\n } catch (err) {\n // https://datatracker.ietf.org/doc/html/rfc9126#section-2.3-1\n // > Since initial processing of the pushed authorization request does not\n // > involve resource owner interaction, error codes related to user\n // > interaction, such as \"access_denied\", are never returned.\n if (err instanceof AuthorizationError && !isPARResponseError(err.error)) {\n throw new InvalidRequestError(err.error_description, err)\n }\n throw err\n }\n }\n\n private async processAuthorizationRequest(\n client: Client,\n deviceId: DeviceId,\n query: OAuthAuthorizationRequestQuery,\n ) {\n // PAR\n if ('request_uri' in query) {\n const requestUri = parseRequestUri(query.request_uri, {\n path: ['query', 'request_uri'],\n })\n return this.requestManager.get(requestUri, deviceId, client.id)\n }\n\n // JAR\n if ('request' in query) {\n // @NOTE Since JAR are signed with the client's private key, a JAR *could*\n // technically be used to authenticate the client when requests are\n // created without PAR (i.e. created on the fly by the authorize\n // endpoint). This implementation actually used to support this\n // (un-spec'd) behavior. That support was removed:\n // - Because it was not actually used\n // - Because it was not part of any standard\n // - Because it makes extending the client authentication mechanism more\n // complex since any extension would not only need to affect the\n // \"private_key_jwt\" auth method but also the JAR \"request\" object.\n const parameters = await this.decodeJAR(client, query)\n\n return this.requestManager.createAuthorizationRequest(\n client,\n null,\n parameters,\n deviceId,\n )\n }\n\n // \"Regular\" authorization request (created on the fly by directing the user\n // to the authorization endpoint with all the parameters in the url).\n return this.requestManager.createAuthorizationRequest(\n client,\n null,\n query,\n deviceId,\n )\n }\n\n /**\n * @see {@link https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-11#section-4.1.1}\n */\n public async authorize(\n query: OAuthAuthorizationRequestQuery,\n { deviceId, deviceMetadata }: DeviceInfo,\n ): Promise<AuthorizationResultRedirect | AuthorizationResultAuthorizePage> {\n const { issuer } = this\n\n // If there is a chance to redirect the user to the client, let's do\n // it by wrapping the error in an AuthorizationError.\n const throwAuthorizationError =\n 'redirect_uri' in query\n ? (err: unknown): never => {\n // https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-11#section-4.1.2.1\n throw AuthorizationError.from(query, err)\n }\n : null\n\n const client = await this.clientManager\n .getClient(query.client_id)\n .catch(throwAuthorizationError)\n\n const { parameters, requestUri } = await this.processAuthorizationRequest(\n client,\n deviceId,\n query,\n ).catch(throwAuthorizationError)\n\n try {\n const sessions = (\n await this.accountManager.listDeviceAccounts(deviceId)\n ).map((deviceAccount) => ({\n account: deviceAccount.account,\n\n // @TODO Return the session expiration date instead of a boolean to\n // avoid having to rely on a leeway when \"accepting\" the request.\n loginRequired:\n parameters.prompt === 'login' ||\n this.checkLoginRequired(deviceAccount),\n consentRequired: this.checkConsentRequired(\n parameters,\n deviceAccount.authorizedClients.get(client.id),\n ),\n }))\n\n // https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest\n\n // prompt=select_account\n //\n // > The Authorization Server SHOULD prompt the End-User to select a user\n // > account. This enables an End-User who has multiple accounts at the\n // > Authorization Server to select amongst the multiple accounts that\n // > they might have current sessions for. If it cannot obtain an account\n // > selection choice made by the End-User, it MUST return an error,\n // > typically account_selection_required.\n if (parameters.prompt === 'select_account' && !sessions.length) {\n throw new AccountSelectionRequiredError(parameters)\n }\n\n const ssoSessions = sessions\n .filter(hasActiveAccount)\n .filter(matchesHint, parameters)\n\n // prompt=none\n //\n // > The Authorization Server MUST NOT display any authentication or\n // > consent user interface pages. An error is returned if an End-User is\n // > not already authenticated or the Client does not have pre-configured\n // > consent for the requested Claims or does not fulfill other conditions\n // > for processing the request. The error code will typically be\n // > login_required, interaction_required, or another code defined in\n // > Section 3.1.2.6. This can be used as a method to check for existing\n // > authentication and/or consent.\n if (parameters.prompt === 'none') {\n if (ssoSessions.length > 1) {\n throw new AccountSelectionRequiredError(parameters)\n }\n if (ssoSessions.length < 1) {\n throw new LoginRequiredError(parameters)\n }\n\n const ssoSession = ssoSessions[0]!\n if (ssoSession.loginRequired) {\n throw new LoginRequiredError(parameters)\n }\n if (ssoSession.consentRequired) {\n throw new ConsentRequiredError(parameters)\n }\n\n const code = await this.requestManager.setAuthorized(\n requestUri,\n client,\n ssoSession.account,\n deviceId,\n deviceMetadata,\n )\n\n return { issuer, parameters, redirect: { code } }\n }\n\n // Automatic SSO when a hint was provided that matches a single session\n if (parameters.prompt == null && parameters.login_hint != null) {\n if (ssoSessions.length === 1) {\n const ssoSession = ssoSessions[0]!\n if (!ssoSession.loginRequired && !ssoSession.consentRequired) {\n const code = await this.requestManager.setAuthorized(\n requestUri,\n client,\n ssoSession.account,\n deviceId,\n deviceMetadata,\n )\n\n return { issuer, parameters, redirect: { code } }\n }\n }\n }\n\n return {\n issuer,\n client,\n parameters,\n requestUri,\n sessions: sessions\n // Strip un-necessary information (like consentRequired)\n .map(({ account, loginRequired }) => ({ account, loginRequired })),\n selectedDid:\n parameters.prompt == null ||\n parameters.prompt === 'login' ||\n parameters.prompt === 'consent'\n ? sessions.find(matchesHint, parameters)?.account.did\n : undefined,\n permissionSets: await this.lexiconManager\n .getPermissionSetsFromScope(parameters.scope)\n .catch((cause) => {\n throw new AuthorizationError(\n parameters,\n 'Unable to retrieve permission sets',\n 'invalid_scope',\n cause,\n )\n }),\n }\n } catch (err) {\n try {\n await this.requestManager.delete(requestUri)\n } catch {\n // There are two error here. Better keep the outer one.\n //\n // @TODO Maybe move this entire code to the /authorize endpoint\n // (allowing to log this error)\n }\n\n throw AuthorizationError.from(parameters, err)\n }\n }\n\n public async token(\n clientCredentials: OAuthClientCredentials,\n clientMetadata: RequestMetadata,\n request: OAuthTokenRequest,\n dpopProof: null | DpopProof,\n ): Promise<OAuthTokenResponse> {\n const { client, clientAuth } = await this.authenticateClient(\n clientCredentials,\n dpopProof,\n )\n\n if (!this.metadata.grant_types_supported?.includes(request.grant_type)) {\n throw new InvalidGrantError(\n `Grant type \"${request.grant_type}\" is not supported by the server`,\n )\n }\n\n if (!client.metadata.grant_types.includes(request.grant_type)) {\n throw new InvalidGrantError(\n `\"${request.grant_type}\" grant type is not allowed for this client`,\n )\n }\n\n if (request.grant_type === 'authorization_code') {\n return this.authorizationCodeGrant(\n client,\n clientAuth,\n clientMetadata,\n request,\n dpopProof,\n )\n }\n\n if (request.grant_type === 'refresh_token') {\n return this.refreshTokenGrant(\n client,\n clientAuth,\n clientMetadata,\n request,\n dpopProof,\n )\n }\n\n throw new InvalidGrantError(\n `Grant type \"${request.grant_type}\" not supported`,\n )\n }\n\n protected async compareClientAuth(\n client: Client,\n clientAuth: ClientAuth,\n dpopProof: null | DpopProof,\n initial: {\n parameters: OAuthAuthorizationRequestParameters\n clientId: ClientId\n clientAuth: null | ClientAuth | ClientAuthLegacy\n },\n ): Promise<void> {\n // Fool proofing, ensure that the client is authenticating using the right method\n if (clientAuth.method !== client.metadata.token_endpoint_auth_method) {\n throw new InvalidGrantError(\n `Client authentication method mismatch (expected ${client.metadata.token_endpoint_auth_method}, got ${clientAuth.method})`,\n )\n }\n\n if (initial.clientId !== client.id) {\n throw new InvalidGrantError(`Token was not issued to this client`)\n }\n\n const { parameters } = initial\n if (parameters.dpop_jkt) {\n if (!dpopProof) {\n throw new InvalidGrantError(`DPoP proof is required for this request`)\n } else if (parameters.dpop_jkt !== dpopProof.jkt) {\n throw new InvalidGrantError(\n `DPoP proof does not match the expected JKT`,\n )\n }\n }\n\n if (!initial.clientAuth) {\n // If the client did not use PAR, it was not authenticated when the request\n // was initially created (see authorize() method in OAuthProvider). Since\n // PAR is not mandatory, and since the token exchange currently taking place\n // *is* authenticated (`clientAuth`), we allow \"upgrading\" the\n // authentication method (the token created will be bound to the current\n // clientAuth).\n return\n }\n\n switch (initial.clientAuth.method) {\n case CLIENT_ASSERTION_TYPE_JWT_BEARER: // LEGACY\n case 'private_key_jwt':\n if (clientAuth.method !== 'private_key_jwt') {\n throw new InvalidGrantError(\n `Client authentication method mismatch (expected ${initial.clientAuth.method})`,\n )\n }\n if (\n clientAuth.kid !== initial.clientAuth.kid ||\n clientAuth.alg !== initial.clientAuth.alg ||\n clientAuth.jkt !== initial.clientAuth.jkt\n ) {\n throw new InvalidGrantError(\n `The session was initiated with a different key than the client assertion currently used`,\n )\n }\n break\n case 'none':\n // @NOTE We allow the client to \"upgrade\" to a confidential client if\n // the session was initially created without client authentication.\n break\n default:\n throw new InvalidGrantError(\n // @ts-expect-error (future proof, backwards compatibility)\n `Invalid method \"${initial.clientAuth.method}\"`,\n )\n }\n }\n\n protected async authorizationCodeGrant(\n client: Client,\n clientAuth: ClientAuth,\n clientMetadata: RequestMetadata,\n input: OAuthAuthorizationCodeGrantTokenRequest,\n dpopProof: null | DpopProof,\n ): Promise<OAuthTokenResponse> {\n const code = await codeSchema\n .parseAsync(input.code, { path: ['code'] })\n .catch((err) => {\n const msg = formatError(err, 'Invalid code')\n throw new InvalidGrantError(msg, err)\n })\n\n const data = await this.requestManager\n .consumeCode(code)\n .catch(async (err) => {\n // Code not found in request manager: check for replays\n const tokenInfo = await this.tokenManager.findByCode(code)\n if (tokenInfo) {\n // try/finally to ensure that both code path get executed (sequentially)\n try {\n // \"code\" was replayed, delete existing session\n await this.tokenManager.deleteToken(tokenInfo.id)\n } finally {\n // As an additional security measure, we also sign the device out,\n // so that the device cannot be used to access the account anymore\n // without a new authentication.\n const { deviceId, did } = tokenInfo.data\n if (deviceId) {\n await this.accountManager.removeDeviceAccount(deviceId, did)\n }\n }\n }\n\n throw InvalidGrantError.from(err, `Invalid code`)\n })\n\n // @NOTE at this point, the request data was removed from the store and only\n // exists in memory here (in the \"data\" variable). Because of this, any\n // error thrown after this point will permanently cause the request data to\n // be lost.\n\n await this.compareClientAuth(client, clientAuth, dpopProof, data)\n\n // If the DPoP proof was not provided earlier (PAR / authorize), let's add\n // it now.\n const parameters =\n dpopProof &&\n client.metadata.dpop_bound_access_tokens &&\n !data.parameters.dpop_jkt\n ? { ...data.parameters, dpop_jkt: dpopProof.jkt }\n : data.parameters\n\n await this.validateCodeGrant(parameters, input)\n\n const { account } = await this.accountManager.getAccount(data.did)\n\n return this.tokenManager.createToken(\n client,\n clientAuth,\n clientMetadata,\n account,\n data.deviceId,\n parameters,\n code,\n )\n }\n\n protected async validateCodeGrant(\n parameters: OAuthAuthorizationRequestParameters,\n input: OAuthAuthorizationCodeGrantTokenRequest,\n ): Promise<void> {\n if (parameters.redirect_uri !== input.redirect_uri) {\n throw new InvalidGrantError(\n 'The redirect_uri parameter must match the one used in the authorization request',\n )\n }\n\n if (parameters.code_challenge) {\n if (!input.code_verifier) {\n throw new InvalidGrantError('code_verifier is required')\n }\n if (input.code_verifier.length < 43) {\n throw new InvalidGrantError('code_verifier too short')\n }\n switch (parameters.code_challenge_method) {\n case undefined: // default is \"plain\"\n case 'plain':\n if (parameters.code_challenge !== input.code_verifier) {\n throw new InvalidGrantError('Invalid code_verifier')\n }\n break\n\n case 'S256': {\n const inputChallenge = Buffer.from(\n parameters.code_challenge,\n 'base64',\n )\n const computedChallenge = createHash('sha256')\n .update(input.code_verifier)\n .digest()\n if (inputChallenge.compare(computedChallenge) !== 0) {\n throw new InvalidGrantError('Invalid code_verifier')\n }\n break\n }\n\n default:\n // Should never happen (because request validation should catch this)\n throw new Error(`Unsupported code_challenge_method`)\n }\n const unique = await this.replayManager.uniqueCodeChallenge(\n parameters.code_challenge,\n )\n if (!unique) {\n throw new InvalidGrantError('Code challenge already used')\n }\n } else if (input.code_verifier !== undefined) {\n throw new InvalidRequestError(\"code_challenge parameter wasn't provided\")\n }\n }\n\n protected async refreshTokenGrant(\n client: Client,\n clientAuth: ClientAuth,\n clientMetadata: RequestMetadata,\n input: OAuthRefreshTokenGrantTokenRequest,\n dpopProof: null | DpopProof,\n ): Promise<OAuthTokenResponse> {\n const refreshToken = await refreshTokenSchema\n .parseAsync(input.refresh_token, { path: ['refresh_token'] })\n .catch((err) => {\n const msg = formatError(err, 'Invalid refresh token')\n throw new InvalidGrantError(msg, err)\n })\n\n const tokenInfo = await this.tokenManager.consumeRefreshToken(refreshToken)\n\n try {\n const { data } = tokenInfo\n await this.compareClientAuth(client, clientAuth, dpopProof, data)\n await this.validateRefreshGrant(client, clientAuth, data)\n\n return await this.tokenManager.rotateToken(\n client,\n clientAuth,\n clientMetadata,\n tokenInfo,\n )\n } catch (err) {\n await this.tokenManager.deleteToken(tokenInfo.id)\n\n throw err\n }\n }\n\n protected async validateRefreshGrant(\n client: Client,\n clientAuth: ClientAuth,\n data: TokenData,\n ): Promise<void> {\n const [sessionLifetime, refreshLifetime] =\n clientAuth.method !== 'none' || client.info.isFirstParty\n ? [\n CONFIDENTIAL_CLIENT_SESSION_LIFETIME,\n CONFIDENTIAL_CLIENT_REFRESH_LIFETIME,\n ]\n : [PUBLIC_CLIENT_SESSION_LIFETIME, PUBLIC_CLIENT_REFRESH_LIFETIME]\n\n const sessionAge = Date.now() - data.createdAt.getTime()\n if (sessionAge > sessionLifetime) {\n throw new InvalidGrantError(`Session expired`)\n }\n\n const refreshAge = Date.now() - data.updatedAt.getTime()\n if (refreshAge > refreshLifetime) {\n throw new InvalidGrantError(`Refresh token expired`)\n }\n }\n\n /**\n * @see {@link https://datatracker.ietf.org/doc/html/rfc7009#section-2.1 rfc7009}\n */\n public async revoke(\n clientCredentials: OAuthClientCredentials,\n { token }: OAuthTokenIdentification,\n dpopProof: null | DpopProof,\n ) {\n // > The authorization server first validates the client credentials (in\n // > case of a confidential client)\n const { client, clientAuth } = await this.authenticateClient(\n clientCredentials,\n dpopProof,\n )\n\n const tokenInfo = await this.tokenManager.findToken(token)\n if (tokenInfo) {\n // > [...] and then verifies whether the token was issued to the client\n // > making the revocation request.\n const { data } = tokenInfo\n await this.compareClientAuth(client, clientAuth, dpopProof, data)\n\n // > In the next step, the authorization server invalidates the token. The\n // > invalidation takes place immediately, and the token cannot be used\n // > again after the revocation.\n await this.tokenManager.deleteToken(tokenInfo.id)\n }\n }\n\n protected override async decodeToken(\n tokenType: OAuthTokenType,\n token: OAuthAccessToken,\n dpopProof: null | DpopProof,\n ): Promise<AccessTokenPayload> {\n const tokenPayload = await super.decodeToken(tokenType, token, dpopProof)\n\n if (this.accessTokenMode !== AccessTokenMode.stateless) {\n // @NOTE in non stateless mode, some claims can be omitted (most notably\n // \"scope\"). We load the token claims here (allowing to ensure that the\n // token is still valid, and to retrieve a (potentially updated) set of\n // claims).\n\n const tokenClaims = await this.tokenManager.loadTokenClaims(\n tokenType,\n tokenPayload,\n )\n\n Object.assign(tokenPayload, tokenClaims)\n }\n\n return tokenPayload\n }\n}\n\nfunction matchesHint(\n this: OAuthAuthorizationRequestParameters,\n { account }: { account: Account },\n): boolean {\n const hint = this.login_hint\n if (!hint) return false\n\n return account.did === hint || account.handle === hint\n}\n\nfunction hasActiveAccount({ account }: { account: Account }): boolean {\n return !account.deactivated\n}\n"]}
|
|
1
|
+
{"version":3,"file":"oauth-provider.js","sourceRoot":"","sources":["../src/oauth-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from 'node:crypto'\nimport type { Redis, RedisOptions } from 'ioredis'\nimport type { Jwks } from '@atproto/jwk'\nimport { LexResolver } from '@atproto/lex-resolver'\nimport type { Account } from '@atproto/oauth-provider-api'\nimport {\n CLIENT_ASSERTION_TYPE_JWT_BEARER,\n type OAuthAccessToken,\n type OAuthAuthorizationCodeGrantTokenRequest,\n type OAuthAuthorizationRequestJar,\n type OAuthAuthorizationRequestPar,\n type OAuthAuthorizationRequestParameters,\n type OAuthAuthorizationRequestQuery,\n type OAuthAuthorizationServerMetadata,\n type OAuthClientCredentials,\n type OAuthClientMetadata,\n type OAuthParResponse,\n type OAuthRefreshTokenGrantTokenRequest,\n type OAuthTokenIdentification,\n type OAuthTokenRequest,\n type OAuthTokenResponse,\n type OAuthTokenType,\n atprotoLoopbackClientMetadata,\n oauthAuthorizationRequestParametersSchema,\n} from '@atproto/oauth-types'\nimport { safeFetchWrap } from '@atproto-labs/fetch-node'\nimport type { SimpleStore } from '@atproto-labs/simple-store'\nimport { SimpleStoreMemory } from '@atproto-labs/simple-store-memory'\nimport { AccessTokenMode } from './access-token/access-token-mode.js'\nimport { AccountManager } from './account/account-manager.js'\nimport {\n type AccountStore,\n type AuthorizedClientData,\n type DeviceAccount,\n asAccountStore,\n} from './account/account-store.js'\nimport type { ClientAuth, ClientAuthLegacy } from './client/client-auth.js'\nimport type { ClientId } from './client/client-id.js'\nimport {\n ClientManager,\n type LoopbackMetadataGetter,\n} from './client/client-manager.js'\nimport { type ClientStore, ifClientStore } from './client/client-store.js'\nimport type { Client } from './client/client.js'\nimport type { Branding, BrandingConfig } from './customization/branding.js'\nimport {\n type Customization,\n type CustomizationConfig,\n customizationSchema,\n} from './customization/customization.js'\nimport type { DeviceId } from './device/device-id.js'\nimport {\n type DeviceInfo,\n DeviceManager,\n type DeviceManagerOptions,\n} from './device/device-manager.js'\nimport { type DeviceStore, asDeviceStore } from './device/device-store.js'\nimport { AccountSelectionRequiredError } from './errors/account-selection-required-error.js'\nimport { AuthorizationError } from './errors/authorization-error.js'\nimport { ConsentRequiredError } from './errors/consent-required-error.js'\nimport { InvalidDpopKeyBindingError } from './errors/invalid-dpop-key-binding-error.js'\nimport { InvalidDpopProofError } from './errors/invalid-dpop-proof-error.js'\nimport { InvalidGrantError } from './errors/invalid-grant-error.js'\nimport { InvalidRequestError } from './errors/invalid-request-error.js'\nimport { LoginRequiredError } from './errors/login-required-error.js'\nimport { LexiconManager } from './lexicon/lexicon-manager.js'\nimport { type LexiconStore, asLexiconStore } from './lexicon/lexicon-store.js'\nimport type { HcaptchaConfig } from './lib/hcaptcha.js'\nimport type { RequestMetadata } from './lib/http/request.js'\nimport { dateToRelativeSeconds } from './lib/util/date.js'\nimport { formatError } from './lib/util/error.js'\nimport type { MultiLangString } from './lib/util/locale.js'\nimport {\n type CustomMetadata,\n buildMetadata,\n} from './metadata/build-metadata.js'\nimport {\n AUTHENTICATION_MAX_AGE,\n CONFIDENTIAL_CLIENT_REFRESH_LIFETIME,\n CONFIDENTIAL_CLIENT_SESSION_LIFETIME,\n PUBLIC_CLIENT_REFRESH_LIFETIME,\n PUBLIC_CLIENT_SESSION_LIFETIME,\n TOKEN_MAX_AGE,\n} from './oauth-constants.js'\nimport type { OAuthHooks } from './oauth-hooks.js'\nimport {\n type DpopProof,\n OAuthVerifier,\n type OAuthVerifierOptions,\n type VerifyTokenPayloadOptions,\n} from './oauth-verifier.js'\nimport { type ReplayStore, ifReplayStore } from './replay/replay-store.js'\nimport { codeSchema } from './request/code.js'\nimport { RequestManager } from './request/request-manager.js'\nimport { type RequestStore, asRequestStore } from './request/request-store.js'\nimport { parseRequestUri } from './request/request-uri.js'\nimport type { AuthorizationRedirectParameters } from './result/authorization-redirect-parameters.js'\nimport type { AuthorizationResultAuthorizePage } from './result/authorization-result-authorize-page.js'\nimport type { AuthorizationResultRedirect } from './result/authorization-result-redirect.js'\nimport type { ErrorHandler } from './router/error-handler.js'\nimport type { AccessTokenPayload } from './signer/access-token-payload.js'\nimport { refreshTokenSchema } from './token/refresh-token.js'\nimport type { TokenData } from './token/token-data.js'\nimport { TokenManager } from './token/token-manager.js'\nimport { type TokenStore, asTokenStore } from './token/token-store.js'\nimport { isPARResponseError } from './types/par-response-error.js'\n\n// Re-export dependencies that are part of the public API of this package, so\n// that consumers don't have to install them separately.\nexport { safeFetchWrap } from '@atproto-labs/fetch-node'\nexport type * from '@atproto/jwk'\nexport { Keyset } from '@atproto/jwk'\nexport type * from '@atproto/jwk-jose'\nexport { JoseKey } from '@atproto/jwk-jose'\nexport type * from '@atproto/lex-resolver'\nexport { LexResolver } from '@atproto/lex-resolver'\n\nexport { AccessTokenMode }\nexport type {\n AccessTokenPayload,\n AuthorizationRedirectParameters,\n AuthorizationResultAuthorizePage as AuthorizationResultAuthorize,\n AuthorizationResultRedirect,\n Branding,\n BrandingConfig,\n CustomMetadata,\n Customization,\n CustomizationConfig,\n ErrorHandler,\n HcaptchaConfig,\n LoopbackMetadataGetter,\n MultiLangString,\n OAuthAuthorizationServerMetadata,\n VerifyTokenPayloadOptions,\n}\n\nexport type ClientJwksCache = SimpleStore<string, Jwks>\nexport type ClientMetadataCache = SimpleStore<string, OAuthClientMetadata>\nexport type OAuthStore = AccountStore &\n ClientStore &\n DeviceStore &\n LexiconStore &\n ReplayStore &\n RequestStore &\n TokenStore\n\ntype OAuthProviderConfig = {\n /**\n * Maximum age a device/account session can be before requiring\n * re-authentication.\n */\n authenticationMaxAge?: number\n\n /**\n * Maximum age access & id tokens can be before requiring a refresh.\n */\n tokenMaxAge?: number\n\n /**\n * If set to {@link AccessTokenMode.stateless}, the generated access tokens\n * will contain all the necessary information to validate the token without\n * needing to query the database. This is useful for cases where the Resource\n * Server is on a different host/server than the Authorization Server.\n *\n * When set to {@link AccessTokenMode.light}, the access tokens will contain\n * only the necessary information to validate the token, but the token id\n * will need to be queried from the database to retrieve the full token\n * information (scope, audience, etc.)\n *\n * @see {@link AccessTokenMode}\n * @default {AccessTokenMode.stateless}\n */\n accessTokenMode?: AccessTokenMode\n\n /**\n * Additional metadata to be included in the discovery document.\n */\n metadata?: CustomMetadata\n\n /**\n * A Lexicon resolver instance to use for fetching lexicon schemas.\n */\n lexResolver?: LexResolver\n\n /**\n * A custom fetch function that can be used to fetch the client metadata from\n * the internet. By default, the fetch function is a safeFetchWrap() function\n * that protects against SSRF attacks, large responses & known bad domains. If\n * you want to disable all protections, you can provide `globalThis.fetch` as\n * fetch function.\n */\n safeFetch?: typeof globalThis.fetch\n\n /**\n * A redis instance to use for replay protection. If not provided, replay\n * protection will use memory storage.\n */\n redis?: Redis | RedisOptions | string\n\n /**\n * This will be used as the default store for all the stores. If a store is\n * not provided, this store will be used instead. If the `store` does not\n * implement a specific store, a runtime error will be thrown. Make sure that\n * this store implements all the interfaces not provided in the other\n * `<name>Store` options.\n */\n store?: Partial<OAuthStore>\n\n accountStore?: AccountStore\n clientStore?: ClientStore\n deviceStore?: DeviceStore\n lexiconStore?: LexiconStore\n replayStore?: ReplayStore\n requestStore?: RequestStore\n tokenStore?: TokenStore\n\n /**\n * In order to speed up the client fetching process, you can provide a cache\n * to store HTTP responses.\n *\n * @note the cached entries should automatically expire after a certain time (typically 10 minutes)\n */\n clientJwksCache?: ClientJwksCache\n\n /**\n * In order to speed up the client fetching process, you can provide a cache\n * to store HTTP responses.\n *\n * @note the cached entries should automatically expire after a certain time (typically 10 minutes)\n */\n clientMetadataCache?: ClientMetadataCache\n\n /**\n * In order to enable loopback clients, you can provide a function that\n * returns the client metadata for a given loopback URL. This is useful for\n * development and testing purposes. This function is not called for internet\n * clients.\n *\n * @default is as specified by ATPROTO\n */\n loopbackMetadata?: null | false | LoopbackMetadataGetter\n}\n\nexport type OAuthProviderOptions = OAuthProviderConfig &\n OAuthVerifierOptions &\n OAuthHooks &\n DeviceManagerOptions &\n CustomizationConfig\n\nexport class OAuthProvider extends OAuthVerifier {\n protected readonly accessTokenMode: AccessTokenMode\n protected readonly hooks: OAuthHooks\n\n public readonly metadata: OAuthAuthorizationServerMetadata\n public readonly customization: Customization\n\n public readonly authenticationMaxAge: number\n\n public readonly accountManager: AccountManager\n public readonly deviceManager: DeviceManager\n public readonly clientManager: ClientManager\n public readonly lexiconManager: LexiconManager\n public readonly requestManager: RequestManager\n public readonly tokenManager: TokenManager\n\n public constructor({\n // OAuthProviderConfig\n authenticationMaxAge = AUTHENTICATION_MAX_AGE,\n tokenMaxAge = TOKEN_MAX_AGE,\n accessTokenMode = AccessTokenMode.stateless,\n\n metadata,\n loopbackMetadata = atprotoLoopbackClientMetadata,\n\n // Services\n safeFetch = safeFetchWrap(),\n lexResolver = new LexResolver({ fetch: safeFetch }),\n\n // compound store implementation\n store,\n\n // Required stores\n accountStore = asAccountStore(store),\n deviceStore = asDeviceStore(store),\n lexiconStore = asLexiconStore(store),\n tokenStore = asTokenStore(store),\n requestStore = asRequestStore(store),\n\n // Optional stores\n clientStore = ifClientStore(store),\n replayStore = ifReplayStore(store),\n\n clientJwksCache = new SimpleStoreMemory({\n maxSize: 50_000_000,\n ttl: 600e3,\n }),\n clientMetadataCache = new SimpleStoreMemory({\n maxSize: 50_000_000,\n ttl: 600e3,\n }),\n\n // OAuthHooks &\n // OAuthVerifierOptions &\n // DeviceManagerOptions &\n // Customization\n ...rest\n }: OAuthProviderOptions) {\n super({ replayStore, ...rest })\n\n // @NOTE: hooks don't really need a type parser, as all zod can actually\n // check at runtime is the fact that the values are functions. The only way\n // we would benefit from zod here would be to wrap the functions with a\n // validator for the provided function's return types, which we don't\n // really need if types are respected.\n this.hooks = rest\n\n this.accessTokenMode = accessTokenMode\n this.authenticationMaxAge = authenticationMaxAge\n this.metadata = buildMetadata(this.issuer, this.keyset, metadata)\n this.customization = customizationSchema.parse(rest)\n\n this.deviceManager = new DeviceManager(deviceStore, {\n ...rest,\n cookie: {\n ...rest.cookie,\n // \"secure\" defaults to \"true\" in DeviceManager. For the oauth routes to\n // work from localhost on Safari, we need to explicitly set secure to\n // false for localhost usage. This is not really an issue with Chrome\n // and Firefox, but Safari enforces it strictly.\n secure: !this.issuer.startsWith('http:'),\n },\n })\n this.accountManager = new AccountManager(\n this.issuer,\n accountStore,\n this.hooks,\n this.customization,\n )\n this.clientManager = new ClientManager(\n this.metadata,\n this.keyset,\n this.hooks,\n clientStore || null,\n loopbackMetadata || null,\n safeFetch,\n clientJwksCache,\n clientMetadataCache,\n )\n this.lexiconManager = new LexiconManager(lexiconStore, lexResolver)\n this.requestManager = new RequestManager(\n requestStore,\n this.lexiconManager,\n this.signer,\n this.metadata,\n this.hooks,\n )\n this.tokenManager = new TokenManager(\n tokenStore,\n this.lexiconManager,\n this.signer,\n this.hooks,\n this.accessTokenMode,\n tokenMaxAge,\n )\n }\n\n get jwks() {\n return this.keyset.publicJwks\n }\n\n /**\n * @returns true if the user's consent is required for the requested scopes\n */\n public checkConsentRequired(\n parameters: OAuthAuthorizationRequestParameters,\n clientData?: AuthorizedClientData,\n ) {\n // Client was never authorized before\n if (!clientData) return true\n\n // Client explicitly asked for consent\n if (parameters.prompt === 'consent') return true\n\n // No scope requested, and client is known by user, no consent required\n const requestedScopes = parameters.scope?.split(' ')\n if (requestedScopes == null) return false\n\n // Ensure that all requested scopes were previously authorized by the user\n const { authorizedScopes } = clientData\n return !requestedScopes.every((scope) => authorizedScopes.includes(scope))\n }\n\n public checkLoginRequired(deviceAccount: DeviceAccount) {\n const authAge = Date.now() - deviceAccount.updatedAt.getTime()\n return authAge > this.authenticationMaxAge\n }\n\n protected async authenticateClient(\n clientCredentials: OAuthClientCredentials,\n dpopProof: null | DpopProof,\n options?: {\n allowMissingDpopProof?: boolean\n },\n ): Promise<{\n client: Client\n clientAuth: ClientAuth\n }> {\n const client = await this.clientManager.getClient(\n clientCredentials.client_id,\n )\n\n if (\n client.metadata.dpop_bound_access_tokens &&\n !dpopProof &&\n !options?.allowMissingDpopProof\n ) {\n throw new InvalidDpopProofError('DPoP proof required')\n }\n\n if (dpopProof && !client.metadata.dpop_bound_access_tokens) {\n throw new InvalidDpopProofError('DPoP proof not allowed for this client')\n }\n\n const clientAuth = await client.authenticate(clientCredentials, {\n authorizationServerIdentifier: this.issuer,\n })\n\n if (clientAuth.method === 'private_key_jwt') {\n // Clients MUST NOT use their client assertion key to sign DPoP proofs\n if (dpopProof && clientAuth.jkt === dpopProof.jkt) {\n throw new InvalidRequestError(\n 'The DPoP proof must be signed with a different key than the client assertion',\n )\n }\n\n // https://www.rfc-editor.org/rfc/rfc7523.html#section-3\n // > 7. [...] The authorization server MAY ensure that JWTs are not\n // > replayed by maintaining the set of used \"jti\" values for the\n // > length of time for which the JWT would be considered valid based\n // > on the applicable \"exp\" instant.\n\n const unique = await this.replayManager.uniqueAuth(\n clientAuth.jti,\n client.id,\n clientAuth.exp,\n )\n if (!unique) {\n throw new InvalidGrantError(`${clientAuth.method} jti reused`)\n }\n }\n\n return { client, clientAuth }\n }\n\n async decodeJAR(\n client: Client,\n input: OAuthAuthorizationRequestJar,\n ): Promise<OAuthAuthorizationRequestParameters> {\n const { payload } = await client.decodeRequestObject(\n input.request,\n this.issuer,\n )\n\n const { jti } = payload\n if (!jti) {\n throw new InvalidRequestError(\n 'Request object payload must contain a \"jti\" claim',\n )\n }\n if (!(await this.replayManager.uniqueJar(jti, client.id))) {\n throw new InvalidRequestError('Request object was replayed')\n }\n\n const parameters = await oauthAuthorizationRequestParametersSchema\n .parseAsync(payload)\n .catch((err) => {\n const msg = formatError(err, 'Invalid parameters in JAR')\n throw new InvalidRequestError(msg, err)\n })\n\n return parameters\n }\n\n /**\n * @see {@link https://datatracker.ietf.org/doc/html/rfc9126}\n */\n public async pushedAuthorizationRequest(\n credentials: OAuthClientCredentials,\n authorizationRequest: OAuthAuthorizationRequestPar,\n dpopProof: null | DpopProof,\n ): Promise<OAuthParResponse> {\n try {\n const { client, clientAuth } = await this.authenticateClient(\n credentials,\n dpopProof,\n // Allow missing DPoP header for PAR requests as rfc9449 allows it\n // (though the dpop_jkt parameter must be present in that case, see\n // check bellow).\n { allowMissingDpopProof: true },\n )\n\n const parameters =\n 'request' in authorizationRequest // Handle JAR\n ? await this.decodeJAR(client, authorizationRequest)\n : authorizationRequest\n\n if (!parameters.dpop_jkt) {\n if (client.metadata.dpop_bound_access_tokens) {\n if (dpopProof) parameters.dpop_jkt = dpopProof.jkt\n else {\n // @NOTE When both PAR and DPoP are used, either the DPoP header, or\n // the dpop_jkt parameter must be present. We do not enforce this\n // for legacy reasons.\n // https://datatracker.ietf.org/doc/html/rfc9449#section-10.1\n }\n }\n } else {\n if (!client.metadata.dpop_bound_access_tokens) {\n throw new InvalidRequestError(\n 'DPoP bound access tokens are not enabled for this client',\n )\n }\n\n // Proof is optional if the dpop_jkt is provided, but if it is provided,\n // it must match the DPoP proof JKT.\n if (dpopProof && dpopProof.jkt !== parameters.dpop_jkt) {\n throw new InvalidDpopKeyBindingError()\n }\n }\n\n const { requestUri, expiresAt } =\n await this.requestManager.createAuthorizationRequest(\n client,\n clientAuth,\n parameters,\n null,\n )\n\n return {\n request_uri: requestUri,\n expires_in: dateToRelativeSeconds(expiresAt),\n }\n } catch (err) {\n // https://datatracker.ietf.org/doc/html/rfc9126#section-2.3-1\n // > Since initial processing of the pushed authorization request does not\n // > involve resource owner interaction, error codes related to user\n // > interaction, such as \"access_denied\", are never returned.\n if (err instanceof AuthorizationError && !isPARResponseError(err.error)) {\n throw new InvalidRequestError(err.error_description, err)\n }\n throw err\n }\n }\n\n private async processAuthorizationRequest(\n client: Client,\n deviceId: DeviceId,\n query: OAuthAuthorizationRequestQuery,\n ) {\n // PAR\n if ('request_uri' in query) {\n const requestUri = parseRequestUri(query.request_uri, {\n path: ['query', 'request_uri'],\n })\n return this.requestManager.get(requestUri, deviceId, client.id)\n }\n\n // JAR\n if ('request' in query) {\n // @NOTE Since JAR are signed with the client's private key, a JAR *could*\n // technically be used to authenticate the client when requests are\n // created without PAR (i.e. created on the fly by the authorize\n // endpoint). This implementation actually used to support this\n // (un-spec'd) behavior. That support was removed:\n // - Because it was not actually used\n // - Because it was not part of any standard\n // - Because it makes extending the client authentication mechanism more\n // complex since any extension would not only need to affect the\n // \"private_key_jwt\" auth method but also the JAR \"request\" object.\n const parameters = await this.decodeJAR(client, query)\n\n return this.requestManager.createAuthorizationRequest(\n client,\n null,\n parameters,\n deviceId,\n )\n }\n\n // \"Regular\" authorization request (created on the fly by directing the user\n // to the authorization endpoint with all the parameters in the url).\n return this.requestManager.createAuthorizationRequest(\n client,\n null,\n query,\n deviceId,\n )\n }\n\n /**\n * @see {@link https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-11#section-4.1.1}\n */\n public async authorize(\n query: OAuthAuthorizationRequestQuery,\n { deviceId, deviceMetadata }: DeviceInfo,\n ): Promise<AuthorizationResultRedirect | AuthorizationResultAuthorizePage> {\n const { issuer } = this\n\n // If there is a chance to redirect the user to the client, let's do\n // it by wrapping the error in an AuthorizationError.\n const throwAuthorizationError =\n 'redirect_uri' in query\n ? (err: unknown): never => {\n // https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-11#section-4.1.2.1\n throw AuthorizationError.from(query, err)\n }\n : null\n\n const client = await this.clientManager\n .getClient(query.client_id)\n .catch(throwAuthorizationError)\n\n const { parameters, requestUri } = await this.processAuthorizationRequest(\n client,\n deviceId,\n query,\n ).catch(throwAuthorizationError)\n\n try {\n const sessions = (\n await this.accountManager.listDeviceAccounts(deviceId)\n ).map((deviceAccount) => ({\n account: deviceAccount.account,\n\n // @TODO Return the session expiration date instead of a boolean to\n // avoid having to rely on a leeway when \"accepting\" the request.\n loginRequired:\n parameters.prompt === 'login' ||\n this.checkLoginRequired(deviceAccount),\n consentRequired: this.checkConsentRequired(\n parameters,\n deviceAccount.authorizedClients.get(client.id),\n ),\n }))\n\n // https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest\n\n // prompt=select_account\n //\n // > The Authorization Server SHOULD prompt the End-User to select a user\n // > account. This enables an End-User who has multiple accounts at the\n // > Authorization Server to select amongst the multiple accounts that\n // > they might have current sessions for. If it cannot obtain an account\n // > selection choice made by the End-User, it MUST return an error,\n // > typically account_selection_required.\n if (parameters.prompt === 'select_account' && !sessions.length) {\n throw new AccountSelectionRequiredError(parameters)\n }\n\n const ssoSessions = sessions\n .filter(hasActiveAccount)\n .filter(matchesHint, parameters)\n\n // prompt=none\n //\n // > The Authorization Server MUST NOT display any authentication or\n // > consent user interface pages. An error is returned if an End-User is\n // > not already authenticated or the Client does not have pre-configured\n // > consent for the requested Claims or does not fulfill other conditions\n // > for processing the request. The error code will typically be\n // > login_required, interaction_required, or another code defined in\n // > Section 3.1.2.6. This can be used as a method to check for existing\n // > authentication and/or consent.\n if (parameters.prompt === 'none') {\n if (ssoSessions.length > 1) {\n throw new AccountSelectionRequiredError(parameters)\n }\n if (ssoSessions.length < 1) {\n throw new LoginRequiredError(parameters)\n }\n\n const ssoSession = ssoSessions[0]!\n if (ssoSession.loginRequired) {\n throw new LoginRequiredError(parameters)\n }\n if (ssoSession.consentRequired) {\n throw new ConsentRequiredError(parameters)\n }\n\n const code = await this.requestManager.setAuthorized(\n requestUri,\n client,\n ssoSession.account,\n deviceId,\n deviceMetadata,\n )\n\n return { issuer, parameters, redirect: { code } }\n }\n\n // Automatic SSO when a hint was provided that matches a single session\n if (parameters.prompt == null && parameters.login_hint != null) {\n if (ssoSessions.length === 1) {\n const ssoSession = ssoSessions[0]!\n if (!ssoSession.loginRequired && !ssoSession.consentRequired) {\n const code = await this.requestManager.setAuthorized(\n requestUri,\n client,\n ssoSession.account,\n deviceId,\n deviceMetadata,\n )\n\n return { issuer, parameters, redirect: { code } }\n }\n }\n }\n\n return {\n issuer,\n client,\n parameters,\n requestUri,\n sessions: sessions\n // Strip un-necessary information (like consentRequired)\n .map(({ account, loginRequired }) => ({ account, loginRequired })),\n selectedDid:\n parameters.prompt == null ||\n parameters.prompt === 'login' ||\n parameters.prompt === 'consent'\n ? sessions.find(matchesHint, parameters)?.account.did\n : undefined,\n permissionSets: await this.lexiconManager\n .getPermissionSetsFromScope(parameters.scope)\n .catch((cause) => {\n throw new AuthorizationError(\n parameters,\n 'Unable to retrieve permission sets',\n 'invalid_scope',\n cause,\n )\n }),\n }\n } catch (err) {\n try {\n await this.requestManager.delete(requestUri)\n } catch {\n // There are two error here. Better keep the outer one.\n //\n // @TODO Maybe move this entire code to the /authorize endpoint\n // (allowing to log this error)\n }\n\n throw AuthorizationError.from(parameters, err)\n }\n }\n\n public async token(\n clientCredentials: OAuthClientCredentials,\n clientMetadata: RequestMetadata,\n request: OAuthTokenRequest,\n dpopProof: null | DpopProof,\n ): Promise<OAuthTokenResponse> {\n const { client, clientAuth } = await this.authenticateClient(\n clientCredentials,\n dpopProof,\n )\n\n if (!this.metadata.grant_types_supported?.includes(request.grant_type)) {\n throw new InvalidGrantError(\n `Grant type \"${request.grant_type}\" is not supported by the server`,\n )\n }\n\n if (!client.metadata.grant_types.includes(request.grant_type)) {\n throw new InvalidGrantError(\n `\"${request.grant_type}\" grant type is not allowed for this client`,\n )\n }\n\n if (request.grant_type === 'authorization_code') {\n return this.authorizationCodeGrant(\n client,\n clientAuth,\n clientMetadata,\n request,\n dpopProof,\n )\n }\n\n if (request.grant_type === 'refresh_token') {\n return this.refreshTokenGrant(\n client,\n clientAuth,\n clientMetadata,\n request,\n dpopProof,\n )\n }\n\n throw new InvalidGrantError(\n `Grant type \"${request.grant_type}\" not supported`,\n )\n }\n\n protected async compareClientAuth(\n client: Client,\n clientAuth: ClientAuth,\n dpopProof: null | DpopProof,\n initial: {\n parameters: OAuthAuthorizationRequestParameters\n clientId: ClientId\n clientAuth: null | ClientAuth | ClientAuthLegacy\n },\n ): Promise<void> {\n // Fool proofing, ensure that the client is authenticating using the right method\n if (clientAuth.method !== client.metadata.token_endpoint_auth_method) {\n throw new InvalidGrantError(\n `Client authentication method mismatch (expected ${client.metadata.token_endpoint_auth_method}, got ${clientAuth.method})`,\n )\n }\n\n if (initial.clientId !== client.id) {\n throw new InvalidGrantError(`Token was not issued to this client`)\n }\n\n const { parameters } = initial\n if (parameters.dpop_jkt) {\n if (!dpopProof) {\n throw new InvalidGrantError(`DPoP proof is required for this request`)\n } else if (parameters.dpop_jkt !== dpopProof.jkt) {\n throw new InvalidGrantError(\n `DPoP proof does not match the expected JKT`,\n )\n }\n }\n\n if (!initial.clientAuth) {\n // If the client did not use PAR, it was not authenticated when the request\n // was initially created (see authorize() method in OAuthProvider). Since\n // PAR is not mandatory, and since the token exchange currently taking place\n // *is* authenticated (`clientAuth`), we allow \"upgrading\" the\n // authentication method (the token created will be bound to the current\n // clientAuth).\n return\n }\n\n switch (initial.clientAuth.method) {\n case CLIENT_ASSERTION_TYPE_JWT_BEARER: // LEGACY\n case 'private_key_jwt':\n if (clientAuth.method !== 'private_key_jwt') {\n throw new InvalidGrantError(\n `Client authentication method mismatch (expected ${initial.clientAuth.method})`,\n )\n }\n if (\n clientAuth.kid !== initial.clientAuth.kid ||\n clientAuth.alg !== initial.clientAuth.alg ||\n clientAuth.jkt !== initial.clientAuth.jkt\n ) {\n throw new InvalidGrantError(\n `The session was initiated with a different key than the client assertion currently used`,\n )\n }\n break\n case 'none':\n // @NOTE We allow the client to \"upgrade\" to a confidential client if\n // the session was initially created without client authentication.\n break\n default:\n throw new InvalidGrantError(\n // @ts-expect-error (future proof, backwards compatibility)\n `Invalid method \"${initial.clientAuth.method}\"`,\n )\n }\n }\n\n protected async authorizationCodeGrant(\n client: Client,\n clientAuth: ClientAuth,\n clientMetadata: RequestMetadata,\n input: OAuthAuthorizationCodeGrantTokenRequest,\n dpopProof: null | DpopProof,\n ): Promise<OAuthTokenResponse> {\n const code = await codeSchema\n .parseAsync(input.code, { path: ['code'] })\n .catch((err) => {\n const msg = formatError(err, 'Invalid code')\n throw new InvalidGrantError(msg, err)\n })\n\n const data = await this.requestManager\n .consumeCode(code)\n .catch(async (err) => {\n // Code not found in request manager: check for replays\n const tokenInfo = await this.tokenManager.findByCode(code)\n if (tokenInfo) {\n // try/finally to ensure that both code path get executed (sequentially)\n try {\n // \"code\" was replayed, delete existing session\n await this.tokenManager.deleteToken(tokenInfo.id)\n } finally {\n // As an additional security measure, we also sign the device out,\n // so that the device cannot be used to access the account anymore\n // without a new authentication.\n const { deviceId, did } = tokenInfo.data\n if (deviceId) {\n await this.accountManager.removeDeviceAccount(deviceId, did)\n }\n }\n }\n\n throw InvalidGrantError.from(err, `Invalid code`)\n })\n\n // @NOTE at this point, the request data was removed from the store and only\n // exists in memory here (in the \"data\" variable). Because of this, any\n // error thrown after this point will permanently cause the request data to\n // be lost.\n\n await this.compareClientAuth(client, clientAuth, dpopProof, data)\n\n // If the DPoP proof was not provided earlier (PAR / authorize), let's add\n // it now.\n const parameters =\n dpopProof &&\n client.metadata.dpop_bound_access_tokens &&\n !data.parameters.dpop_jkt\n ? { ...data.parameters, dpop_jkt: dpopProof.jkt }\n : data.parameters\n\n await this.validateCodeGrant(parameters, input)\n\n const { account } = await this.accountManager.getAccount(data.did)\n\n return this.tokenManager.createToken(\n client,\n clientAuth,\n clientMetadata,\n account,\n data.deviceId,\n parameters,\n code,\n )\n }\n\n protected async validateCodeGrant(\n parameters: OAuthAuthorizationRequestParameters,\n input: OAuthAuthorizationCodeGrantTokenRequest,\n ): Promise<void> {\n if (parameters.redirect_uri !== input.redirect_uri) {\n throw new InvalidGrantError(\n 'The redirect_uri parameter must match the one used in the authorization request',\n )\n }\n\n if (parameters.code_challenge) {\n if (!input.code_verifier) {\n throw new InvalidGrantError('code_verifier is required')\n }\n if (input.code_verifier.length < 43) {\n throw new InvalidGrantError('code_verifier too short')\n }\n switch (parameters.code_challenge_method) {\n case undefined: // default is \"plain\"\n case 'plain':\n if (parameters.code_challenge !== input.code_verifier) {\n throw new InvalidGrantError('Invalid code_verifier')\n }\n break\n\n case 'S256': {\n const inputChallenge = Buffer.from(\n parameters.code_challenge,\n 'base64',\n )\n const computedChallenge = createHash('sha256')\n .update(input.code_verifier)\n .digest()\n if (inputChallenge.compare(computedChallenge) !== 0) {\n throw new InvalidGrantError('Invalid code_verifier')\n }\n break\n }\n\n default:\n // Should never happen (because request validation should catch this)\n throw new Error(`Unsupported code_challenge_method`)\n }\n const unique = await this.replayManager.uniqueCodeChallenge(\n parameters.code_challenge,\n )\n if (!unique) {\n throw new InvalidGrantError('Code challenge already used')\n }\n } else if (input.code_verifier !== undefined) {\n throw new InvalidRequestError(\"code_challenge parameter wasn't provided\")\n }\n }\n\n protected async refreshTokenGrant(\n client: Client,\n clientAuth: ClientAuth,\n clientMetadata: RequestMetadata,\n input: OAuthRefreshTokenGrantTokenRequest,\n dpopProof: null | DpopProof,\n ): Promise<OAuthTokenResponse> {\n const refreshToken = await refreshTokenSchema\n .parseAsync(input.refresh_token, { path: ['refresh_token'] })\n .catch((err) => {\n const msg = formatError(err, 'Invalid refresh token')\n throw new InvalidGrantError(msg, err)\n })\n\n const tokenInfo = await this.tokenManager.consumeRefreshToken(refreshToken)\n\n try {\n const { data } = tokenInfo\n await this.compareClientAuth(client, clientAuth, dpopProof, data)\n await this.validateRefreshGrant(client, clientAuth, data)\n\n return await this.tokenManager.rotateToken(\n client,\n clientAuth,\n clientMetadata,\n tokenInfo,\n )\n } catch (err) {\n await this.tokenManager.deleteToken(tokenInfo.id)\n\n throw err\n }\n }\n\n protected async validateRefreshGrant(\n client: Client,\n clientAuth: ClientAuth,\n data: TokenData,\n ): Promise<void> {\n const [sessionLifetime, refreshLifetime] =\n clientAuth.method !== 'none' || client.info.isFirstParty\n ? [\n CONFIDENTIAL_CLIENT_SESSION_LIFETIME,\n CONFIDENTIAL_CLIENT_REFRESH_LIFETIME,\n ]\n : [PUBLIC_CLIENT_SESSION_LIFETIME, PUBLIC_CLIENT_REFRESH_LIFETIME]\n\n const sessionAge = Date.now() - data.createdAt.getTime()\n if (sessionAge > sessionLifetime) {\n throw new InvalidGrantError(`Session expired`)\n }\n\n const refreshAge = Date.now() - data.updatedAt.getTime()\n if (refreshAge > refreshLifetime) {\n throw new InvalidGrantError(`Refresh token expired`)\n }\n }\n\n /**\n * @see {@link https://datatracker.ietf.org/doc/html/rfc7009#section-2.1 rfc7009}\n */\n public async revoke(\n clientCredentials: OAuthClientCredentials,\n { token }: OAuthTokenIdentification,\n dpopProof: null | DpopProof,\n ) {\n // > The authorization server first validates the client credentials (in\n // > case of a confidential client)\n const { client, clientAuth } = await this.authenticateClient(\n clientCredentials,\n dpopProof,\n )\n\n const tokenInfo = await this.tokenManager.findToken(token)\n if (tokenInfo) {\n // > [...] and then verifies whether the token was issued to the client\n // > making the revocation request.\n const { data } = tokenInfo\n await this.compareClientAuth(client, clientAuth, dpopProof, data)\n\n // > In the next step, the authorization server invalidates the token. The\n // > invalidation takes place immediately, and the token cannot be used\n // > again after the revocation.\n await this.tokenManager.deleteToken(tokenInfo.id)\n }\n }\n\n protected override async decodeToken(\n tokenType: OAuthTokenType,\n token: OAuthAccessToken,\n dpopProof: null | DpopProof,\n ): Promise<AccessTokenPayload> {\n const tokenPayload = await super.decodeToken(tokenType, token, dpopProof)\n\n if (this.accessTokenMode !== AccessTokenMode.stateless) {\n // @NOTE in non stateless mode, some claims can be omitted (most notably\n // \"scope\"). We load the token claims here (allowing to ensure that the\n // token is still valid, and to retrieve a (potentially updated) set of\n // claims).\n\n const tokenClaims = await this.tokenManager.loadTokenClaims(\n tokenType,\n tokenPayload,\n )\n\n Object.assign(tokenPayload, tokenClaims)\n }\n\n return tokenPayload\n }\n}\n\nfunction matchesHint(\n this: OAuthAuthorizationRequestParameters,\n { account }: { account: Account },\n): boolean {\n const hint = this.login_hint\n if (!hint) return false\n\n return account.did === hint || account.handle === hint\n}\n\nfunction hasActiveAccount({ account }: { account: Account }): boolean {\n return !account.deactivated\n}\n"]}
|
package/dist/oauth-store.d.ts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Every store file exports all the types needed to implement that store. This
|
|
3
|
-
* files re-exports all the types from the x-store files.
|
|
4
|
-
*/
|
|
5
1
|
export * from './account/account-store.js';
|
|
6
2
|
export * from './client/client-store.js';
|
|
7
3
|
export * from './device/device-store.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-store.d.ts","sourceRoot":"","sources":["../src/oauth-store.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"oauth-store.d.ts","sourceRoot":"","sources":["../src/oauth-store.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAA;AAC1C,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,wBAAwB,CAAA"}
|
package/dist/oauth-store.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Every store file exports all the types needed to implement that store. This
|
|
3
|
-
* files re-exports all the types from the x-store files.
|
|
4
|
-
*/
|
|
5
1
|
export * from './account/account-store.js';
|
|
6
2
|
export * from './client/client-store.js';
|
|
7
3
|
export * from './device/device-store.js';
|
package/dist/oauth-store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-store.js","sourceRoot":"","sources":["../src/oauth-store.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"oauth-store.js","sourceRoot":"","sources":["../src/oauth-store.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAA;AAC1C,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,wBAAwB,CAAA","sourcesContent":["export * from './account/account-store.js'\nexport * from './client/client-store.js'\nexport * from './device/device-store.js'\nexport * from './lexicon/lexicon-store.js'\nexport * from './replay/replay-store.js'\nexport * from './request/request-store.js'\nexport * from './token/token-store.js'\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
import { oauthProtectedResourceMetadataSchema } from '@atproto/oauth-types';
|
|
3
|
+
export declare function buildProtectedResourceMetadata(value: z.input<typeof oauthProtectedResourceMetadataSchema>): {
|
|
4
|
+
resource: "http://127.0.0.1" | "http://localhost" | `http://127.0.0.1#${string}` | `http://127.0.0.1/${string}` | `http://127.0.0.1:${string}` | `http://127.0.0.1?${string}` | `http://[::1]${string}` | `http://localhost#${string}` | `http://localhost/${string}` | `http://localhost:${string}` | `http://localhost?${string}` | `https://${string}`;
|
|
5
|
+
authorization_servers?: ("http://127.0.0.1" | "http://localhost" | `http://127.0.0.1#${string}` | `http://127.0.0.1/${string}` | `http://127.0.0.1:${string}` | `http://127.0.0.1?${string}` | `http://[::1]${string}` | `http://localhost#${string}` | `http://localhost/${string}` | `http://localhost:${string}` | `http://localhost?${string}` | `https://${string}`)[] | undefined;
|
|
6
|
+
jwks_uri?: "http://127.0.0.1" | "http://localhost" | `http://127.0.0.1#${string}` | `http://127.0.0.1/${string}` | `http://127.0.0.1:${string}` | `http://127.0.0.1?${string}` | `http://[::1]${string}` | `http://localhost#${string}` | `http://localhost/${string}` | `http://localhost:${string}` | `http://localhost?${string}` | `https://${string}` | undefined;
|
|
7
|
+
scopes_supported?: string[] | undefined;
|
|
8
|
+
bearer_methods_supported?: ("body" | "header" | "query")[] | undefined;
|
|
9
|
+
resource_signing_alg_values_supported?: string[] | undefined;
|
|
10
|
+
resource_documentation?: "http://127.0.0.1" | "http://localhost" | `http://127.0.0.1#${string}` | `http://127.0.0.1/${string}` | `http://127.0.0.1:${string}` | `http://127.0.0.1?${string}` | `http://[::1]${string}` | `http://localhost#${string}` | `http://localhost/${string}` | `http://localhost:${string}` | `http://localhost?${string}` | `https://${string}` | undefined;
|
|
11
|
+
resource_policy_uri?: "http://127.0.0.1" | "http://localhost" | `http://127.0.0.1#${string}` | `http://127.0.0.1/${string}` | `http://127.0.0.1:${string}` | `http://127.0.0.1?${string}` | `http://[::1]${string}` | `http://localhost#${string}` | `http://localhost/${string}` | `http://localhost:${string}` | `http://localhost?${string}` | `https://${string}` | undefined;
|
|
12
|
+
resource_tos_uri?: "http://127.0.0.1" | "http://localhost" | `http://127.0.0.1#${string}` | `http://127.0.0.1/${string}` | `http://127.0.0.1:${string}` | `http://127.0.0.1?${string}` | `http://[::1]${string}` | `http://localhost#${string}` | `http://localhost/${string}` | `http://localhost:${string}` | `http://localhost?${string}` | `https://${string}` | undefined;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=oauth-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth-utils.d.ts","sourceRoot":"","sources":["../src/oauth-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAC5B,OAAO,EAAE,oCAAoC,EAAE,MAAM,sBAAsB,CAAA;AAE3E,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,oCAAoC,CAAC;;;;;;;;;;EAG5D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth-utils.js","sourceRoot":"","sources":["../src/oauth-utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oCAAoC,EAAE,MAAM,sBAAsB,CAAA;AAE3E,MAAM,UAAU,8BAA8B,CAC5C,KAA2D;IAE3D,OAAO,oCAAoC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;AAC1D,CAAC","sourcesContent":["import type { z } from 'zod'\nimport { oauthProtectedResourceMetadataSchema } from '@atproto/oauth-types'\n\nexport function buildProtectedResourceMetadata(\n value: z.input<typeof oauthProtectedResourceMetadataSchema>,\n) {\n return oauthProtectedResourceMetadataSchema.parse(value)\n}\n"]}
|
package/dist/oauth-verifier.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { Redis, RedisOptions } from 'ioredis';
|
|
2
2
|
import { Key, Keyset } from '@atproto/jwk';
|
|
3
|
-
import { OAuthAccessToken, OAuthIssuerIdentifier, OAuthTokenType } from '@atproto/oauth-types';
|
|
4
|
-
import { DpopManager, DpopManagerOptions } from './dpop/dpop-manager.js';
|
|
3
|
+
import { type OAuthAccessToken, type OAuthIssuerIdentifier, type OAuthTokenType } from '@atproto/oauth-types';
|
|
4
|
+
import { DpopManager, type DpopManagerOptions } from './dpop/dpop-manager.js';
|
|
5
5
|
import { DpopNonce } from './dpop/dpop-nonce.js';
|
|
6
|
-
import { DpopProof } from './dpop/dpop-proof.js';
|
|
7
|
-
import { OAuthHooks } from './oauth-hooks.js';
|
|
6
|
+
import type { DpopProof } from './dpop/dpop-proof.js';
|
|
7
|
+
import type { OAuthHooks } from './oauth-hooks.js';
|
|
8
8
|
import { ReplayManager } from './replay/replay-manager.js';
|
|
9
|
-
import { ReplayStore } from './replay/replay-store.js';
|
|
10
|
-
import { AccessTokenPayload } from './signer/access-token-payload.js';
|
|
9
|
+
import type { ReplayStore } from './replay/replay-store.js';
|
|
10
|
+
import type { AccessTokenPayload } from './signer/access-token-payload.js';
|
|
11
11
|
import { Signer } from './signer/signer.js';
|
|
12
12
|
export type DecodeTokenHook = OAuthHooks['onDecodeToken'];
|
|
13
13
|
export type OAuthVerifierOptions = DpopManagerOptions & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-verifier.d.ts","sourceRoot":"","sources":["../src/oauth-verifier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,GAAG,EAAE,MAAM,EAAe,MAAM,cAAc,CAAA;AACvD,OAAO,EACL,gBAAgB,
|
|
1
|
+
{"version":3,"file":"oauth-verifier.d.ts","sourceRoot":"","sources":["../src/oauth-verifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-verifier.js","sourceRoot":"","sources":["../src/oauth-verifier.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Redis, RedisOptions } from 'ioredis'\nimport { Key, Keyset, isSignedJwt } from '@atproto/jwk'\nimport {\n OAuthAccessToken,\n OAuthIssuerIdentifier,\n OAuthTokenType,\n oauthIssuerIdentifierSchema,\n} from '@atproto/oauth-types'\nimport { DpopManager, DpopManagerOptions } from './dpop/dpop-manager.js'\nimport { DpopNonce } from './dpop/dpop-nonce.js'\nimport { DpopProof } from './dpop/dpop-proof.js'\nimport { InvalidDpopKeyBindingError } from './errors/invalid-dpop-key-binding-error.js'\nimport { InvalidDpopProofError } from './errors/invalid-dpop-proof-error.js'\nimport { InvalidTokenError } from './errors/invalid-token-error.js'\nimport { UseDpopNonceError } from './errors/use-dpop-nonce-error.js'\nimport { WWWAuthenticateError } from './errors/www-authenticate-error.js'\nimport { parseAuthorizationHeader } from './lib/util/authorization-header.js'\nimport { includedIn } from './lib/util/function.js'\nimport { OAuthHooks } from './oauth-hooks.js'\nimport { ReplayManager } from './replay/replay-manager.js'\nimport { ReplayStoreMemory } from './replay/replay-store-memory.js'\nimport { ReplayStoreRedis } from './replay/replay-store-redis.js'\nimport { ReplayStore } from './replay/replay-store.js'\nimport { AccessTokenPayload } from './signer/access-token-payload.js'\nimport { Signer } from './signer/signer.js'\n\nexport type DecodeTokenHook = OAuthHooks['onDecodeToken']\n\nexport type OAuthVerifierOptions = DpopManagerOptions & {\n /**\n * The \"issuer\" identifier of the OAuth provider, this is the base URL of the\n * OAuth provider.\n */\n issuer: URL | string\n\n /**\n * The keyset used to sign access tokens.\n */\n keyset: Keyset | Iterable<Key | undefined | null | false>\n\n /**\n * A redis instance to use for replay protection. If not provided, replay\n * protection will use memory storage.\n */\n redis?: Redis | RedisOptions | string\n\n replayStore?: ReplayStore\n\n onDecodeToken?: DecodeTokenHook\n}\n\nexport type VerifyTokenPayloadOptions = {\n /** One of these audience must be included in the token audience(s) */\n audience?: [string, ...string[]]\n /** One of these scope must be included in the token scope(s) */\n scope?: [string, ...string[]]\n}\n\nexport { DpopNonce, Key, Keyset }\nexport type {\n AccessTokenPayload,\n DpopProof,\n OAuthTokenType,\n RedisOptions,\n ReplayStore,\n}\n\nexport class OAuthVerifier {\n private readonly onDecodeToken?: DecodeTokenHook\n\n public readonly issuer: OAuthIssuerIdentifier\n public readonly keyset: Keyset\n\n public readonly dpopManager: DpopManager\n public readonly replayManager: ReplayManager\n public readonly signer: Signer\n\n constructor({\n redis,\n issuer,\n keyset,\n replayStore = redis != null\n ? new ReplayStoreRedis({ redis })\n : new ReplayStoreMemory(),\n onDecodeToken,\n\n ...rest\n }: OAuthVerifierOptions) {\n const dpopMgrOptions: DpopManagerOptions = rest\n\n const issuerParsed = oauthIssuerIdentifierSchema.parse(issuer)\n const issuerUrl = new URL(issuerParsed)\n\n // @TODO (?) support issuer with path\n if (issuerUrl.pathname !== '/') {\n throw new TypeError(\n `\"issuer\" must be an URL with no path, search or hash (${issuerUrl})`,\n )\n }\n\n this.issuer = issuerParsed\n this.keyset = keyset instanceof Keyset ? keyset : new Keyset(keyset)\n\n this.dpopManager = new DpopManager(dpopMgrOptions)\n this.replayManager = new ReplayManager(replayStore)\n this.signer = new Signer(this.issuer, this.keyset)\n\n this.onDecodeToken = onDecodeToken\n }\n\n public nextDpopNonce() {\n return this.dpopManager.nextNonce()\n }\n\n public async checkDpopProof(\n httpMethod: string,\n httpUrl: Readonly<URL>,\n httpHeaders: Record<string, undefined | string | string[]>,\n accessToken?: string,\n ): Promise<null | DpopProof> {\n const dpopProof = await this.dpopManager.checkProof(\n httpMethod,\n httpUrl,\n httpHeaders,\n accessToken,\n )\n\n if (dpopProof) {\n const unique = await this.replayManager.uniqueDpop(dpopProof.jti)\n if (!unique) throw new InvalidDpopProofError('DPoP proof replayed')\n }\n\n return dpopProof\n }\n\n protected async decodeToken(\n tokenType: OAuthTokenType,\n token: OAuthAccessToken,\n dpopProof: null | DpopProof,\n ): Promise<AccessTokenPayload> {\n if (!isSignedJwt(token)) {\n throw new InvalidTokenError(tokenType, `Malformed token`)\n }\n\n const { payload } = await this.signer\n .verifyAccessToken(token)\n .catch((err) => {\n throw InvalidTokenError.from(err, tokenType)\n })\n\n if (payload.cnf?.jkt) {\n // An access token with a cnf.jkt claim must be a DPoP token\n if (tokenType !== 'DPoP') {\n throw new InvalidTokenError(\n 'DPoP',\n `Access token is bound to a DPoP proof, but token type is ${tokenType}`,\n )\n }\n\n // DPoP token type must be used with a DPoP proof\n if (!dpopProof) {\n throw new InvalidDpopProofError(`DPoP proof required`)\n }\n\n // DPoP proof must be signed with the key that matches the \"cnf\" claim\n if (payload.cnf.jkt !== dpopProof.jkt) {\n throw new InvalidDpopKeyBindingError()\n }\n } else {\n // An access token without a cnf.jkt claim must be a Bearer token\n if (tokenType !== 'Bearer') {\n throw new InvalidTokenError(\n 'Bearer',\n `Bearer token type must be used without a DPoP proof`,\n )\n }\n\n // @NOTE We ignore (but allow) DPoP proofs for Bearer tokens\n }\n\n const payloadOverride = await this.onDecodeToken?.call(null, {\n tokenType,\n token,\n payload,\n dpopProof,\n })\n\n return payloadOverride ?? payload\n }\n\n /**\n * @throws {WWWAuthenticateError}\n * @throws {InvalidTokenError}\n */\n public async authenticateRequest(\n httpMethod: string,\n httpUrl: Readonly<URL>,\n httpHeaders: Record<string, undefined | string | string[]>,\n verifyOptions?: VerifyTokenPayloadOptions,\n ): Promise<AccessTokenPayload> {\n const [tokenType, token] = parseAuthorizationHeader(\n httpHeaders['authorization'],\n )\n try {\n const dpopProof = await this.checkDpopProof(\n httpMethod,\n httpUrl,\n httpHeaders,\n token,\n )\n\n const tokenPayload = await this.decodeToken(tokenType, token, dpopProof)\n\n this.verifyTokenPayload(tokenType, tokenPayload, verifyOptions)\n\n return tokenPayload\n } catch (err) {\n if (err instanceof UseDpopNonceError) throw err.toWwwAuthenticateError()\n if (err instanceof WWWAuthenticateError) throw err\n\n throw InvalidTokenError.from(err, tokenType)\n }\n }\n\n protected verifyTokenPayload(\n tokenType: OAuthTokenType,\n tokenPayload: AccessTokenPayload,\n options?: VerifyTokenPayloadOptions,\n ): void {\n if (options?.audience) {\n const { aud } = tokenPayload\n const hasMatch =\n aud != null &&\n (Array.isArray(aud)\n ? options.audience.some(includedIn, aud)\n : options.audience.includes(aud))\n if (!hasMatch) {\n const details = `(got: ${aud}, expected one of: ${options.audience})`\n throw new InvalidTokenError(tokenType, `Invalid audience ${details}`)\n }\n }\n\n if (options?.scope) {\n const { scope } = tokenPayload\n const scopes = scope?.split(' ')\n if (!scopes || !options.scope.some(includedIn, scopes)) {\n const details = `(got: ${scope}, expected one of: ${options.scope})`\n throw new InvalidTokenError(tokenType, `Invalid scope ${details}`)\n }\n }\n\n if (tokenPayload.exp != null && tokenPayload.exp * 1000 <= Date.now()) {\n const expirationDate = new Date(tokenPayload.exp * 1000).toISOString()\n throw new InvalidTokenError(\n tokenType,\n `Token expired at ${expirationDate}`,\n )\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"oauth-verifier.js","sourceRoot":"","sources":["../src/oauth-verifier.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Redis, RedisOptions } from 'ioredis'\nimport { Key, Keyset, isSignedJwt } from '@atproto/jwk'\nimport {\n type OAuthAccessToken,\n type OAuthIssuerIdentifier,\n type OAuthTokenType,\n oauthIssuerIdentifierSchema,\n} from '@atproto/oauth-types'\nimport { DpopManager, type DpopManagerOptions } from './dpop/dpop-manager.js'\nimport { DpopNonce } from './dpop/dpop-nonce.js'\nimport type { DpopProof } from './dpop/dpop-proof.js'\nimport { InvalidDpopKeyBindingError } from './errors/invalid-dpop-key-binding-error.js'\nimport { InvalidDpopProofError } from './errors/invalid-dpop-proof-error.js'\nimport { InvalidTokenError } from './errors/invalid-token-error.js'\nimport { UseDpopNonceError } from './errors/use-dpop-nonce-error.js'\nimport { WWWAuthenticateError } from './errors/www-authenticate-error.js'\nimport { parseAuthorizationHeader } from './lib/util/authorization-header.js'\nimport { includedIn } from './lib/util/function.js'\nimport type { OAuthHooks } from './oauth-hooks.js'\nimport { ReplayManager } from './replay/replay-manager.js'\nimport { ReplayStoreMemory } from './replay/replay-store-memory.js'\nimport { ReplayStoreRedis } from './replay/replay-store-redis.js'\nimport type { ReplayStore } from './replay/replay-store.js'\nimport type { AccessTokenPayload } from './signer/access-token-payload.js'\nimport { Signer } from './signer/signer.js'\n\nexport type DecodeTokenHook = OAuthHooks['onDecodeToken']\n\nexport type OAuthVerifierOptions = DpopManagerOptions & {\n /**\n * The \"issuer\" identifier of the OAuth provider, this is the base URL of the\n * OAuth provider.\n */\n issuer: URL | string\n\n /**\n * The keyset used to sign access tokens.\n */\n keyset: Keyset | Iterable<Key | undefined | null | false>\n\n /**\n * A redis instance to use for replay protection. If not provided, replay\n * protection will use memory storage.\n */\n redis?: Redis | RedisOptions | string\n\n replayStore?: ReplayStore\n\n onDecodeToken?: DecodeTokenHook\n}\n\nexport type VerifyTokenPayloadOptions = {\n /** One of these audience must be included in the token audience(s) */\n audience?: [string, ...string[]]\n /** One of these scope must be included in the token scope(s) */\n scope?: [string, ...string[]]\n}\n\nexport { DpopNonce, Key, Keyset }\nexport type {\n AccessTokenPayload,\n DpopProof,\n OAuthTokenType,\n RedisOptions,\n ReplayStore,\n}\n\nexport class OAuthVerifier {\n private readonly onDecodeToken?: DecodeTokenHook\n\n public readonly issuer: OAuthIssuerIdentifier\n public readonly keyset: Keyset\n\n public readonly dpopManager: DpopManager\n public readonly replayManager: ReplayManager\n public readonly signer: Signer\n\n constructor({\n redis,\n issuer,\n keyset,\n replayStore = redis != null\n ? new ReplayStoreRedis({ redis })\n : new ReplayStoreMemory(),\n onDecodeToken,\n\n ...rest\n }: OAuthVerifierOptions) {\n const dpopMgrOptions: DpopManagerOptions = rest\n\n const issuerParsed = oauthIssuerIdentifierSchema.parse(issuer)\n const issuerUrl = new URL(issuerParsed)\n\n // @TODO (?) support issuer with path\n if (issuerUrl.pathname !== '/') {\n throw new TypeError(\n `\"issuer\" must be an URL with no path, search or hash (${issuerUrl})`,\n )\n }\n\n this.issuer = issuerParsed\n this.keyset = keyset instanceof Keyset ? keyset : new Keyset(keyset)\n\n this.dpopManager = new DpopManager(dpopMgrOptions)\n this.replayManager = new ReplayManager(replayStore)\n this.signer = new Signer(this.issuer, this.keyset)\n\n this.onDecodeToken = onDecodeToken\n }\n\n public nextDpopNonce() {\n return this.dpopManager.nextNonce()\n }\n\n public async checkDpopProof(\n httpMethod: string,\n httpUrl: Readonly<URL>,\n httpHeaders: Record<string, undefined | string | string[]>,\n accessToken?: string,\n ): Promise<null | DpopProof> {\n const dpopProof = await this.dpopManager.checkProof(\n httpMethod,\n httpUrl,\n httpHeaders,\n accessToken,\n )\n\n if (dpopProof) {\n const unique = await this.replayManager.uniqueDpop(dpopProof.jti)\n if (!unique) throw new InvalidDpopProofError('DPoP proof replayed')\n }\n\n return dpopProof\n }\n\n protected async decodeToken(\n tokenType: OAuthTokenType,\n token: OAuthAccessToken,\n dpopProof: null | DpopProof,\n ): Promise<AccessTokenPayload> {\n if (!isSignedJwt(token)) {\n throw new InvalidTokenError(tokenType, `Malformed token`)\n }\n\n const { payload } = await this.signer\n .verifyAccessToken(token)\n .catch((err) => {\n throw InvalidTokenError.from(err, tokenType)\n })\n\n if (payload.cnf?.jkt) {\n // An access token with a cnf.jkt claim must be a DPoP token\n if (tokenType !== 'DPoP') {\n throw new InvalidTokenError(\n 'DPoP',\n `Access token is bound to a DPoP proof, but token type is ${tokenType}`,\n )\n }\n\n // DPoP token type must be used with a DPoP proof\n if (!dpopProof) {\n throw new InvalidDpopProofError(`DPoP proof required`)\n }\n\n // DPoP proof must be signed with the key that matches the \"cnf\" claim\n if (payload.cnf.jkt !== dpopProof.jkt) {\n throw new InvalidDpopKeyBindingError()\n }\n } else {\n // An access token without a cnf.jkt claim must be a Bearer token\n if (tokenType !== 'Bearer') {\n throw new InvalidTokenError(\n 'Bearer',\n `Bearer token type must be used without a DPoP proof`,\n )\n }\n\n // @NOTE We ignore (but allow) DPoP proofs for Bearer tokens\n }\n\n const payloadOverride = await this.onDecodeToken?.call(null, {\n tokenType,\n token,\n payload,\n dpopProof,\n })\n\n return payloadOverride ?? payload\n }\n\n /**\n * @throws {WWWAuthenticateError}\n * @throws {InvalidTokenError}\n */\n public async authenticateRequest(\n httpMethod: string,\n httpUrl: Readonly<URL>,\n httpHeaders: Record<string, undefined | string | string[]>,\n verifyOptions?: VerifyTokenPayloadOptions,\n ): Promise<AccessTokenPayload> {\n const [tokenType, token] = parseAuthorizationHeader(\n httpHeaders['authorization'],\n )\n try {\n const dpopProof = await this.checkDpopProof(\n httpMethod,\n httpUrl,\n httpHeaders,\n token,\n )\n\n const tokenPayload = await this.decodeToken(tokenType, token, dpopProof)\n\n this.verifyTokenPayload(tokenType, tokenPayload, verifyOptions)\n\n return tokenPayload\n } catch (err) {\n if (err instanceof UseDpopNonceError) throw err.toWwwAuthenticateError()\n if (err instanceof WWWAuthenticateError) throw err\n\n throw InvalidTokenError.from(err, tokenType)\n }\n }\n\n protected verifyTokenPayload(\n tokenType: OAuthTokenType,\n tokenPayload: AccessTokenPayload,\n options?: VerifyTokenPayloadOptions,\n ): void {\n if (options?.audience) {\n const { aud } = tokenPayload\n const hasMatch =\n aud != null &&\n (Array.isArray(aud)\n ? options.audience.some(includedIn, aud)\n : options.audience.includes(aud))\n if (!hasMatch) {\n const details = `(got: ${aud}, expected one of: ${options.audience})`\n throw new InvalidTokenError(tokenType, `Invalid audience ${details}`)\n }\n }\n\n if (options?.scope) {\n const { scope } = tokenPayload\n const scopes = scope?.split(' ')\n if (!scopes || !options.scope.some(includedIn, scopes)) {\n const details = `(got: ${scope}, expected one of: ${options.scope})`\n throw new InvalidTokenError(tokenType, `Invalid scope ${details}`)\n }\n }\n\n if (tokenPayload.exp != null && tokenPayload.exp * 1000 <= Date.now()) {\n const expirationDate = new Date(tokenPayload.exp * 1000).toISOString()\n throw new InvalidTokenError(\n tokenType,\n `Token expired at ${expirationDate}`,\n )\n }\n }\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ClientId } from '../client/client-id.js';
|
|
2
|
-
import { ReplayStore } from './replay-store.js';
|
|
1
|
+
import type { ClientId } from '../client/client-id.js';
|
|
2
|
+
import type { ReplayStore } from './replay-store.js';
|
|
3
3
|
export declare class ReplayManager {
|
|
4
4
|
protected readonly replayStore: ReplayStore;
|
|
5
5
|
constructor(replayStore: ReplayStore);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay-manager.d.ts","sourceRoot":"","sources":["../../src/replay/replay-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"replay-manager.d.ts","sourceRoot":"","sources":["../../src/replay/replay-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAOtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAKpD,qBAAa,aAAa;IACZ,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW;IAAvD,YAA+B,WAAW,EAAE,WAAW,EAAI;IAErD,UAAU,CACd,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,QAAQ,EAClB,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,OAAO,CAAC,CAMlB;IAEK,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAMjE;IAEK,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAMnE;IAEK,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAM7D;CACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CLIENT_ASSERTION_MAX_AGE, CODE_CHALLENGE_REPLAY_TIMEFRAME, DPOP_NONCE_MAX_AGE, JAR_MAX_AGE, } from '../constants.js';
|
|
1
|
+
import { CLIENT_ASSERTION_MAX_AGE, CODE_CHALLENGE_REPLAY_TIMEFRAME, DPOP_NONCE_MAX_AGE, JAR_MAX_AGE, } from '../oauth-constants.js';
|
|
2
2
|
const SECURITY_RATIO = 1.1; // 10% extra time for security
|
|
3
3
|
const asTimeFrame = (timeFrame) => Math.ceil(timeFrame * SECURITY_RATIO);
|
|
4
4
|
export class ReplayManager {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay-manager.js","sourceRoot":"","sources":["../../src/replay/replay-manager.ts"],"names":[],"mappings":"AACA,OAAO,EACL,wBAAwB,EACxB,+BAA+B,EAC/B,kBAAkB,EAClB,WAAW,GACZ,MAAM,
|
|
1
|
+
{"version":3,"file":"replay-manager.js","sourceRoot":"","sources":["../../src/replay/replay-manager.ts"],"names":[],"mappings":"AACA,OAAO,EACL,wBAAwB,EACxB,+BAA+B,EAC/B,kBAAkB,EAClB,WAAW,GACZ,MAAM,uBAAuB,CAAA;AAG9B,MAAM,cAAc,GAAG,GAAG,CAAA,CAAC,8BAA8B;AACzD,MAAM,WAAW,GAAG,CAAC,SAAiB,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,cAAc,CAAC,CAAA;AAEhF,MAAM,OAAO,aAAa;IACxB,YAA+B,WAAwB;2BAAxB,WAAW;IAAgB,CAAC;IAE3D,KAAK,CAAC,UAAU,CACd,GAAW,EACX,QAAkB,EAClB,GAAY;QAEZ,MAAM,SAAS,GACb,GAAG,IAAI,IAAI;YACT,CAAC,CAAC,WAAW,CAAC,wBAAwB,CAAC;YACvC,CAAC,CAAC,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC7B,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,QAAQ,EAAE,EAAE,GAAG,EAAE,SAAS,CAAC,CAAA;IACpE,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,GAAW,EAAE,QAAkB;QAC7C,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAC5B,OAAO,QAAQ,EAAE,EACjB,GAAG,EACH,WAAW,CAAC,WAAW,CAAC,CACzB,CAAA;IACH,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,GAAW,EAAE,QAAmB;QAC/C,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAC5B,QAAQ,CAAC,CAAC,CAAC,QAAQ,QAAQ,EAAE,CAAC,CAAC,CAAC,MAAM,EACtC,GAAG,EACH,WAAW,CAAC,kBAAkB,CAAC,CAChC,CAAA;IACH,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,SAAiB;QACzC,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAC5B,eAAe,EACf,SAAS,EACT,WAAW,CAAC,+BAA+B,CAAC,CAC7C,CAAA;IACH,CAAC;CACF","sourcesContent":["import type { ClientId } from '../client/client-id.js'\nimport {\n CLIENT_ASSERTION_MAX_AGE,\n CODE_CHALLENGE_REPLAY_TIMEFRAME,\n DPOP_NONCE_MAX_AGE,\n JAR_MAX_AGE,\n} from '../oauth-constants.js'\nimport type { ReplayStore } from './replay-store.js'\n\nconst SECURITY_RATIO = 1.1 // 10% extra time for security\nconst asTimeFrame = (timeFrame: number) => Math.ceil(timeFrame * SECURITY_RATIO)\n\nexport class ReplayManager {\n constructor(protected readonly replayStore: ReplayStore) {}\n\n async uniqueAuth(\n jti: string,\n clientId: ClientId,\n exp?: number,\n ): Promise<boolean> {\n const timeFrame =\n exp == null\n ? asTimeFrame(CLIENT_ASSERTION_MAX_AGE)\n : exp * 1000 - Date.now()\n return this.replayStore.unique(`Auth@${clientId}`, jti, timeFrame)\n }\n\n async uniqueJar(jti: string, clientId: ClientId): Promise<boolean> {\n return this.replayStore.unique(\n `JAR@${clientId}`,\n jti,\n asTimeFrame(JAR_MAX_AGE),\n )\n }\n\n async uniqueDpop(jti: string, clientId?: ClientId): Promise<boolean> {\n return this.replayStore.unique(\n clientId ? `DPoP@${clientId}` : `DPoP`,\n jti,\n asTimeFrame(DPOP_NONCE_MAX_AGE),\n )\n }\n\n async uniqueCodeChallenge(challenge: string): Promise<boolean> {\n return this.replayStore.unique(\n 'CodeChallenge',\n challenge,\n asTimeFrame(CODE_CHALLENGE_REPLAY_TIMEFRAME),\n )\n }\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Redis } from 'ioredis';
|
|
2
|
-
import { CreateRedisOptions } from '../lib/redis.js';
|
|
2
|
+
import { type CreateRedisOptions } from '../lib/redis.js';
|
|
3
3
|
import type { ReplayStore } from './replay-store.js';
|
|
4
4
|
export type { CreateRedisOptions, Redis };
|
|
5
5
|
export type ReplayStoreRedisOptions = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay-store-redis.d.ts","sourceRoot":"","sources":["../../src/replay/replay-store-redis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,kBAAkB,EAAe,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"replay-store-redis.d.ts","sourceRoot":"","sources":["../../src/replay/replay-store-redis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,KAAK,kBAAkB,EAAe,MAAM,iBAAiB,CAAA;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEpD,YAAY,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAA;AAEzC,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,kBAAkB,CAAA;CAC1B,CAAA;AAED,qBAAa,gBAAiB,YAAW,WAAW;IAClD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAO;IAE7B,YAAY,OAAO,EAAE,uBAAuB,EAE3C;IAED;;OAEG;IACG,MAAM,CACV,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAIlB;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay-store-redis.js","sourceRoot":"","sources":["../../src/replay/replay-store-redis.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"replay-store-redis.js","sourceRoot":"","sources":["../../src/replay/replay-store-redis.ts"],"names":[],"mappings":"AACA,OAAO,EAA2B,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAStE,MAAM,OAAO,gBAAgB;IAG3B,YAAY,OAAgC;QAC1C,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IACzC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM,CACV,SAAiB,EACjB,KAAa,EACb,SAAiB;QAEjB,MAAM,GAAG,GAAG,UAAU,SAAS,IAAI,KAAK,EAAE,CAAA;QAC1C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,CAAA;QACnE,OAAO,IAAI,IAAI,IAAI,CAAA;IACrB,CAAC;CACF","sourcesContent":["import type { Redis } from 'ioredis'\nimport { type CreateRedisOptions, createRedis } from '../lib/redis.js'\nimport type { ReplayStore } from './replay-store.js'\n\nexport type { CreateRedisOptions, Redis }\n\nexport type ReplayStoreRedisOptions = {\n redis: CreateRedisOptions\n}\n\nexport class ReplayStoreRedis implements ReplayStore {\n private readonly redis: Redis\n\n constructor(options: ReplayStoreRedisOptions) {\n this.redis = createRedis(options.redis)\n }\n\n /**\n * Returns true if the nonce is unique within the given time frame.\n */\n async unique(\n namespace: string,\n nonce: string,\n timeFrame: number,\n ): Promise<boolean> {\n const key = `nonces:${namespace}:${nonce}`\n const prev = await this.redis.set(key, '1', 'PX', timeFrame, 'GET')\n return prev == null\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay-store.d.ts","sourceRoot":"","sources":["../../src/replay/replay-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"replay-store.d.ts","sourceRoot":"","sources":["../../src/replay/replay-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAGpD,YAAY,EAAE,SAAS,EAAE,CAAA;AAEzB,MAAM,WAAW,WAAW;IAC1B;;;;;;OAMG;IACH,MAAM,CACJ,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,GAChB,SAAS,CAAC,OAAO,CAAC,CAAA;CACtB;AAED,wBAAgB,aAAa,CAC3B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,GAC7D,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,CAEzD;AAED,wBAAgB,aAAa,CAC3B,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,GAC9D,WAAW,GAAG,SAAS,CAMzB;AAED,wBAAgB,aAAa,CAC3B,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,GAC9D,WAAW,CAKb"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay-store.js","sourceRoot":"","sources":["../../src/replay/replay-store.ts"],"names":[],"mappings":"AAoBA,MAAM,UAAU,aAAa,CAC3B,cAA8D;IAE9D,OAAO,OAAO,cAAc,CAAC,MAAM,KAAK,UAAU,CAAA;AACpD,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,cAA+D;IAE/D,IAAI,cAAc,IAAI,aAAa,CAAC,cAAc,CAAC,EAAE,CAAC;QACpD,OAAO,cAAc,CAAA;IACvB,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,cAA+D;IAE/D,MAAM,KAAK,GAAG,aAAa,CAAC,cAAc,CAAC,CAAA;IAC3C,IAAI,KAAK;QAAE,OAAO,KAAK,CAAA;IAEvB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;AACvD,CAAC","sourcesContent":["import { Awaitable } from '../lib/util/type.js'\n\n// Export all types needed to implement the ReplayStore interface\nexport type { Awaitable }\n\nexport interface ReplayStore {\n /**\n * Returns true if the nonce is unique within the given time frame. While not\n * strictly necessary for security purposes, the namespace should be used to\n * mitigate denial of service attacks from one client to the other.\n *\n * @param timeFrame expressed in milliseconds.\n */\n unique(\n namespace: string,\n nonce: string,\n timeFrame: number,\n ): Awaitable<boolean>\n}\n\nexport function isReplayStore(\n implementation: Record<string, unknown> & Partial<ReplayStore>,\n): implementation is Record<string, unknown> & ReplayStore {\n return typeof implementation.unique === 'function'\n}\n\nexport function ifReplayStore(\n implementation?: Record<string, unknown> & Partial<ReplayStore>,\n): ReplayStore | undefined {\n if (implementation && isReplayStore(implementation)) {\n return implementation\n }\n\n return undefined\n}\n\nexport function asReplayStore(\n implementation?: Record<string, unknown> & Partial<ReplayStore>,\n): ReplayStore {\n const store = ifReplayStore(implementation)\n if (store) return store\n\n throw new Error('Invalid ReplayStore implementation')\n}\n"]}
|
|
1
|
+
{"version":3,"file":"replay-store.js","sourceRoot":"","sources":["../../src/replay/replay-store.ts"],"names":[],"mappings":"AAoBA,MAAM,UAAU,aAAa,CAC3B,cAA8D;IAE9D,OAAO,OAAO,cAAc,CAAC,MAAM,KAAK,UAAU,CAAA;AACpD,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,cAA+D;IAE/D,IAAI,cAAc,IAAI,aAAa,CAAC,cAAc,CAAC,EAAE,CAAC;QACpD,OAAO,cAAc,CAAA;IACvB,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,cAA+D;IAE/D,MAAM,KAAK,GAAG,aAAa,CAAC,cAAc,CAAC,CAAA;IAC3C,IAAI,KAAK;QAAE,OAAO,KAAK,CAAA;IAEvB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;AACvD,CAAC","sourcesContent":["import type { Awaitable } from '../lib/util/type.js'\n\n// Export all types needed to implement the ReplayStore interface\nexport type { Awaitable }\n\nexport interface ReplayStore {\n /**\n * Returns true if the nonce is unique within the given time frame. While not\n * strictly necessary for security purposes, the namespace should be used to\n * mitigate denial of service attacks from one client to the other.\n *\n * @param timeFrame expressed in milliseconds.\n */\n unique(\n namespace: string,\n nonce: string,\n timeFrame: number,\n ): Awaitable<boolean>\n}\n\nexport function isReplayStore(\n implementation: Record<string, unknown> & Partial<ReplayStore>,\n): implementation is Record<string, unknown> & ReplayStore {\n return typeof implementation.unique === 'function'\n}\n\nexport function ifReplayStore(\n implementation?: Record<string, unknown> & Partial<ReplayStore>,\n): ReplayStore | undefined {\n if (implementation && isReplayStore(implementation)) {\n return implementation\n }\n\n return undefined\n}\n\nexport function asReplayStore(\n implementation?: Record<string, unknown> & Partial<ReplayStore>,\n): ReplayStore {\n const store = ifReplayStore(implementation)\n if (store) return store\n\n throw new Error('Invalid ReplayStore implementation')\n}\n"]}
|
package/dist/request/code.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { CODE_BYTES_LENGTH, CODE_PREFIX } from '../constants.js';
|
|
3
2
|
import { randomHexId } from '../lib/util/crypto.js';
|
|
3
|
+
import { CODE_BYTES_LENGTH, CODE_PREFIX } from '../oauth-constants.js';
|
|
4
4
|
export const CODE_LENGTH = CODE_PREFIX.length + CODE_BYTES_LENGTH * 2; // hex encoding
|
|
5
5
|
export const codeSchema = z
|
|
6
6
|
.string()
|
package/dist/request/code.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code.js","sourceRoot":"","sources":["../../src/request/code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"code.js","sourceRoot":"","sources":["../../src/request/code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACnD,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAEtE,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC,MAAM,GAAG,iBAAiB,GAAG,CAAC,CAAA,CAAC,eAAe;AAErF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC;KACxB,MAAM,EAAE;KACR,MAAM,CAAC,WAAW,CAAC,CAAC,eAAe;KACnC,MAAM,CACL,CAAC,CAAC,EAAyC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,EACvE;IACE,OAAO,EAAE,qBAAqB;CAC/B,CACF,CAAA;AAEH,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,IAAa,EAAgB,EAAE,CACpD,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,CAAA;AAGpC,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,IAAmB,EAAE;IACpD,OAAO,GAAG,WAAW,GAAG,MAAM,WAAW,CAAC,iBAAiB,CAAC,EAAE,CAAA;AAChE,CAAC,CAAA","sourcesContent":["import { z } from 'zod'\nimport { randomHexId } from '../lib/util/crypto.js'\nimport { CODE_BYTES_LENGTH, CODE_PREFIX } from '../oauth-constants.js'\n\nexport const CODE_LENGTH = CODE_PREFIX.length + CODE_BYTES_LENGTH * 2 // hex encoding\n\nexport const codeSchema = z\n .string()\n .length(CODE_LENGTH) // hex encoding\n .refine(\n (v): v is `${typeof CODE_PREFIX}${string}` => v.startsWith(CODE_PREFIX),\n {\n message: `Invalid code format`,\n },\n )\n\nexport const isCode = (data: unknown): data is Code =>\n codeSchema.safeParse(data).success\n\nexport type Code = z.infer<typeof codeSchema>\nexport const generateCode = async (): Promise<Code> => {\n return `${CODE_PREFIX}${await randomHexId(CODE_BYTES_LENGTH)}`\n}\n"]}
|