@atproto/oauth-provider 0.6.5 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/dist/access-token/access-token-mode.d.ts +5 -0
- package/dist/access-token/access-token-mode.d.ts.map +1 -0
- package/dist/access-token/access-token-mode.js +9 -0
- package/dist/access-token/access-token-mode.js.map +1 -0
- package/dist/account/account-manager.d.ts +13 -7
- package/dist/account/account-manager.d.ts.map +1 -1
- package/dist/account/account-manager.js +69 -52
- package/dist/account/account-manager.js.map +1 -1
- package/dist/account/account-store.d.ts +88 -77
- package/dist/account/account-store.d.ts.map +1 -1
- package/dist/account/account-store.js +24 -73
- package/dist/account/account-store.js.map +1 -1
- package/dist/account/sign-in-data.d.ts +4 -13
- package/dist/account/sign-in-data.d.ts.map +1 -1
- package/dist/account/sign-in-data.js +9 -9
- package/dist/account/sign-in-data.js.map +1 -1
- package/dist/account/sign-up-input.d.ts +4 -5
- package/dist/account/sign-up-input.d.ts.map +1 -1
- package/dist/account/sign-up-input.js +13 -3
- package/dist/account/sign-up-input.js.map +1 -1
- package/dist/client/client-manager.d.ts +4 -1
- package/dist/client/client-manager.d.ts.map +1 -1
- package/dist/client/client-manager.js +13 -1
- package/dist/client/client-manager.js.map +1 -1
- package/dist/client/client-store.d.ts +1 -1
- package/dist/client/client-store.d.ts.map +1 -1
- package/dist/constants.d.ts +5 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +6 -2
- package/dist/constants.js.map +1 -1
- package/dist/customization/branding.d.ts +54 -0
- package/dist/customization/branding.d.ts.map +1 -0
- package/dist/customization/branding.js +13 -0
- package/dist/customization/branding.js.map +1 -0
- package/dist/customization/build-customization-css.d.ts +3 -0
- package/dist/customization/build-customization-css.d.ts.map +1 -0
- package/dist/customization/build-customization-css.js +27 -0
- package/dist/customization/build-customization-css.js.map +1 -0
- package/dist/customization/build-customization-data.d.ts +4 -0
- package/dist/customization/build-customization-data.d.ts.map +1 -0
- package/dist/customization/build-customization-data.js +18 -0
- package/dist/customization/build-customization-data.js.map +1 -0
- package/dist/customization/colors.d.ts +7 -0
- package/dist/customization/colors.d.ts.map +1 -0
- package/dist/customization/colors.js +27 -0
- package/dist/customization/colors.js.map +1 -0
- package/dist/customization/customization.d.ts +129 -0
- package/dist/customization/customization.d.ts.map +1 -0
- package/dist/customization/customization.js +26 -0
- package/dist/customization/customization.js.map +1 -0
- package/dist/customization/links.d.ts +26 -0
- package/dist/customization/links.d.ts.map +1 -0
- package/dist/customization/links.js +12 -0
- package/dist/customization/links.js.map +1 -0
- package/dist/device/device-id.d.ts +1 -0
- package/dist/device/device-id.d.ts.map +1 -1
- package/dist/device/device-id.js +4 -0
- package/dist/device/device-id.js.map +1 -1
- package/dist/device/device-manager.d.ts +6 -36
- package/dist/device/device-manager.d.ts.map +1 -1
- package/dist/device/device-manager.js +49 -43
- package/dist/device/device-manager.js.map +1 -1
- package/dist/device/device-store.d.ts +1 -0
- package/dist/device/device-store.d.ts.map +1 -1
- package/dist/device/device-store.js.map +1 -1
- package/dist/dpop/dpop-manager.d.ts +3 -3
- package/dist/dpop/dpop-nonce.d.ts +3 -3
- package/dist/dpop/dpop-nonce.d.ts.map +1 -1
- package/dist/errors/access-denied-error.d.ts +4 -3
- package/dist/errors/access-denied-error.d.ts.map +1 -1
- package/dist/errors/access-denied-error.js +5 -6
- package/dist/errors/access-denied-error.js.map +1 -1
- package/dist/{output/build-error-payload.d.ts → errors/error-parser.d.ts} +1 -1
- package/dist/errors/error-parser.d.ts.map +1 -0
- package/dist/{output/build-error-payload.js → errors/error-parser.js} +2 -2
- package/dist/errors/error-parser.js.map +1 -0
- package/dist/errors/invalid-grant-error.d.ts +1 -0
- package/dist/errors/invalid-grant-error.d.ts.map +1 -1
- package/dist/errors/invalid-grant-error.js +5 -0
- package/dist/errors/invalid-grant-error.js.map +1 -1
- package/dist/errors/login-required-error.d.ts +1 -0
- package/dist/errors/login-required-error.d.ts.map +1 -1
- package/dist/errors/login-required-error.js +5 -0
- package/dist/errors/login-required-error.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/html/build-document.d.ts +2 -2
- package/dist/lib/html/build-document.d.ts.map +1 -1
- package/dist/lib/html/build-document.js +4 -0
- package/dist/lib/html/build-document.js.map +1 -1
- package/dist/lib/html/hydration-data.d.ts +4 -0
- package/dist/lib/html/hydration-data.d.ts.map +1 -0
- package/dist/{output/backend-data.js → lib/html/hydration-data.js} +8 -8
- package/dist/lib/html/hydration-data.js.map +1 -0
- 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 -1
- 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 +1 -1
- package/dist/lib/http/accept.js.map +1 -1
- package/dist/lib/http/context.d.ts +2 -4
- package/dist/lib/http/context.d.ts.map +1 -1
- package/dist/lib/http/context.js +29 -4
- package/dist/lib/http/context.js.map +1 -1
- package/dist/lib/http/headers.d.ts +3 -0
- package/dist/lib/http/headers.d.ts.map +1 -0
- package/dist/lib/http/headers.js +14 -0
- package/dist/lib/http/headers.js.map +1 -0
- package/dist/lib/http/index.d.ts +1 -0
- package/dist/lib/http/index.d.ts.map +1 -1
- package/dist/lib/http/index.js +1 -0
- package/dist/lib/http/index.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 +8 -24
- package/dist/lib/http/middleware.js.map +1 -1
- package/dist/lib/http/parser.d.ts +3 -3
- package/dist/lib/http/parser.d.ts.map +1 -1
- package/dist/lib/http/request.d.ts +13 -9
- package/dist/lib/http/request.d.ts.map +1 -1
- package/dist/lib/http/request.js +27 -49
- package/dist/lib/http/request.js.map +1 -1
- package/dist/lib/http/response.d.ts +6 -2
- package/dist/lib/http/response.d.ts.map +1 -1
- package/dist/lib/http/response.js +31 -11
- package/dist/lib/http/response.js.map +1 -1
- package/dist/lib/http/route.d.ts +3 -3
- package/dist/lib/http/route.d.ts.map +1 -1
- package/dist/lib/http/route.js +1 -1
- package/dist/lib/http/route.js.map +1 -1
- package/dist/lib/http/router.d.ts +12 -11
- package/dist/lib/http/router.d.ts.map +1 -1
- package/dist/lib/http/router.js +26 -34
- package/dist/lib/http/router.js.map +1 -1
- package/dist/lib/http/security-headers.js +1 -1
- package/dist/lib/http/security-headers.js.map +1 -1
- package/dist/lib/http/stream.d.ts +3 -3
- package/dist/lib/http/stream.d.ts.map +1 -1
- package/dist/lib/http/types.d.ts +1 -1
- package/dist/lib/http/types.d.ts.map +1 -1
- package/dist/lib/send-web-page.d.ts +8 -0
- package/dist/lib/send-web-page.d.ts.map +1 -0
- package/dist/{output → lib}/send-web-page.js +9 -7
- package/dist/lib/send-web-page.js.map +1 -0
- package/dist/lib/util/authorization-header.d.ts.map +1 -1
- package/dist/lib/util/color.d.ts +32 -0
- package/dist/lib/util/color.d.ts.map +1 -0
- package/dist/lib/util/color.js +116 -0
- package/dist/lib/util/color.js.map +1 -0
- package/dist/lib/util/crypto.d.ts +1 -0
- package/dist/lib/util/crypto.d.ts.map +1 -1
- package/dist/lib/util/crypto.js +8 -3
- package/dist/lib/util/crypto.js.map +1 -1
- package/dist/lib/util/function.d.ts +1 -0
- package/dist/lib/util/function.d.ts.map +1 -1
- package/dist/lib/util/function.js +12 -0
- package/dist/lib/util/function.js.map +1 -1
- package/dist/lib/util/locale.d.ts +20 -0
- package/dist/lib/util/locale.d.ts.map +1 -0
- package/dist/lib/util/locale.js +14 -0
- package/dist/lib/util/locale.js.map +1 -0
- 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 +1 -1
- package/dist/lib/util/time.js.map +1 -1
- package/dist/lib/util/type.d.ts +22 -0
- package/dist/lib/util/type.d.ts.map +1 -1
- package/dist/lib/util/type.js.map +1 -1
- package/dist/lib/util/ui8.d.ts +4 -0
- package/dist/lib/util/ui8.d.ts.map +1 -0
- package/dist/lib/util/ui8.js +17 -0
- package/dist/lib/util/ui8.js.map +1 -0
- package/dist/lib/util/zod-error.d.ts +2 -0
- package/dist/lib/util/zod-error.d.ts.map +1 -0
- package/dist/lib/util/zod-error.js +16 -0
- package/dist/lib/util/zod-error.js.map +1 -0
- package/dist/oauth-errors.d.ts +22 -22
- package/dist/oauth-errors.d.ts.map +1 -1
- package/dist/oauth-errors.js +37 -45
- package/dist/oauth-errors.js.map +1 -1
- package/dist/oauth-hooks.d.ts +11 -23
- package/dist/oauth-hooks.d.ts.map +1 -1
- package/dist/oauth-hooks.js.map +1 -1
- package/dist/oauth-middleware.d.ts +12 -0
- package/dist/oauth-middleware.d.ts.map +1 -0
- package/dist/oauth-middleware.js +32 -0
- package/dist/oauth-middleware.js.map +1 -0
- package/dist/oauth-provider.d.ts +109 -113
- package/dist/oauth-provider.d.ts.map +1 -1
- package/dist/oauth-provider.js +124 -542
- package/dist/oauth-provider.js.map +1 -1
- package/dist/oauth-verifier.d.ts +7 -26
- package/dist/oauth-verifier.d.ts.map +1 -1
- package/dist/oauth-verifier.js +6 -16
- package/dist/oauth-verifier.js.map +1 -1
- package/dist/request/code.d.ts.map +1 -1
- package/dist/request/request-data.d.ts +2 -4
- package/dist/request/request-data.d.ts.map +1 -1
- package/dist/request/request-data.js.map +1 -1
- package/dist/request/request-manager.d.ts +4 -2
- package/dist/request/request-manager.d.ts.map +1 -1
- package/dist/request/request-manager.js +9 -8
- package/dist/request/request-manager.js.map +1 -1
- package/dist/request/request-store.d.ts +6 -0
- package/dist/request/request-store.d.ts.map +1 -1
- package/dist/request/request-store.js +3 -1
- package/dist/request/request-store.js.map +1 -1
- package/dist/result/authorization-redirect-parameters.d.ts +18 -0
- package/dist/result/authorization-redirect-parameters.d.ts.map +1 -0
- package/dist/result/authorization-redirect-parameters.js +3 -0
- package/dist/result/authorization-redirect-parameters.js.map +1 -0
- package/dist/result/authorization-result-authorize-page.d.ts +13 -0
- package/dist/result/authorization-result-authorize-page.d.ts.map +1 -0
- package/dist/result/authorization-result-authorize-page.js +3 -0
- package/dist/result/authorization-result-authorize-page.js.map +1 -0
- package/dist/result/authorization-result-redirect.d.ts +8 -0
- package/dist/result/authorization-result-redirect.d.ts.map +1 -0
- package/dist/result/authorization-result-redirect.js +3 -0
- package/dist/result/authorization-result-redirect.js.map +1 -0
- package/dist/router/assets/assets-manifest.d.ts +10 -0
- package/dist/router/assets/assets-manifest.d.ts.map +1 -0
- package/dist/router/assets/assets-manifest.js +77 -0
- package/dist/router/assets/assets-manifest.js.map +1 -0
- package/dist/router/assets/assets.d.ts +16 -0
- package/dist/router/assets/assets.d.ts.map +1 -0
- package/dist/router/assets/assets.js +43 -0
- package/dist/router/assets/assets.js.map +1 -0
- package/dist/router/assets/csrf.d.ts +4 -0
- package/dist/router/assets/csrf.d.ts.map +1 -0
- package/dist/router/assets/csrf.js +51 -0
- package/dist/router/assets/csrf.js.map +1 -0
- package/dist/router/assets/send-account-page.d.ts +7 -0
- package/dist/router/assets/send-account-page.d.ts.map +1 -0
- package/dist/router/assets/send-account-page.js +34 -0
- package/dist/router/assets/send-account-page.js.map +1 -0
- package/dist/router/assets/send-authorization-page.d.ts +5 -0
- package/dist/router/assets/send-authorization-page.d.ts.map +1 -0
- package/dist/router/assets/send-authorization-page.js +49 -0
- package/dist/router/assets/send-authorization-page.js.map +1 -0
- package/dist/router/assets/send-error-page.d.ts +4 -0
- package/dist/router/assets/send-error-page.d.ts.map +1 -0
- package/dist/router/assets/send-error-page.js +34 -0
- package/dist/router/assets/send-error-page.js.map +1 -0
- package/dist/router/create-account-page-middleware.d.ts +6 -0
- package/dist/router/create-account-page-middleware.d.ts.map +1 -0
- package/dist/router/create-account-page-middleware.js +39 -0
- package/dist/router/create-account-page-middleware.js.map +1 -0
- package/dist/router/create-api-middleware.d.ts +8 -0
- package/dist/router/create-api-middleware.d.ts.map +1 -0
- package/dist/router/create-api-middleware.js +501 -0
- package/dist/router/create-api-middleware.js.map +1 -0
- package/dist/router/create-authorization-page-middleware.d.ts +6 -0
- package/dist/router/create-authorization-page-middleware.d.ts.map +1 -0
- package/dist/router/create-authorization-page-middleware.js +104 -0
- package/dist/router/create-authorization-page-middleware.js.map +1 -0
- package/dist/router/create-oauth-middleware.d.ts +6 -0
- package/dist/router/create-oauth-middleware.d.ts.map +1 -0
- package/dist/router/create-oauth-middleware.js +142 -0
- package/dist/router/create-oauth-middleware.js.map +1 -0
- package/dist/router/error-handler.d.ts +3 -0
- package/dist/router/error-handler.d.ts.map +1 -0
- package/dist/{account/account.js → router/error-handler.js} +1 -1
- package/dist/router/error-handler.js.map +1 -0
- package/dist/router/middleware-options.d.ts +6 -0
- package/dist/router/middleware-options.d.ts.map +1 -0
- package/dist/router/middleware-options.js +3 -0
- package/dist/router/middleware-options.js.map +1 -0
- package/dist/router/send-redirect.d.ts +16 -0
- package/dist/router/send-redirect.d.ts.map +1 -0
- package/dist/{output/send-authorize-redirect.js → router/send-redirect.js} +40 -24
- package/dist/router/send-redirect.js.map +1 -0
- package/dist/{token/token-claims.d.ts → signer/api-token-payload.d.ts} +237 -232
- package/dist/signer/api-token-payload.d.ts.map +1 -0
- package/dist/signer/api-token-payload.js +17 -0
- package/dist/signer/api-token-payload.js.map +1 -0
- package/dist/signer/signed-token-payload.d.ts +164 -159
- package/dist/signer/signed-token-payload.d.ts.map +1 -1
- package/dist/signer/signed-token-payload.js +10 -16
- package/dist/signer/signed-token-payload.js.map +1 -1
- package/dist/signer/signer.d.ts +42 -11246
- package/dist/signer/signer.d.ts.map +1 -1
- package/dist/signer/signer.js +30 -15
- package/dist/signer/signer.js.map +1 -1
- package/dist/token/refresh-token.d.ts.map +1 -1
- package/dist/token/token-data.d.ts +1 -1
- package/dist/token/token-data.d.ts.map +1 -1
- package/dist/token/token-id.d.ts.map +1 -1
- package/dist/token/token-manager.d.ts +28 -26
- package/dist/token/token-manager.d.ts.map +1 -1
- package/dist/token/token-manager.js +138 -196
- package/dist/token/token-manager.js.map +1 -1
- package/dist/token/token-store.d.ts +4 -4
- package/dist/token/token-store.d.ts.map +1 -1
- package/dist/token/token-store.js +1 -0
- package/dist/token/token-store.js.map +1 -1
- package/dist/token/verify-token-claims.d.ts +3 -3
- package/dist/token/verify-token-claims.d.ts.map +1 -1
- package/dist/token/verify-token-claims.js +1 -1
- package/dist/token/verify-token-claims.js.map +1 -1
- package/dist/types/email-otp.d.ts +3 -0
- package/dist/types/email-otp.d.ts.map +1 -0
- package/dist/types/email-otp.js +6 -0
- package/dist/types/email-otp.js.map +1 -0
- package/dist/types/email.d.ts +3 -0
- package/dist/types/email.d.ts.map +1 -0
- package/dist/types/email.js +29 -0
- package/dist/types/email.js.map +1 -0
- package/dist/types/handle.d.ts +3 -0
- package/dist/types/handle.d.ts.map +1 -0
- package/dist/types/handle.js +22 -0
- package/dist/types/handle.js.map +1 -0
- package/dist/types/invite-code.d.ts +4 -0
- package/dist/types/invite-code.d.ts.map +1 -0
- package/dist/types/invite-code.js +6 -0
- package/dist/types/invite-code.js.map +1 -0
- package/dist/types/password.d.ts +4 -0
- package/dist/types/password.d.ts.map +1 -0
- package/dist/types/password.js +7 -0
- package/dist/types/password.js.map +1 -0
- package/package.json +11 -8
- package/src/access-token/access-token-mode.ts +4 -0
- package/src/account/account-manager.ts +105 -75
- package/src/account/account-store.ts +118 -114
- package/src/account/sign-in-data.ts +10 -10
- package/src/account/sign-up-input.ts +13 -4
- package/src/client/client-manager.ts +34 -2
- package/src/client/client-store.ts +1 -1
- package/src/constants.ts +6 -1
- package/src/customization/branding.ts +12 -0
- package/src/customization/build-customization-css.ts +30 -0
- package/src/customization/build-customization-data.ts +22 -0
- package/src/customization/colors.ts +30 -0
- package/src/customization/customization.ts +25 -0
- package/src/customization/links.ts +10 -0
- package/src/device/device-id.ts +5 -0
- package/src/device/device-manager.ts +76 -66
- package/src/device/device-store.ts +2 -0
- package/src/errors/access-denied-error.ts +24 -17
- package/src/{output/build-error-payload.ts → errors/error-parser.ts} +1 -1
- package/src/errors/invalid-grant-error.ts +5 -0
- package/src/errors/login-required-error.ts +10 -0
- package/src/index.ts +1 -0
- package/src/lib/html/build-document.ts +6 -4
- package/src/{output/backend-data.ts → lib/html/hydration-data.ts} +7 -5
- package/src/lib/html/tags.ts +2 -2
- package/src/lib/http/accept.ts +3 -3
- package/src/lib/http/context.ts +41 -10
- package/src/lib/http/headers.ts +15 -0
- package/src/lib/http/index.ts +1 -0
- package/src/lib/http/middleware.ts +8 -23
- package/src/lib/http/request.ts +40 -75
- package/src/lib/http/response.ts +39 -15
- package/src/lib/http/route.ts +8 -5
- package/src/lib/http/router.ts +40 -46
- package/src/lib/http/security-headers.ts +1 -1
- package/src/lib/http/types.ts +1 -6
- package/src/{output → lib}/send-web-page.ts +10 -9
- package/src/lib/util/color.ts +132 -0
- package/src/lib/util/crypto.ts +9 -4
- package/src/lib/util/function.ts +14 -0
- package/src/lib/util/locale.ts +18 -0
- package/src/lib/util/time.ts +3 -4
- package/src/lib/util/type.ts +24 -0
- package/src/lib/util/ui8.ts +14 -0
- package/src/lib/util/zod-error.ts +14 -0
- package/src/oauth-errors.ts +22 -22
- package/src/oauth-hooks.ts +11 -24
- package/src/oauth-middleware.ts +53 -0
- package/src/oauth-provider.ts +290 -1061
- package/src/oauth-verifier.ts +9 -55
- package/src/request/request-data.ts +5 -4
- package/src/request/request-manager.ts +11 -11
- package/src/request/request-store.ts +7 -0
- package/src/result/authorization-redirect-parameters.ts +24 -0
- package/src/result/authorization-result-authorize-page.ts +14 -0
- package/src/result/authorization-result-redirect.ts +8 -0
- package/src/router/assets/assets-manifest.ts +108 -0
- package/src/router/assets/assets.ts +54 -0
- package/src/router/assets/csrf.ts +63 -0
- package/src/router/assets/send-account-page.ts +43 -0
- package/src/router/assets/send-authorization-page.ts +62 -0
- package/src/router/assets/send-error-page.ts +42 -0
- package/src/router/create-account-page-middleware.ts +69 -0
- package/src/router/create-api-middleware.ts +814 -0
- package/src/router/create-authorization-page-middleware.ts +173 -0
- package/src/router/create-oauth-middleware.ts +247 -0
- package/src/router/error-handler.ts +6 -0
- package/src/router/middleware-options.ts +9 -0
- package/src/router/send-redirect.ts +142 -0
- package/src/signer/api-token-payload.ts +18 -0
- package/src/signer/signed-token-payload.ts +18 -28
- package/src/signer/signer.ts +49 -34
- package/src/token/token-data.ts +1 -1
- package/src/token/token-manager.ts +190 -239
- package/src/token/token-store.ts +6 -4
- package/src/token/verify-token-claims.ts +4 -4
- package/src/types/email-otp.ts +3 -0
- package/src/types/email.ts +26 -0
- package/src/types/handle.ts +18 -0
- package/src/types/invite-code.ts +4 -0
- package/src/types/password.ts +4 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.json +1 -1
- package/dist/access-token/access-token-type.d.ts +0 -6
- package/dist/access-token/access-token-type.d.ts.map +0 -1
- package/dist/access-token/access-token-type.js +0 -10
- package/dist/access-token/access-token-type.js.map +0 -1
- package/dist/account/account.d.ts +0 -2
- package/dist/account/account.d.ts.map +0 -1
- package/dist/account/account.js.map +0 -1
- package/dist/assets/assets-middleware.d.ts +0 -5
- package/dist/assets/assets-middleware.d.ts.map +0 -1
- package/dist/assets/assets-middleware.js +0 -41
- package/dist/assets/assets-middleware.js.map +0 -1
- package/dist/lib/locale.d.ts +0 -15
- package/dist/lib/locale.d.ts.map +0 -1
- package/dist/lib/locale.js +0 -17
- package/dist/lib/locale.js.map +0 -1
- package/dist/output/backend-data.d.ts +0 -4
- package/dist/output/backend-data.d.ts.map +0 -1
- package/dist/output/backend-data.js.map +0 -1
- package/dist/output/build-authorize-data.d.ts +0 -29
- package/dist/output/build-authorize-data.d.ts.map +0 -1
- package/dist/output/build-authorize-data.js +0 -21
- package/dist/output/build-authorize-data.js.map +0 -1
- package/dist/output/build-customization-data.d.ts +0 -234
- package/dist/output/build-customization-data.d.ts.map +0 -1
- package/dist/output/build-customization-data.js +0 -174
- package/dist/output/build-customization-data.js.map +0 -1
- package/dist/output/build-error-data.d.ts +0 -3
- package/dist/output/build-error-data.d.ts.map +0 -1
- package/dist/output/build-error-data.js +0 -10
- package/dist/output/build-error-data.js.map +0 -1
- package/dist/output/build-error-payload.d.ts.map +0 -1
- package/dist/output/build-error-payload.js.map +0 -1
- package/dist/output/output-manager.d.ts +0 -28
- package/dist/output/output-manager.d.ts.map +0 -1
- package/dist/output/output-manager.js +0 -134
- package/dist/output/output-manager.js.map +0 -1
- package/dist/output/send-authorize-redirect.d.ts +0 -25
- package/dist/output/send-authorize-redirect.d.ts.map +0 -1
- package/dist/output/send-authorize-redirect.js.map +0 -1
- package/dist/output/send-web-page.d.ts +0 -8
- package/dist/output/send-web-page.d.ts.map +0 -1
- package/dist/output/send-web-page.js.map +0 -1
- package/dist/token/token-claims.d.ts.map +0 -1
- package/dist/token/token-claims.js +0 -27
- package/dist/token/token-claims.js.map +0 -1
- package/src/access-token/access-token-type.ts +0 -5
- package/src/account/account.ts +0 -1
- package/src/assets/assets-middleware.ts +0 -44
- package/src/lib/locale.ts +0 -21
- package/src/output/build-authorize-data.ts +0 -53
- package/src/output/build-customization-data.ts +0 -217
- package/src/output/build-error-data.ts +0 -8
- package/src/output/output-manager.ts +0 -188
- package/src/output/send-authorize-redirect.ts +0 -137
- package/src/token/token-claims.ts +0 -30
- package/tsconfig.backend.tsbuildinfo +0 -1
- /package/{tsconfig.backend.json → tsconfig.build.json} +0 -0
@@ -1,5 +1,6 @@
|
|
1
1
|
import { createHash } from 'node:crypto'
|
2
|
-
import { isSignedJwt } from '@atproto/jwk'
|
2
|
+
import { SignedJwt, isSignedJwt } from '@atproto/jwk'
|
3
|
+
import type { Account } from '@atproto/oauth-provider-api'
|
3
4
|
import {
|
4
5
|
CLIENT_ASSERTION_TYPE_JWT_BEARER,
|
5
6
|
OAuthAccessToken,
|
@@ -11,9 +12,7 @@ import {
|
|
11
12
|
OAuthTokenResponse,
|
12
13
|
OAuthTokenType,
|
13
14
|
} from '@atproto/oauth-types'
|
14
|
-
import {
|
15
|
-
import { DeviceAccountInfo } from '../account/account-store.js'
|
16
|
-
import { Account } from '../account/account.js'
|
15
|
+
import { AccessTokenMode } from '../access-token/access-token-mode.js'
|
17
16
|
import { ClientAuth } from '../client/client-auth.js'
|
18
17
|
import { Client } from '../client/client.js'
|
19
18
|
import {
|
@@ -33,21 +32,18 @@ import { RequestMetadata } from '../lib/http/request.js'
|
|
33
32
|
import { dateToEpoch, dateToRelativeSeconds } from '../lib/util/date.js'
|
34
33
|
import { callAsync } from '../lib/util/function.js'
|
35
34
|
import { OAuthHooks } from '../oauth-hooks.js'
|
35
|
+
import { Sub } from '../oidc/sub.js'
|
36
36
|
import { Code, isCode } from '../request/code.js'
|
37
|
+
import { SignedTokenPayload } from '../signer/signed-token-payload.js'
|
37
38
|
import { Signer } from '../signer/signer.js'
|
38
39
|
import {
|
40
|
+
RefreshToken,
|
39
41
|
generateRefreshToken,
|
40
42
|
isRefreshToken,
|
41
43
|
refreshTokenSchema,
|
42
44
|
} from './refresh-token.js'
|
43
|
-
import { TokenClaims } from './token-claims.js'
|
44
45
|
import { TokenData } from './token-data.js'
|
45
|
-
import {
|
46
|
-
TokenId,
|
47
|
-
generateTokenId,
|
48
|
-
isTokenId,
|
49
|
-
tokenIdSchema,
|
50
|
-
} from './token-id.js'
|
46
|
+
import { TokenId, generateTokenId, isTokenId } from './token-id.js'
|
51
47
|
import { TokenInfo, TokenStore } from './token-store.js'
|
52
48
|
import {
|
53
49
|
VerifyTokenClaimsOptions,
|
@@ -55,16 +51,15 @@ import {
|
|
55
51
|
verifyTokenClaims,
|
56
52
|
} from './verify-token-claims.js'
|
57
53
|
|
58
|
-
export
|
59
|
-
|
60
|
-
}
|
54
|
+
export { AccessTokenMode, Signer }
|
55
|
+
export type { OAuthHooks, TokenStore, VerifyTokenClaimsResult }
|
61
56
|
|
62
57
|
export class TokenManager {
|
63
58
|
constructor(
|
64
59
|
protected readonly store: TokenStore,
|
65
60
|
protected readonly signer: Signer,
|
66
61
|
protected readonly hooks: OAuthHooks,
|
67
|
-
protected readonly
|
62
|
+
protected readonly accessTokenMode: AccessTokenMode,
|
68
63
|
protected readonly tokenMaxAge = TOKEN_MAX_AGE,
|
69
64
|
) {}
|
70
65
|
|
@@ -72,12 +67,30 @@ export class TokenManager {
|
|
72
67
|
return new Date(now.getTime() + this.tokenMaxAge)
|
73
68
|
}
|
74
69
|
|
75
|
-
protected
|
76
|
-
|
77
|
-
|
78
|
-
|
70
|
+
protected async buildAccessToken(
|
71
|
+
tokenId: TokenId,
|
72
|
+
account: Account,
|
73
|
+
client: Client,
|
74
|
+
parameters: OAuthAuthorizationRequestParameters,
|
75
|
+
options: {
|
76
|
+
now: Date
|
77
|
+
expiresAt: Date
|
78
|
+
},
|
79
|
+
): Promise<OAuthAccessToken> {
|
80
|
+
return this.signer.createAccessToken({
|
81
|
+
jti: tokenId,
|
82
|
+
sub: account.sub,
|
83
|
+
exp: dateToEpoch(options.expiresAt),
|
84
|
+
iat: dateToEpoch(options.now),
|
85
|
+
cnf: parameters.dpop_jkt ? { jkt: parameters.dpop_jkt } : undefined,
|
79
86
|
|
80
|
-
|
87
|
+
...(this.accessTokenMode === AccessTokenMode.stateless && {
|
88
|
+
aud: account.aud,
|
89
|
+
scope: parameters.scope,
|
90
|
+
// https://datatracker.ietf.org/doc/html/rfc8693#section-4.3
|
91
|
+
client_id: client.id,
|
92
|
+
}),
|
93
|
+
})
|
81
94
|
}
|
82
95
|
|
83
96
|
async create(
|
@@ -85,7 +98,7 @@ export class TokenManager {
|
|
85
98
|
clientAuth: ClientAuth,
|
86
99
|
clientMetadata: RequestMetadata,
|
87
100
|
account: Account,
|
88
|
-
|
101
|
+
deviceId: null | DeviceId,
|
89
102
|
parameters: OAuthAuthorizationRequestParameters,
|
90
103
|
input:
|
91
104
|
| OAuthAuthorizationCodeGrantTokenRequest
|
@@ -132,9 +145,11 @@ export class TokenManager {
|
|
132
145
|
throw new InvalidGrantError('Invalid code')
|
133
146
|
}
|
134
147
|
|
148
|
+
// @NOTE not using `this.findByCode` because we want to delete the token
|
149
|
+
// if it still exists (rather than throwing if the code is invalid).
|
135
150
|
const tokenInfo = await this.store.findTokenByCode(input.code)
|
136
151
|
if (tokenInfo) {
|
137
|
-
await this.
|
152
|
+
await this.deleteToken(tokenInfo.id)
|
138
153
|
throw new InvalidGrantError(`Code replayed`)
|
139
154
|
}
|
140
155
|
|
@@ -184,11 +199,6 @@ export class TokenManager {
|
|
184
199
|
)
|
185
200
|
}
|
186
201
|
|
187
|
-
if (!device) {
|
188
|
-
// Fool-proofing (authorization_code grant should always have a device)
|
189
|
-
throw new InvalidRequestError('consent was not given for this device')
|
190
|
-
}
|
191
|
-
|
192
202
|
break
|
193
203
|
}
|
194
204
|
|
@@ -209,47 +219,29 @@ export class TokenManager {
|
|
209
219
|
const now = new Date()
|
210
220
|
const expiresAt = this.createTokenExpiry(now)
|
211
221
|
|
212
|
-
const authorizationDetails = await callAsync(
|
213
|
-
this.hooks.getAuthorizationDetails,
|
214
|
-
{
|
215
|
-
client,
|
216
|
-
clientAuth,
|
217
|
-
clientMetadata,
|
218
|
-
parameters,
|
219
|
-
account,
|
220
|
-
},
|
221
|
-
)
|
222
|
-
|
223
222
|
const tokenData: TokenData = {
|
224
223
|
createdAt: now,
|
225
224
|
updatedAt: now,
|
226
225
|
expiresAt,
|
227
226
|
clientId: client.id,
|
228
227
|
clientAuth,
|
229
|
-
deviceId
|
228
|
+
deviceId,
|
230
229
|
sub: account.sub,
|
231
230
|
parameters,
|
232
|
-
details:
|
231
|
+
details: null,
|
233
232
|
code,
|
234
233
|
}
|
235
234
|
|
236
235
|
await this.store.createToken(tokenId, tokenData, refreshToken)
|
237
236
|
|
238
237
|
try {
|
239
|
-
const accessToken
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
alg: undefined,
|
247
|
-
exp: expiresAt,
|
248
|
-
iat: now,
|
249
|
-
jti: tokenId,
|
250
|
-
cnf: parameters.dpop_jkt ? { jkt: parameters.dpop_jkt } : undefined,
|
251
|
-
authorization_details: authorizationDetails,
|
252
|
-
})
|
238
|
+
const accessToken = await this.buildAccessToken(
|
239
|
+
tokenId,
|
240
|
+
account,
|
241
|
+
client,
|
242
|
+
parameters,
|
243
|
+
{ now, expiresAt },
|
244
|
+
)
|
253
245
|
|
254
246
|
const response = await this.buildTokenResponse(
|
255
247
|
client,
|
@@ -257,8 +249,7 @@ export class TokenManager {
|
|
257
249
|
refreshToken,
|
258
250
|
expiresAt,
|
259
251
|
parameters,
|
260
|
-
account,
|
261
|
-
authorizationDetails,
|
252
|
+
account.sub,
|
262
253
|
)
|
263
254
|
|
264
255
|
await callAsync(this.hooks.onTokenCreated, {
|
@@ -267,33 +258,33 @@ export class TokenManager {
|
|
267
258
|
clientMetadata,
|
268
259
|
account,
|
269
260
|
parameters,
|
270
|
-
deviceId: device ? device.id : null,
|
271
261
|
})
|
272
262
|
|
273
263
|
return response
|
274
264
|
} catch (err) {
|
275
265
|
// Just in case the token could not be issued, we delete it from the store
|
276
|
-
await this.
|
266
|
+
await this.deleteToken(tokenId)
|
277
267
|
|
278
268
|
throw err
|
279
269
|
}
|
280
270
|
}
|
281
271
|
|
282
|
-
protected
|
272
|
+
protected buildTokenResponse(
|
283
273
|
client: Client,
|
284
274
|
accessToken: OAuthAccessToken,
|
285
275
|
refreshToken: string | undefined,
|
286
276
|
expiresAt: Date,
|
287
277
|
parameters: OAuthAuthorizationRequestParameters,
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
const tokenResponse: OAuthTokenResponse = {
|
278
|
+
sub: Sub,
|
279
|
+
): OAuthTokenResponse {
|
280
|
+
return {
|
292
281
|
access_token: accessToken,
|
293
282
|
token_type: parameters.dpop_jkt ? 'DPoP' : 'Bearer',
|
294
283
|
refresh_token: refreshToken,
|
295
284
|
scope: parameters.scope,
|
296
|
-
|
285
|
+
|
286
|
+
// @NOTE using a getter so that the value gets computed when the JSON
|
287
|
+
// response is generated, allowing to value to be as accurate as possible.
|
297
288
|
get expires_in() {
|
298
289
|
return dateToRelativeSeconds(expiresAt)
|
299
290
|
},
|
@@ -301,13 +292,11 @@ export class TokenManager {
|
|
301
292
|
// ATPROTO extension: add the sub claim to the token response to allow
|
302
293
|
// clients to resolve the PDS url (audience) using the did resolution
|
303
294
|
// mechanism.
|
304
|
-
sub
|
295
|
+
sub,
|
305
296
|
}
|
306
|
-
|
307
|
-
return tokenResponse
|
308
297
|
}
|
309
298
|
|
310
|
-
|
299
|
+
public async validateAccess(
|
311
300
|
client: Client,
|
312
301
|
clientAuth: ClientAuth,
|
313
302
|
tokenInfo: TokenInfo,
|
@@ -316,10 +305,6 @@ export class TokenManager {
|
|
316
305
|
throw new InvalidGrantError(`Token was not issued to this client`)
|
317
306
|
}
|
318
307
|
|
319
|
-
if (tokenInfo.info?.authorizedClients.includes(client.id) === false) {
|
320
|
-
throw new InvalidGrantError(`Client no longer trusted by user`)
|
321
|
-
}
|
322
|
-
|
323
308
|
if (tokenInfo.data.clientAuth.method !== clientAuth.method) {
|
324
309
|
throw new InvalidGrantError(`Client authentication method mismatch`)
|
325
310
|
}
|
@@ -329,6 +314,34 @@ export class TokenManager {
|
|
329
314
|
}
|
330
315
|
}
|
331
316
|
|
317
|
+
public async validateRefresh(
|
318
|
+
client: Client,
|
319
|
+
clientAuth: ClientAuth,
|
320
|
+
{ data }: TokenInfo,
|
321
|
+
): Promise<void> {
|
322
|
+
// @TODO This value should be computable even if we don't have the "client"
|
323
|
+
// (because fetching client info could be flaky). Instead, all the info
|
324
|
+
// needed should be stored in the token info.
|
325
|
+
const allowLongerLifespan =
|
326
|
+
client.info.isFirstParty || data.clientAuth.method !== 'none'
|
327
|
+
|
328
|
+
const lifetime = allowLongerLifespan
|
329
|
+
? AUTHENTICATED_REFRESH_LIFETIME
|
330
|
+
: UNAUTHENTICATED_REFRESH_LIFETIME
|
331
|
+
|
332
|
+
if (data.createdAt.getTime() + lifetime < Date.now()) {
|
333
|
+
throw new InvalidGrantError(`Refresh token expired`)
|
334
|
+
}
|
335
|
+
|
336
|
+
const inactivityTimeout = allowLongerLifespan
|
337
|
+
? AUTHENTICATED_REFRESH_INACTIVITY_TIMEOUT
|
338
|
+
: UNAUTHENTICATED_REFRESH_INACTIVITY_TIMEOUT
|
339
|
+
|
340
|
+
if (data.updatedAt.getTime() + inactivityTimeout < Date.now()) {
|
341
|
+
throw new InvalidGrantError(`Refresh token exceeded inactivity timeout`)
|
342
|
+
}
|
343
|
+
}
|
344
|
+
|
332
345
|
async refresh(
|
333
346
|
client: Client,
|
334
347
|
clientAuth: ClientAuth,
|
@@ -342,25 +355,23 @@ export class TokenManager {
|
|
342
355
|
}
|
343
356
|
const refreshToken = refreshTokenParsed.data
|
344
357
|
|
345
|
-
const tokenInfo = await this.
|
346
|
-
|
347
|
-
|
348
|
-
|
358
|
+
const tokenInfo = await this.findByRefreshToken(refreshToken).catch(
|
359
|
+
(err) => {
|
360
|
+
throw InvalidGrantError.from(
|
361
|
+
err,
|
362
|
+
err instanceof InvalidRequestError
|
363
|
+
? err.error_description
|
364
|
+
: 'Invalid refresh token',
|
365
|
+
)
|
366
|
+
},
|
367
|
+
)
|
349
368
|
|
350
369
|
const { account, data } = tokenInfo
|
351
370
|
const { parameters } = data
|
352
371
|
|
353
372
|
try {
|
354
|
-
if (tokenInfo.currentRefreshToken !== refreshToken) {
|
355
|
-
throw new InvalidGrantError(`refresh token replayed`)
|
356
|
-
}
|
357
|
-
|
358
373
|
await this.validateAccess(client, clientAuth, tokenInfo)
|
359
|
-
|
360
|
-
if (input.grant_type !== 'refresh_token') {
|
361
|
-
// Fool-proofing (should never happen)
|
362
|
-
throw new InvalidGrantError(`Invalid grant type`)
|
363
|
-
}
|
374
|
+
await this.validateRefresh(client, clientAuth, tokenInfo)
|
364
375
|
|
365
376
|
if (!client.metadata.grant_types.includes(input.grant_type)) {
|
366
377
|
// In case the client metadata was updated after the token was issued
|
@@ -377,34 +388,6 @@ export class TokenManager {
|
|
377
388
|
}
|
378
389
|
}
|
379
390
|
|
380
|
-
const lastActivity = data.updatedAt
|
381
|
-
const inactivityTimeout =
|
382
|
-
clientAuth.method === 'none' && !client.info.isFirstParty
|
383
|
-
? UNAUTHENTICATED_REFRESH_INACTIVITY_TIMEOUT
|
384
|
-
: AUTHENTICATED_REFRESH_INACTIVITY_TIMEOUT
|
385
|
-
if (lastActivity.getTime() + inactivityTimeout < Date.now()) {
|
386
|
-
throw new InvalidGrantError(`Refresh token exceeded inactivity timeout`)
|
387
|
-
}
|
388
|
-
|
389
|
-
const lifetime =
|
390
|
-
clientAuth.method === 'none' && !client.info.isFirstParty
|
391
|
-
? UNAUTHENTICATED_REFRESH_LIFETIME
|
392
|
-
: AUTHENTICATED_REFRESH_LIFETIME
|
393
|
-
if (data.createdAt.getTime() + lifetime < Date.now()) {
|
394
|
-
throw new InvalidGrantError(`Refresh token expired`)
|
395
|
-
}
|
396
|
-
|
397
|
-
const authorizationDetails = await callAsync(
|
398
|
-
this.hooks.getAuthorizationDetails,
|
399
|
-
{
|
400
|
-
client,
|
401
|
-
clientAuth,
|
402
|
-
clientMetadata,
|
403
|
-
parameters,
|
404
|
-
account,
|
405
|
-
},
|
406
|
-
)
|
407
|
-
|
408
391
|
const nextTokenId = await generateTokenId()
|
409
392
|
const nextRefreshToken = await generateRefreshToken()
|
410
393
|
|
@@ -434,20 +417,13 @@ export class TokenManager {
|
|
434
417
|
},
|
435
418
|
)
|
436
419
|
|
437
|
-
const accessToken
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
alg: undefined,
|
445
|
-
exp: expiresAt,
|
446
|
-
iat: now,
|
447
|
-
jti: nextTokenId,
|
448
|
-
cnf: parameters.dpop_jkt ? { jkt: parameters.dpop_jkt } : undefined,
|
449
|
-
authorization_details: authorizationDetails,
|
450
|
-
})
|
420
|
+
const accessToken = await this.buildAccessToken(
|
421
|
+
nextTokenId,
|
422
|
+
account,
|
423
|
+
client,
|
424
|
+
parameters,
|
425
|
+
{ now, expiresAt },
|
426
|
+
)
|
451
427
|
|
452
428
|
const response = await this.buildTokenResponse(
|
453
429
|
client,
|
@@ -455,8 +431,7 @@ export class TokenManager {
|
|
455
431
|
nextRefreshToken,
|
456
432
|
expiresAt,
|
457
433
|
parameters,
|
458
|
-
account,
|
459
|
-
authorizationDetails,
|
434
|
+
account.sub,
|
460
435
|
)
|
461
436
|
|
462
437
|
await callAsync(this.hooks.onTokenRefreshed, {
|
@@ -465,170 +440,146 @@ export class TokenManager {
|
|
465
440
|
clientMetadata,
|
466
441
|
account,
|
467
442
|
parameters,
|
468
|
-
deviceId: tokenInfo.data.deviceId,
|
469
443
|
})
|
470
444
|
|
471
445
|
return response
|
472
446
|
} catch (err) {
|
473
447
|
// Just in case the token could not be refreshed, we delete it from the store
|
474
|
-
await this.
|
448
|
+
await this.deleteToken(tokenInfo.id)
|
475
449
|
|
476
450
|
throw err
|
477
451
|
}
|
478
452
|
}
|
479
453
|
|
480
454
|
/**
|
481
|
-
* @
|
455
|
+
* @note The token validity is not guaranteed. The caller must ensure that the
|
456
|
+
* token is valid before using the returned token info.
|
482
457
|
*/
|
483
|
-
async
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
await this.store.deleteToken(tokenId)
|
497
|
-
return
|
498
|
-
}
|
458
|
+
public async findToken(token: string): Promise<TokenInfo> {
|
459
|
+
if (isTokenId(token)) {
|
460
|
+
return this.getTokenInfo(token)
|
461
|
+
} else if (isCode(token)) {
|
462
|
+
return this.findByCode(token)
|
463
|
+
} else if (isRefreshToken(token)) {
|
464
|
+
return this.findByRefreshToken(token)
|
465
|
+
} else if (isSignedJwt(token)) {
|
466
|
+
return this.findBySignedJwt(token)
|
467
|
+
} else {
|
468
|
+
throw new InvalidRequestError(`Invalid token`)
|
469
|
+
}
|
470
|
+
}
|
499
471
|
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
}
|
472
|
+
public async findBySignedJwt(token: SignedJwt): Promise<TokenInfo> {
|
473
|
+
const { payload } = await this.signer.verifyAccessToken(token, {
|
474
|
+
clockTolerance: Infinity,
|
475
|
+
})
|
505
476
|
|
506
|
-
|
507
|
-
const tokenInfo = await this.store.findTokenByCode(token)
|
508
|
-
if (tokenInfo) await this.store.deleteToken(tokenInfo.id)
|
509
|
-
return
|
510
|
-
}
|
477
|
+
const tokenInfo = await this.getTokenInfo(payload.jti)
|
511
478
|
|
512
|
-
|
513
|
-
|
514
|
-
|
479
|
+
// Fool-proof: Invalid store implementation ?
|
480
|
+
if (payload.sub !== tokenInfo.account.sub) {
|
481
|
+
await this.deleteToken(tokenInfo.id)
|
482
|
+
throw new Error(
|
483
|
+
`Account sub (${tokenInfo.account.sub}) does not match token sub (${payload.sub})`,
|
484
|
+
)
|
515
485
|
}
|
486
|
+
|
487
|
+
return tokenInfo
|
516
488
|
}
|
517
489
|
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
* @see {@link https://datatracker.ietf.org/doc/html/rfc7662 RFC7662}
|
522
|
-
*/
|
523
|
-
async clientTokenInfo(
|
524
|
-
client: Client,
|
525
|
-
clientAuth: ClientAuth,
|
526
|
-
token: string,
|
527
|
-
): Promise<TokenInfo> {
|
528
|
-
const tokenInfo = await this.findTokenInfo(token)
|
490
|
+
public async findByRefreshToken(token: RefreshToken): Promise<TokenInfo> {
|
491
|
+
const tokenInfo = await this.store.findTokenByRefreshToken(token)
|
492
|
+
|
529
493
|
if (!tokenInfo) {
|
530
|
-
throw new
|
494
|
+
throw new InvalidRequestError(`Invalid refresh token`)
|
531
495
|
}
|
532
496
|
|
533
|
-
|
534
|
-
await this.
|
535
|
-
} catch (err) {
|
536
|
-
await this.store.deleteToken(tokenInfo.id)
|
537
|
-
throw err
|
538
|
-
}
|
497
|
+
if (tokenInfo.currentRefreshToken !== token) {
|
498
|
+
await this.deleteToken(tokenInfo.id)
|
539
499
|
|
540
|
-
|
541
|
-
throw new InvalidGrantError(`Token expired`)
|
500
|
+
throw new InvalidRequestError(`Refresh token replayed`)
|
542
501
|
}
|
543
502
|
|
544
503
|
return tokenInfo
|
545
504
|
}
|
546
505
|
|
547
|
-
|
548
|
-
|
549
|
-
case isTokenId(token):
|
550
|
-
return this.store.readToken(token)
|
506
|
+
public async findByCode(code: Code): Promise<TokenInfo> {
|
507
|
+
const tokenInfo = await this.store.findTokenByCode(code)
|
551
508
|
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
.catch((_) => ({ payload: null }))
|
556
|
-
if (!payload) return null
|
557
|
-
|
558
|
-
const tokenInfo = await this.store.readToken(payload.jti)
|
559
|
-
if (!tokenInfo) return null
|
560
|
-
|
561
|
-
// Audience changed (e.g. user was moved to another resource server)
|
562
|
-
if (payload.aud !== tokenInfo.account.aud) {
|
563
|
-
return null
|
564
|
-
}
|
565
|
-
|
566
|
-
// Invalid store implementation ?
|
567
|
-
if (payload.sub !== tokenInfo.account.sub) {
|
568
|
-
throw new Error(
|
569
|
-
`Account sub (${tokenInfo.account.sub}) does not match token sub (${payload.sub})`,
|
570
|
-
)
|
571
|
-
}
|
572
|
-
|
573
|
-
return tokenInfo
|
574
|
-
}
|
509
|
+
if (!tokenInfo) {
|
510
|
+
throw new InvalidRequestError(`Invalid code`)
|
511
|
+
}
|
575
512
|
|
576
|
-
|
577
|
-
|
578
|
-
if (!tokenInfo?.currentRefreshToken) return null
|
579
|
-
if (tokenInfo.currentRefreshToken !== token) return null
|
580
|
-
return tokenInfo
|
581
|
-
}
|
513
|
+
return tokenInfo
|
514
|
+
}
|
582
515
|
|
583
|
-
|
584
|
-
|
585
|
-
return null
|
586
|
-
}
|
516
|
+
public async deleteToken(tokenId: TokenId): Promise<void> {
|
517
|
+
return this.store.deleteToken(tokenId)
|
587
518
|
}
|
588
519
|
|
589
|
-
async getTokenInfo(
|
520
|
+
async getTokenInfo(tokenId: TokenId): Promise<TokenInfo> {
|
590
521
|
const tokenInfo = await this.store.readToken(tokenId)
|
591
522
|
|
592
523
|
if (!tokenInfo) {
|
593
|
-
throw new
|
594
|
-
}
|
595
|
-
|
596
|
-
if (!(tokenInfo.data.expiresAt.getTime() > Date.now())) {
|
597
|
-
throw new InvalidTokenError(tokenType, `Token expired`)
|
524
|
+
throw new InvalidRequestError(`Invalid token`)
|
598
525
|
}
|
599
526
|
|
600
527
|
return tokenInfo
|
601
528
|
}
|
602
529
|
|
603
|
-
async
|
530
|
+
async verifyToken(
|
531
|
+
token: OAuthAccessToken,
|
604
532
|
tokenType: OAuthTokenType,
|
605
|
-
|
533
|
+
tokenId: TokenId,
|
606
534
|
dpopJkt: string | null,
|
607
535
|
verifyOptions?: VerifyTokenClaimsOptions,
|
608
|
-
): Promise<
|
609
|
-
const tokenInfo = await this.getTokenInfo(
|
610
|
-
|
536
|
+
): Promise<VerifyTokenClaimsResult> {
|
537
|
+
const tokenInfo = await this.getTokenInfo(tokenId).catch((err) => {
|
538
|
+
throw InvalidTokenError.from(err, tokenType)
|
539
|
+
})
|
540
|
+
|
541
|
+
if (isCurrentTokenExpired(tokenInfo)) {
|
542
|
+
await this.deleteToken(tokenId)
|
543
|
+
throw new InvalidTokenError(tokenType, `Token expired`)
|
544
|
+
}
|
545
|
+
|
546
|
+
const { account, data } = tokenInfo
|
547
|
+
const { parameters } = data
|
611
548
|
|
612
549
|
// Construct a list of claim, as if the token was a JWT.
|
613
|
-
const claims:
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
client_id: tokenInfo.data.clientId,
|
550
|
+
const claims: SignedTokenPayload = {
|
551
|
+
iss: this.signer.issuer,
|
552
|
+
jti: tokenId,
|
553
|
+
sub: account.sub,
|
554
|
+
exp: dateToEpoch(data.expiresAt),
|
555
|
+
iat: dateToEpoch(data.updatedAt),
|
620
556
|
cnf: parameters.dpop_jkt ? { jkt: parameters.dpop_jkt } : undefined,
|
557
|
+
|
558
|
+
// These are not stored in the JWT access token in "light" access token
|
559
|
+
// mode. See `buildAccessToken`.
|
560
|
+
aud: account.aud,
|
561
|
+
scope: parameters.scope,
|
562
|
+
client_id: data.clientId,
|
621
563
|
}
|
622
564
|
|
623
|
-
|
624
|
-
token,
|
565
|
+
return verifyTokenClaims(
|
625
566
|
token,
|
567
|
+
tokenId,
|
626
568
|
tokenType,
|
627
569
|
dpopJkt,
|
628
570
|
claims,
|
629
571
|
verifyOptions,
|
630
572
|
)
|
573
|
+
}
|
631
574
|
|
632
|
-
|
575
|
+
async listAccountTokens(sub: Sub): Promise<TokenInfo[]> {
|
576
|
+
const results = await this.store.listAccountTokens(sub)
|
577
|
+
return results
|
578
|
+
.filter((tokenInfo) => tokenInfo.account.sub === sub) // Fool proof
|
579
|
+
.filter((tokenInfo) => !isCurrentTokenExpired(tokenInfo))
|
633
580
|
}
|
634
581
|
}
|
582
|
+
|
583
|
+
function isCurrentTokenExpired(tokenInfo: TokenInfo): boolean {
|
584
|
+
return tokenInfo.data.expiresAt.getTime() < Date.now()
|
585
|
+
}
|