@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
package/dist/oauth-provider.js
CHANGED
@@ -1,47 +1,33 @@
|
|
1
1
|
"use strict";
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
-
};
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
-
exports.OAuthProvider = exports.Keyset = void 0;
|
7
|
-
const http_errors_1 = __importDefault(require("http-errors"));
|
8
|
-
const zod_1 = require("zod");
|
3
|
+
exports.OAuthProvider = exports.Keyset = exports.AccessTokenMode = void 0;
|
9
4
|
const jwk_1 = require("@atproto/jwk");
|
10
5
|
Object.defineProperty(exports, "Keyset", { enumerable: true, get: function () { return jwk_1.Keyset; } });
|
11
6
|
const oauth_types_1 = require("@atproto/oauth-types");
|
12
7
|
const fetch_node_1 = require("@atproto-labs/fetch-node");
|
13
8
|
const simple_store_memory_1 = require("@atproto-labs/simple-store-memory");
|
14
|
-
const
|
9
|
+
const access_token_mode_js_1 = require("./access-token/access-token-mode.js");
|
10
|
+
Object.defineProperty(exports, "AccessTokenMode", { enumerable: true, get: function () { return access_token_mode_js_1.AccessTokenMode; } });
|
15
11
|
const account_manager_js_1 = require("./account/account-manager.js");
|
16
12
|
const account_store_js_1 = require("./account/account-store.js");
|
17
|
-
const sign_in_data_js_1 = require("./account/sign-in-data.js");
|
18
|
-
const sign_up_input_js_1 = require("./account/sign-up-input.js");
|
19
|
-
const assets_middleware_js_1 = require("./assets/assets-middleware.js");
|
20
13
|
const client_auth_js_1 = require("./client/client-auth.js");
|
21
14
|
const client_manager_js_1 = require("./client/client-manager.js");
|
22
15
|
const client_store_js_1 = require("./client/client-store.js");
|
23
16
|
const constants_js_1 = require("./constants.js");
|
17
|
+
const customization_js_1 = require("./customization/customization.js");
|
24
18
|
const device_manager_js_1 = require("./device/device-manager.js");
|
25
19
|
const device_store_js_1 = require("./device/device-store.js");
|
26
20
|
const access_denied_error_js_1 = require("./errors/access-denied-error.js");
|
27
21
|
const account_selection_required_error_js_1 = require("./errors/account-selection-required-error.js");
|
28
22
|
const consent_required_error_js_1 = require("./errors/consent-required-error.js");
|
29
|
-
const invalid_client_error_js_1 = require("./errors/invalid-client-error.js");
|
30
23
|
const invalid_grant_error_js_1 = require("./errors/invalid-grant-error.js");
|
31
24
|
const invalid_parameters_error_js_1 = require("./errors/invalid-parameters-error.js");
|
32
25
|
const invalid_request_error_js_1 = require("./errors/invalid-request-error.js");
|
33
26
|
const login_required_error_js_1 = require("./errors/login-required-error.js");
|
34
|
-
const unauthorized_client_error_js_1 = require("./errors/unauthorized-client-error.js");
|
35
|
-
const www_authenticate_error_js_1 = require("./errors/www-authenticate-error.js");
|
36
|
-
const index_js_1 = require("./lib/http/index.js");
|
37
|
-
const request_js_1 = require("./lib/http/request.js");
|
38
27
|
const date_js_1 = require("./lib/util/date.js");
|
28
|
+
const zod_error_js_1 = require("./lib/util/zod-error.js");
|
39
29
|
const build_metadata_js_1 = require("./metadata/build-metadata.js");
|
40
30
|
const oauth_verifier_js_1 = require("./oauth-verifier.js");
|
41
|
-
const build_customization_data_js_1 = require("./output/build-customization-data.js");
|
42
|
-
const build_error_payload_js_1 = require("./output/build-error-payload.js");
|
43
|
-
const output_manager_js_1 = require("./output/output-manager.js");
|
44
|
-
const send_authorize_redirect_js_1 = require("./output/send-authorize-redirect.js");
|
45
31
|
const replay_store_js_1 = require("./replay/replay-store.js");
|
46
32
|
const code_js_1 = require("./request/code.js");
|
47
33
|
const request_manager_js_1 = require("./request/request-manager.js");
|
@@ -49,19 +35,21 @@ const request_store_memory_js_1 = require("./request/request-store-memory.js");
|
|
49
35
|
const request_store_redis_js_1 = require("./request/request-store-redis.js");
|
50
36
|
const request_store_js_1 = require("./request/request-store.js");
|
51
37
|
const request_uri_js_1 = require("./request/request-uri.js");
|
52
|
-
const token_id_js_1 = require("./token/token-id.js");
|
53
38
|
const token_manager_js_1 = require("./token/token-manager.js");
|
54
39
|
const token_store_js_1 = require("./token/token-store.js");
|
55
40
|
class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
41
|
+
accessTokenMode;
|
56
42
|
metadata;
|
43
|
+
customization;
|
57
44
|
authenticationMaxAge;
|
58
45
|
accountManager;
|
59
46
|
deviceManager;
|
60
47
|
clientManager;
|
61
48
|
requestManager;
|
62
49
|
tokenManager;
|
63
|
-
|
64
|
-
|
50
|
+
constructor({
|
51
|
+
// OAuthProviderConfig
|
52
|
+
authenticationMaxAge = constants_js_1.AUTHENTICATION_MAX_AGE, tokenMaxAge = constants_js_1.TOKEN_MAX_AGE, accessTokenMode = access_token_mode_js_1.AccessTokenMode.stateless, metadata, safeFetch = (0, fetch_node_1.safeFetchWrap)(), redis, store, // compound store implementation
|
65
53
|
// Requires stores
|
66
54
|
accountStore = (0, account_store_js_1.asAccountStore)(store), deviceStore = (0, device_store_js_1.asDeviceStore)(store), tokenStore = (0, token_store_js_1.asTokenStore)(store),
|
67
55
|
// These are optional
|
@@ -77,7 +65,6 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
77
65
|
// DeviceManagerOptions &
|
78
66
|
// Customization
|
79
67
|
...rest }) {
|
80
|
-
const customization = build_customization_data_js_1.customizationSchema.parse(rest);
|
81
68
|
const deviceManagerOptions = device_manager_js_1.deviceManagerOptionsSchema.parse(rest);
|
82
69
|
// @NOTE: hooks don't really need a type parser, as all zod can actually
|
83
70
|
// check at runtime is the fact that the values are functions. The only way
|
@@ -94,26 +81,40 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
94
81
|
requestStore ??= redis
|
95
82
|
? new request_store_redis_js_1.RequestStoreRedis({ redis })
|
96
83
|
: new request_store_memory_js_1.RequestStoreMemory();
|
84
|
+
this.accessTokenMode = accessTokenMode;
|
97
85
|
this.authenticationMaxAge = authenticationMaxAge;
|
98
86
|
this.metadata = (0, build_metadata_js_1.buildMetadata)(this.issuer, this.keyset, metadata);
|
87
|
+
this.customization = customization_js_1.customizationSchema.parse(rest);
|
99
88
|
this.deviceManager = new device_manager_js_1.DeviceManager(deviceStore, deviceManagerOptions);
|
100
|
-
this.
|
101
|
-
this.accountManager = new account_manager_js_1.AccountManager(this.issuer, accountStore, hooks, customization);
|
89
|
+
this.accountManager = new account_manager_js_1.AccountManager(this.issuer, accountStore, hooks, this.customization);
|
102
90
|
this.clientManager = new client_manager_js_1.ClientManager(this.metadata, this.keyset, hooks, clientStore || null, loopbackMetadata || null, safeFetch, clientJwksCache, clientMetadataCache);
|
103
91
|
this.requestManager = new request_manager_js_1.RequestManager(requestStore, this.signer, this.metadata, hooks);
|
104
|
-
this.tokenManager = new token_manager_js_1.TokenManager(tokenStore, this.signer, hooks, this.
|
92
|
+
this.tokenManager = new token_manager_js_1.TokenManager(tokenStore, this.signer, hooks, this.accessTokenMode, tokenMaxAge);
|
105
93
|
}
|
106
94
|
get jwks() {
|
107
95
|
return this.keyset.publicJwks;
|
108
96
|
}
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
97
|
+
/**
|
98
|
+
* @returns true if the user's consent is required for the requested scopes
|
99
|
+
*/
|
100
|
+
checkConsentRequired(parameters, clientData) {
|
101
|
+
// Client was never authorized before
|
102
|
+
if (!clientData)
|
114
103
|
return true;
|
115
|
-
|
116
|
-
|
104
|
+
// Client explicitly asked for consent
|
105
|
+
if (parameters.prompt === 'consent')
|
106
|
+
return true;
|
107
|
+
// No scope requested, and client is known by user, no consent required
|
108
|
+
const requestedScopes = parameters.scope?.split(' ');
|
109
|
+
if (requestedScopes == null)
|
110
|
+
return false;
|
111
|
+
// Ensure that all requested scopes were previously authorized by the user
|
112
|
+
const { authorizedScopes } = clientData;
|
113
|
+
return !requestedScopes.every((scope) => authorizedScopes.includes(scope));
|
114
|
+
}
|
115
|
+
checkLoginRequired(deviceAccount) {
|
116
|
+
const authAge = Date.now() - deviceAccount.updatedAt.getTime();
|
117
|
+
return authAge > this.authenticationMaxAge;
|
117
118
|
}
|
118
119
|
async authenticateClient(credentials) {
|
119
120
|
const client = await this.clientManager.getClient(credentials.client_id);
|
@@ -198,7 +199,9 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
198
199
|
if ('request_uri' in query) {
|
199
200
|
const requestUri = await request_uri_js_1.requestUriSchema
|
200
201
|
.parseAsync(query.request_uri, { path: ['query', 'request_uri'] })
|
201
|
-
.catch(
|
202
|
+
.catch((err) => {
|
203
|
+
throw new invalid_request_error_js_1.InvalidRequestError((0, zod_error_js_1.extractZodErrorMessage)(err) ?? 'Input validation error', err);
|
204
|
+
});
|
202
205
|
return this.requestManager.get(requestUri, deviceId, client.id);
|
203
206
|
}
|
204
207
|
if ('request' in query) {
|
@@ -218,14 +221,6 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
218
221
|
}
|
219
222
|
return this.requestManager.createAuthorizationRequest(client, { method: 'none' }, query, deviceId, null);
|
220
223
|
}
|
221
|
-
async deleteRequest(requestUri, parameters) {
|
222
|
-
try {
|
223
|
-
await this.requestManager.delete(requestUri);
|
224
|
-
}
|
225
|
-
catch (err) {
|
226
|
-
throw access_denied_error_js_1.AccessDeniedError.from(parameters, err);
|
227
|
-
}
|
228
|
-
}
|
229
224
|
/**
|
230
225
|
* @see {@link https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-11#section-4.1.1}
|
231
226
|
*/
|
@@ -242,9 +237,9 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
242
237
|
const client = await this.clientManager
|
243
238
|
.getClient(clientCredentials.client_id)
|
244
239
|
.catch(accessDeniedCatcher);
|
245
|
-
const {
|
240
|
+
const { parameters, uri } = await this.processAuthorizationRequest(client, deviceId, query).catch(accessDeniedCatcher);
|
246
241
|
try {
|
247
|
-
const sessions = await this.getSessions(client,
|
242
|
+
const sessions = await this.getSessions(client.id, deviceId, parameters);
|
248
243
|
if (parameters.prompt === 'none') {
|
249
244
|
const ssoSessions = sessions.filter((s) => s.matchesHint);
|
250
245
|
if (ssoSessions.length > 1) {
|
@@ -261,7 +256,7 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
261
256
|
throw new consent_required_error_js_1.ConsentRequiredError(parameters);
|
262
257
|
}
|
263
258
|
const code = await this.requestManager.setAuthorized(uri, client, ssoSession.account, deviceId, deviceMetadata);
|
264
|
-
return { issuer,
|
259
|
+
return { issuer, parameters, redirect: { code } };
|
265
260
|
}
|
266
261
|
// Automatic SSO when a did was provided
|
267
262
|
if (parameters.prompt == null && parameters.login_hint != null) {
|
@@ -270,7 +265,7 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
270
265
|
const ssoSession = ssoSessions[0];
|
271
266
|
if (!ssoSession.loginRequired && !ssoSession.consentRequired) {
|
272
267
|
const code = await this.requestManager.setAuthorized(uri, client, ssoSession.account, deviceId, deviceMetadata);
|
273
|
-
return { issuer,
|
268
|
+
return { issuer, parameters, redirect: { code } };
|
274
269
|
}
|
275
270
|
}
|
276
271
|
}
|
@@ -278,112 +273,57 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
278
273
|
issuer,
|
279
274
|
client,
|
280
275
|
parameters,
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
276
|
+
uri,
|
277
|
+
sessions: sessions.map((session) => ({
|
278
|
+
// Map to avoid leaking other data that might be present in the session
|
279
|
+
account: session.account,
|
280
|
+
selected: session.selected,
|
281
|
+
loginRequired: session.loginRequired,
|
282
|
+
consentRequired: session.consentRequired,
|
283
|
+
})),
|
284
|
+
scopeDetails: parameters.scope
|
285
|
+
?.split(/\s+/)
|
286
|
+
.filter(Boolean)
|
287
|
+
.sort((a, b) => a.localeCompare(b))
|
288
|
+
.map((scope) => ({
|
289
|
+
scope,
|
290
|
+
// @TODO Allow to customize the scope descriptions (e.g.
|
291
|
+
// using a hook)
|
292
|
+
description: undefined,
|
293
|
+
})),
|
295
294
|
};
|
296
295
|
}
|
297
296
|
catch (err) {
|
298
|
-
|
297
|
+
try {
|
298
|
+
await this.requestManager.delete(uri);
|
299
|
+
}
|
300
|
+
catch {
|
301
|
+
// There are two error here. Better keep the outer one.
|
302
|
+
//
|
303
|
+
// @TODO Maybe move this entire code to the /authorize endpoint
|
304
|
+
// (allowing to log this error)
|
305
|
+
}
|
299
306
|
// Not using accessDeniedCatcher here because "parameters" will most
|
300
307
|
// likely contain the redirect_uri (using the client default).
|
301
|
-
throw access_denied_error_js_1.AccessDeniedError.from(parameters, err);
|
308
|
+
throw access_denied_error_js_1.AccessDeniedError.from(parameters, err, 'server_error');
|
302
309
|
}
|
303
310
|
}
|
304
|
-
async getSessions(
|
305
|
-
const
|
311
|
+
async getSessions(clientId, deviceId, parameters) {
|
312
|
+
const deviceAccounts = await this.accountManager.listDeviceAccounts(deviceId);
|
306
313
|
const hint = parameters.login_hint;
|
307
314
|
const matchesHint = (account) => (!!account.sub && account.sub === hint) ||
|
308
315
|
(!!account.preferred_username && account.preferred_username === hint);
|
309
|
-
return
|
310
|
-
account,
|
311
|
-
info,
|
316
|
+
return deviceAccounts.map((deviceAccount) => ({
|
317
|
+
account: deviceAccount.account,
|
312
318
|
selected: parameters.prompt !== 'select_account' &&
|
313
|
-
matchesHint(account)
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
loginRequired: parameters.prompt === 'login' ||
|
320
|
-
this.loginRequired(client, parameters, info),
|
321
|
-
consentRequired: parameters.prompt === 'consent' ||
|
322
|
-
// @TODO the "authorizedClients" should also include the scopes that
|
323
|
-
// were already authorized for the client. Otherwise a client could
|
324
|
-
// use silent authentication to get additional scopes without consent.
|
325
|
-
!info.authorizedClients.includes(client.id),
|
326
|
-
matchesHint: hint == null || matchesHint(account),
|
319
|
+
matchesHint(deviceAccount.account),
|
320
|
+
// @TODO Return the session expiration date instead of a boolean to
|
321
|
+
// avoid having to rely on a leeway when "accepting" the request.
|
322
|
+
loginRequired: parameters.prompt === 'login' || this.checkLoginRequired(deviceAccount),
|
323
|
+
consentRequired: this.checkConsentRequired(parameters, deviceAccount.authorizedClients.get(clientId)),
|
324
|
+
matchesHint: hint == null || matchesHint(deviceAccount.account),
|
327
325
|
}));
|
328
326
|
}
|
329
|
-
async signUp({ requestUri, deviceId, deviceMetadata }, data) {
|
330
|
-
const { clientId } = await this.requestManager.get(requestUri, deviceId);
|
331
|
-
const client = await this.clientManager.getClient(clientId);
|
332
|
-
const { account } = await this.accountManager.signUp(data, deviceId, deviceMetadata);
|
333
|
-
return {
|
334
|
-
account,
|
335
|
-
consentRequired: !client.info.isFirstParty,
|
336
|
-
};
|
337
|
-
}
|
338
|
-
async signIn({ requestUri, deviceId, deviceMetadata }, data) {
|
339
|
-
// Ensure the request is still valid (and update the request expiration)
|
340
|
-
// @TODO use the returned scopes to determine if consent is required
|
341
|
-
const { clientId } = await this.requestManager.get(requestUri, deviceId);
|
342
|
-
const client = await this.clientManager.getClient(clientId);
|
343
|
-
const { account, info } = await this.accountManager.signIn(data, deviceId, deviceMetadata);
|
344
|
-
return {
|
345
|
-
account,
|
346
|
-
consentRequired: client.info.isFirstParty
|
347
|
-
? false
|
348
|
-
: // @TODO: the "authorizedClients" should also include the scopes that
|
349
|
-
// were already authorized for the client. Otherwise a client could
|
350
|
-
// use silent authentication to get additional scopes without consent.
|
351
|
-
!info.authorizedClients.includes(client.id),
|
352
|
-
};
|
353
|
-
}
|
354
|
-
async acceptRequest({ requestUri, deviceId, deviceMetadata }, sub) {
|
355
|
-
const { issuer } = this;
|
356
|
-
const { parameters, clientId, clientAuth } = await this.requestManager.get(requestUri, deviceId);
|
357
|
-
const client = await this.clientManager.getClient(clientId);
|
358
|
-
try {
|
359
|
-
// @TODO Currently, a user can "accept" a request for any did that sing-in
|
360
|
-
// on the device, even if "remember" was set to false.
|
361
|
-
const { account, info } = await this.accountManager.get(deviceId, sub);
|
362
|
-
// The user is trying to authorize without a fresh login
|
363
|
-
if (this.loginRequired(client, parameters, info)) {
|
364
|
-
throw new login_required_error_js_1.LoginRequiredError(parameters, 'Account authentication required.');
|
365
|
-
}
|
366
|
-
const code = await this.requestManager.setAuthorized(requestUri, client, account, deviceId, deviceMetadata);
|
367
|
-
await this.accountManager.addAuthorizedClient(deviceId, account, client, clientAuth);
|
368
|
-
return { issuer, parameters, redirect: { code } };
|
369
|
-
}
|
370
|
-
catch (err) {
|
371
|
-
await this.deleteRequest(requestUri, parameters);
|
372
|
-
throw access_denied_error_js_1.AccessDeniedError.from(parameters, err);
|
373
|
-
}
|
374
|
-
}
|
375
|
-
async rejectRequest({ requestUri, deviceId, }) {
|
376
|
-
const { parameters } = await this.requestManager.get(requestUri, deviceId);
|
377
|
-
await this.deleteRequest(requestUri, parameters);
|
378
|
-
return {
|
379
|
-
issuer: this.issuer,
|
380
|
-
parameters: parameters,
|
381
|
-
redirect: {
|
382
|
-
error: 'access_denied',
|
383
|
-
error_description: 'Access denied',
|
384
|
-
},
|
385
|
-
};
|
386
|
-
}
|
387
327
|
async token(clientCredentials, clientMetadata, request, dpopJkt) {
|
388
328
|
const [client, clientAuth] = await this.authenticateClient(clientCredentials);
|
389
329
|
if (!this.metadata.grant_types_supported?.includes(request.grant_type)) {
|
@@ -401,8 +341,8 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
401
341
|
throw new invalid_grant_error_js_1.InvalidGrantError(`Grant type "${request.grant_type}" not supported`);
|
402
342
|
}
|
403
343
|
async codeGrant(client, clientAuth, clientMetadata, input, dpopJkt) {
|
344
|
+
const code = code_js_1.codeSchema.parse(input.code);
|
404
345
|
try {
|
405
|
-
const code = code_js_1.codeSchema.parse(input.code);
|
406
346
|
const { sub, deviceId, parameters } = await this.requestManager.findCode(client, clientAuth, code);
|
407
347
|
// the following check prevents re-use of PKCE challenges, enforcing the
|
408
348
|
// clients to generate a new challenge for each authorization request. The
|
@@ -417,22 +357,30 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
417
357
|
// a good enough incentive to follow the best practices, until we have a
|
418
358
|
// better implementation.
|
419
359
|
//
|
420
|
-
// @TODO
|
360
|
+
// @TODO Use tokenManager to ensure uniqueness of code_challenge
|
421
361
|
if (parameters.code_challenge) {
|
422
362
|
const unique = await this.replayManager.uniqueCodeChallenge(parameters.code_challenge);
|
423
363
|
if (!unique) {
|
424
|
-
throw new invalid_grant_error_js_1.InvalidGrantError('
|
364
|
+
throw new invalid_grant_error_js_1.InvalidGrantError('Code challenge already used');
|
425
365
|
}
|
426
366
|
}
|
427
|
-
const { account
|
428
|
-
return await this.tokenManager.create(client, clientAuth, clientMetadata, account,
|
367
|
+
const { account } = await this.accountManager.getAccount(sub);
|
368
|
+
return await this.tokenManager.create(client, clientAuth, clientMetadata, account, deviceId, parameters, input, dpopJkt);
|
429
369
|
}
|
430
370
|
catch (err) {
|
431
371
|
// If a token is replayed, requestManager.findCode will throw. In that
|
432
372
|
// case, we need to revoke any token that was issued for this code.
|
433
|
-
await this.tokenManager.
|
434
|
-
|
435
|
-
|
373
|
+
const tokenInfo = await this.tokenManager.findByCode(code);
|
374
|
+
if (tokenInfo) {
|
375
|
+
await this.tokenManager.deleteToken(tokenInfo.id);
|
376
|
+
// As an additional security measure, we also sign the device out, so
|
377
|
+
// that the device cannot be used to access the account anymore without
|
378
|
+
// a new authentication.
|
379
|
+
const { deviceId, sub } = tokenInfo.data;
|
380
|
+
if (deviceId) {
|
381
|
+
await this.accountManager.removeDeviceAccount(deviceId, sub);
|
382
|
+
}
|
383
|
+
}
|
436
384
|
throw err;
|
437
385
|
}
|
438
386
|
}
|
@@ -442,405 +390,39 @@ class OAuthProvider extends oauth_verifier_js_1.OAuthVerifier {
|
|
442
390
|
/**
|
443
391
|
* @see {@link https://datatracker.ietf.org/doc/html/rfc7009#section-2.1 rfc7009}
|
444
392
|
*/
|
445
|
-
async revoke({ token }) {
|
446
|
-
//
|
447
|
-
//
|
448
|
-
await this.tokenManager.revoke(token);
|
449
|
-
}
|
450
|
-
/**
|
451
|
-
* @see {@link https://datatracker.ietf.org/doc/html/rfc7662#section-2.1 rfc7662}
|
452
|
-
*/
|
453
|
-
async introspect(credentials, { token }) {
|
393
|
+
async revoke(credentials, { token }) {
|
394
|
+
// > The authorization server first validates the client credentials (in
|
395
|
+
// > case of a confidential client)
|
454
396
|
const [client, clientAuth] = await this.authenticateClient(credentials);
|
455
|
-
|
456
|
-
//
|
457
|
-
// >
|
458
|
-
// >
|
459
|
-
// >
|
460
|
-
|
461
|
-
// >
|
462
|
-
// >
|
463
|
-
|
464
|
-
|
465
|
-
}
|
466
|
-
const start = Date.now();
|
467
|
-
try {
|
468
|
-
const tokenInfo = await this.tokenManager.clientTokenInfo(client, clientAuth, token);
|
469
|
-
return {
|
470
|
-
active: true,
|
471
|
-
scope: tokenInfo.data.parameters.scope,
|
472
|
-
client_id: tokenInfo.data.clientId,
|
473
|
-
username: tokenInfo.account.preferred_username,
|
474
|
-
token_type: tokenInfo.data.parameters.dpop_jkt ? 'DPoP' : 'Bearer',
|
475
|
-
authorization_details: tokenInfo.data.details ?? undefined,
|
476
|
-
aud: tokenInfo.account.aud,
|
477
|
-
exp: (0, date_js_1.dateToEpoch)(tokenInfo.data.expiresAt),
|
478
|
-
iat: (0, date_js_1.dateToEpoch)(tokenInfo.data.updatedAt),
|
479
|
-
iss: this.signer.issuer,
|
480
|
-
jti: tokenInfo.id,
|
481
|
-
sub: tokenInfo.account.sub,
|
482
|
-
};
|
483
|
-
}
|
484
|
-
catch (err) {
|
485
|
-
// Prevent brute force & timing attack (only for inactive tokens)
|
486
|
-
await new Promise((r) => setTimeout(r, 750 - (Date.now() - start)));
|
487
|
-
return {
|
488
|
-
active: false,
|
489
|
-
};
|
490
|
-
}
|
397
|
+
const tokenInfo = await this.tokenManager.findToken(token);
|
398
|
+
// > [...] and then verifies whether the token was issued to the client
|
399
|
+
// > making the revocation request. If this validation fails, the request is
|
400
|
+
// > refused and the client is informed of the error by the authorization
|
401
|
+
// > server as described below.
|
402
|
+
await this.tokenManager.validateAccess(client, clientAuth, tokenInfo);
|
403
|
+
// > In the next step, the authorization server invalidates the token. The
|
404
|
+
// > invalidation takes place immediately, and the token cannot be used
|
405
|
+
// > again after the revocation.
|
406
|
+
await this.tokenManager.deleteToken(tokenInfo.id);
|
491
407
|
}
|
492
|
-
async
|
493
|
-
if (
|
494
|
-
|
495
|
-
return this.tokenManager.authenticateTokenId(tokenType, token, dpopJkt, verifyOptions);
|
408
|
+
async verifyToken(tokenType, token, dpopJkt, verifyOptions) {
|
409
|
+
if (this.accessTokenMode === access_token_mode_js_1.AccessTokenMode.stateless) {
|
410
|
+
return super.verifyToken(tokenType, token, dpopJkt, verifyOptions);
|
496
411
|
}
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
buildRouter(options) {
|
508
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
509
|
-
const server = this;
|
510
|
-
const issuerUrl = new URL(server.issuer);
|
511
|
-
const issuerOrigin = issuerUrl.origin;
|
512
|
-
const router = new index_js_1.Router(issuerUrl);
|
513
|
-
// Utils
|
514
|
-
const csrfCookie = (requestUri) => `csrf-${requestUri}`;
|
515
|
-
const onError = options?.onError ??
|
516
|
-
(process.env['NODE_ENV'] === 'development'
|
517
|
-
? (req, res, err, msg) => {
|
518
|
-
console.error(`OAuthProvider error (${msg}):`, err);
|
519
|
-
}
|
520
|
-
: null);
|
521
|
-
// CORS preflight
|
522
|
-
const corsHeaders = function (req, res, next) {
|
523
|
-
res.setHeader('Access-Control-Max-Age', '86400'); // 1 day
|
524
|
-
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
|
525
|
-
//
|
526
|
-
// > For requests without credentials, the literal value "*" can be
|
527
|
-
// > specified as a wildcard; the value tells browsers to allow
|
528
|
-
// > requesting code from any origin to access the resource.
|
529
|
-
// > Attempting to use the wildcard with credentials results in an
|
530
|
-
// > error.
|
531
|
-
//
|
532
|
-
// A "*" is safer to use than reflecting the request origin.
|
533
|
-
res.setHeader('Access-Control-Allow-Origin', '*');
|
534
|
-
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods
|
535
|
-
// > The value "*" only counts as a special wildcard value for
|
536
|
-
// > requests without credentials (requests without HTTP cookies or
|
537
|
-
// > HTTP authentication information). In requests with credentials,
|
538
|
-
// > it is treated as the literal method name "*" without special
|
539
|
-
// > semantics.
|
540
|
-
res.setHeader('Access-Control-Allow-Methods', '*');
|
541
|
-
res.setHeader('Access-Control-Allow-Headers', 'Content-Type,DPoP');
|
542
|
-
next();
|
543
|
-
};
|
544
|
-
const corsPreflight = (0, index_js_1.combineMiddlewares)([
|
545
|
-
corsHeaders,
|
546
|
-
(req, res) => {
|
547
|
-
res.writeHead(200).end();
|
548
|
-
},
|
549
|
-
]);
|
550
|
-
/**
|
551
|
-
* Wrap an OAuth endpoint in a middleware that will set the appropriate
|
552
|
-
* response headers and format the response as JSON.
|
553
|
-
*/
|
554
|
-
const jsonHandler = (buildJson) => async function (req, res) {
|
555
|
-
// https://www.rfc-editor.org/rfc/rfc6749.html#section-5.1
|
556
|
-
res.setHeader('Cache-Control', 'no-store');
|
557
|
-
res.setHeader('Pragma', 'no-cache');
|
558
|
-
// Ensure we can agree on a content encoding & type before starting to
|
559
|
-
// build the JSON response.
|
560
|
-
if (!(0, request_js_1.negotiateResponseContent)(req, ['application/json'])) {
|
561
|
-
throw (0, http_errors_1.default)(406, 'Unsupported media type');
|
562
|
-
}
|
563
|
-
try {
|
564
|
-
const { payload, status = 200 } = await buildJson.call(this, req, res);
|
565
|
-
(0, index_js_1.writeJson)(res, payload, { status });
|
566
|
-
}
|
567
|
-
catch (err) {
|
568
|
-
onError?.(req, res, err, 'OAuth request error');
|
569
|
-
if (!res.headersSent) {
|
570
|
-
const payload = (0, build_error_payload_js_1.buildErrorPayload)(err);
|
571
|
-
const status = (0, build_error_payload_js_1.buildErrorStatus)(err);
|
572
|
-
(0, index_js_1.writeJson)(res, payload, { status });
|
573
|
-
}
|
574
|
-
else {
|
575
|
-
res.destroy();
|
576
|
-
}
|
577
|
-
}
|
578
|
-
};
|
579
|
-
const oauthHandler = (buildOAuthResponse, status) => (0, index_js_1.combineMiddlewares)([
|
580
|
-
corsHeaders,
|
581
|
-
jsonHandler(async function (req, res) {
|
582
|
-
try {
|
583
|
-
// https://datatracker.ietf.org/doc/html/rfc9449#section-8.2
|
584
|
-
const dpopNonce = server.nextDpopNonce();
|
585
|
-
if (dpopNonce) {
|
586
|
-
const name = 'DPoP-Nonce';
|
587
|
-
res.setHeader(name, dpopNonce);
|
588
|
-
res.appendHeader('Access-Control-Expose-Headers', name);
|
589
|
-
}
|
590
|
-
const payload = await buildOAuthResponse.call(this, req, res);
|
591
|
-
return { payload, status };
|
592
|
-
}
|
593
|
-
catch (err) {
|
594
|
-
if (!res.headersSent && err instanceof www_authenticate_error_js_1.WWWAuthenticateError) {
|
595
|
-
const name = 'WWW-Authenticate';
|
596
|
-
res.setHeader(name, err.wwwAuthenticateHeader);
|
597
|
-
res.appendHeader('Access-Control-Expose-Headers', name);
|
598
|
-
}
|
599
|
-
throw err;
|
600
|
-
}
|
601
|
-
}),
|
602
|
-
]);
|
603
|
-
const apiHandler = (inputSchema, buildJson, status) => jsonHandler(async function (req, res) {
|
604
|
-
(0, index_js_1.validateFetchMode)(req, res, ['same-origin']);
|
605
|
-
(0, index_js_1.validateFetchSite)(req, res, ['same-origin']);
|
606
|
-
(0, index_js_1.validateSameOrigin)(req, res, issuerOrigin);
|
607
|
-
const referer = (0, index_js_1.validateReferer)(req, res, {
|
608
|
-
origin: issuerOrigin,
|
609
|
-
pathname: '/oauth/authorize',
|
610
|
-
});
|
611
|
-
const requestUri = await request_uri_js_1.requestUriSchema.parseAsync(referer.searchParams.get('request_uri'), { path: ['query', 'request_uri'] });
|
612
|
-
(0, index_js_1.validateCsrfToken)(req, res, req.headers['x-csrf-token'], csrfCookie(requestUri));
|
613
|
-
const { deviceId, deviceMetadata } = await server.deviceManager.load(req, res);
|
614
|
-
const inputRaw = await (0, index_js_1.parseHttpRequest)(req, ['json']);
|
615
|
-
const input = await inputSchema.parseAsync(inputRaw, { path: ['body'] });
|
616
|
-
const context = { requestUri, deviceId, deviceMetadata };
|
617
|
-
const payload = await buildJson.call(this, req, res, input, context);
|
618
|
-
return { payload, status };
|
619
|
-
});
|
620
|
-
const navigationHandler = (handler) => async function (req, res) {
|
621
|
-
try {
|
622
|
-
res.setHeader('Cache-Control', 'no-store');
|
623
|
-
res.setHeader('Pragma', 'no-cache');
|
624
|
-
res.setHeader('Referrer-Policy', 'same-origin');
|
625
|
-
(0, index_js_1.validateFetchMode)(req, res, ['navigate']);
|
626
|
-
(0, index_js_1.validateFetchDest)(req, res, ['document']);
|
627
|
-
(0, index_js_1.validateSameOrigin)(req, res, issuerOrigin);
|
628
|
-
await handler.call(this, req, res);
|
629
|
-
}
|
630
|
-
catch (err) {
|
631
|
-
onError?.(req, res, err, `Failed to handle navigation request to "${req.url}"`);
|
632
|
-
if (!res.headersSent) {
|
633
|
-
await server.outputManager.sendErrorPage(res, err, {
|
634
|
-
preferredLocales: (0, request_js_1.extractLocales)(req),
|
635
|
-
});
|
636
|
-
}
|
637
|
-
}
|
638
|
-
};
|
639
|
-
// Simple GET requests fall under the category of "no-cors" request, meaning
|
640
|
-
// that the browser will allow any cross-origin request, with credentials,
|
641
|
-
// to be sent to the oauth server. The OAuth Server will, however:
|
642
|
-
// 1) validate the request origin (see navigationHandler),
|
643
|
-
// 2) validate the CSRF token,
|
644
|
-
// 3) validate the referer,
|
645
|
-
// 4) validate the sec-fetch-site header,
|
646
|
-
// 4) validate the sec-fetch-mode header (see navigationHandler),
|
647
|
-
// 5) validate the sec-fetch-dest header (see navigationHandler).
|
648
|
-
// And will error (refuse to serve the request) if any of these checks fail.
|
649
|
-
const sameOriginNavigationHandler = (handler) => navigationHandler(async function (req, res) {
|
650
|
-
(0, index_js_1.validateFetchSite)(req, res, ['same-origin']);
|
651
|
-
const deviceInfo = await server.deviceManager.load(req, res);
|
652
|
-
return handler.call(this, req, res, deviceInfo);
|
653
|
-
});
|
654
|
-
const authorizeRedirectNavigationHandler = (handler) => sameOriginNavigationHandler(async function (req, res, deviceInfo) {
|
655
|
-
const referer = (0, index_js_1.validateReferer)(req, res, {
|
656
|
-
origin: issuerOrigin,
|
657
|
-
pathname: '/oauth/authorize',
|
658
|
-
});
|
659
|
-
const requestUri = await request_uri_js_1.requestUriSchema.parseAsync(referer.searchParams.get('request_uri'));
|
660
|
-
const csrfToken = this.url.searchParams.get('csrf_token');
|
661
|
-
const csrfCookieName = csrfCookie(requestUri);
|
662
|
-
// Next line will "clear" the CSRF token cookie, preventing replay of
|
663
|
-
// this request (navigating "back" will result in an error).
|
664
|
-
(0, index_js_1.validateCsrfToken)(req, res, csrfToken, csrfCookieName, true);
|
665
|
-
const context = { ...deviceInfo, requestUri };
|
666
|
-
const redirect = await handler.call(this, req, res, context);
|
667
|
-
return (0, send_authorize_redirect_js_1.sendAuthorizeRedirect)(res, redirect);
|
668
|
-
});
|
669
|
-
/**
|
670
|
-
* Provides a better UX when a request is denied by redirecting to the
|
671
|
-
* client with the error details. This will also log any error that caused
|
672
|
-
* the access to be denied (such as system errors).
|
673
|
-
*/
|
674
|
-
const accessDeniedToRedirectCatcher = (req, res, err) => {
|
675
|
-
if (err instanceof access_denied_error_js_1.AccessDeniedError && err.parameters.redirect_uri) {
|
676
|
-
const { cause } = err;
|
677
|
-
if (cause)
|
678
|
-
onError?.(req, res, cause, 'Access denied');
|
679
|
-
return {
|
680
|
-
issuer: server.issuer,
|
681
|
-
parameters: err.parameters,
|
682
|
-
redirect: err.toJSON(),
|
683
|
-
};
|
684
|
-
}
|
685
|
-
throw err;
|
686
|
-
};
|
687
|
-
//- Public OAuth endpoints
|
688
|
-
router.options('/.well-known/oauth-authorization-server', corsPreflight);
|
689
|
-
router.get('/.well-known/oauth-authorization-server', corsHeaders, (0, index_js_1.cacheControlMiddleware)(300), (0, index_js_1.staticJsonMiddleware)(server.metadata));
|
690
|
-
router.options('/oauth/jwks', corsPreflight);
|
691
|
-
router.get('/oauth/jwks', corsHeaders, (0, index_js_1.cacheControlMiddleware)(300), (0, index_js_1.staticJsonMiddleware)(server.jwks));
|
692
|
-
router.options('/oauth/par', corsPreflight);
|
693
|
-
router.post('/oauth/par', oauthHandler(async function (req, _res) {
|
694
|
-
const payload = await (0, index_js_1.parseHttpRequest)(req, ['json', 'urlencoded']);
|
695
|
-
const credentials = await oauth_types_1.oauthClientCredentialsSchema
|
696
|
-
.parseAsync(payload, { path: ['body'] })
|
697
|
-
.catch(throwInvalidRequest);
|
698
|
-
const authorizationRequest = await oauth_types_1.oauthAuthorizationRequestParSchema
|
699
|
-
.parseAsync(payload, { path: ['body'] })
|
700
|
-
.catch(throwInvalidRequest);
|
701
|
-
const dpopJkt = await server.checkDpopProof(req.headers['dpop'], req.method, this.url);
|
702
|
-
return server.pushedAuthorizationRequest(credentials, authorizationRequest, dpopJkt);
|
703
|
-
}, 201));
|
704
|
-
// https://datatracker.ietf.org/doc/html/rfc9126#section-2.3
|
705
|
-
// > If the request did not use the POST method, the authorization server
|
706
|
-
// > responds with an HTTP 405 (Method Not Allowed) status code.
|
707
|
-
router.all('/oauth/par', (req, res) => {
|
708
|
-
res.writeHead(405).end();
|
709
|
-
});
|
710
|
-
router.options('/oauth/token', corsPreflight);
|
711
|
-
router.post('/oauth/token', oauthHandler(async function (req, _res) {
|
712
|
-
const payload = await (0, index_js_1.parseHttpRequest)(req, ['json', 'urlencoded']);
|
713
|
-
const clientMetadata = await server.deviceManager.getRequestMetadata(req);
|
714
|
-
const clientCredentials = await oauth_types_1.oauthClientCredentialsSchema
|
715
|
-
.parseAsync(payload, { path: ['body'] })
|
716
|
-
.catch(throwInvalidClient);
|
717
|
-
const tokenRequest = await oauth_types_1.oauthTokenRequestSchema
|
718
|
-
.parseAsync(payload, { path: ['body'] })
|
719
|
-
.catch(throwInvalidGrant);
|
720
|
-
const dpopJkt = await server.checkDpopProof(req.headers['dpop'], req.method, this.url);
|
721
|
-
return server.token(clientCredentials, clientMetadata, tokenRequest, dpopJkt);
|
722
|
-
}));
|
723
|
-
router.options('/oauth/revoke', corsPreflight);
|
724
|
-
router.post('/oauth/revoke', oauthHandler(async function (req, res) {
|
725
|
-
const payload = await (0, index_js_1.parseHttpRequest)(req, ['json', 'urlencoded']);
|
726
|
-
const tokenIdentification = await oauth_types_1.oauthTokenIdentificationSchema
|
727
|
-
.parseAsync(payload, { path: ['body'] })
|
728
|
-
.catch(throwInvalidRequest);
|
729
|
-
try {
|
730
|
-
await server.revoke(tokenIdentification);
|
731
|
-
}
|
732
|
-
catch (err) {
|
733
|
-
onError?.(req, res, err, 'Failed to revoke token');
|
734
|
-
}
|
735
|
-
return {};
|
736
|
-
}));
|
737
|
-
router.get('/oauth/revoke', navigationHandler(async function (req, res) {
|
738
|
-
const query = Object.fromEntries(this.url.searchParams);
|
739
|
-
const tokenIdentification = await oauth_types_1.oauthTokenIdentificationSchema
|
740
|
-
.parseAsync(query, { path: ['query'] })
|
741
|
-
.catch(throwInvalidRequest);
|
742
|
-
try {
|
743
|
-
await server.revoke(tokenIdentification);
|
744
|
-
}
|
745
|
-
catch (err) {
|
746
|
-
onError?.(req, res, err, 'Failed to revoke token');
|
747
|
-
}
|
748
|
-
// Same as POST + redirect to callback URL
|
749
|
-
// todo: generate JSONP response (if "callback" is provided)
|
750
|
-
throw new Error('You are successfully logged out. Redirect not implemented');
|
751
|
-
}));
|
752
|
-
router.options('/oauth/introspect', corsPreflight);
|
753
|
-
router.post('/oauth/introspect', oauthHandler(async function (req, _res) {
|
754
|
-
const payload = await (0, index_js_1.parseHttpRequest)(req, ['json', 'urlencoded']);
|
755
|
-
const credentials = await oauth_types_1.oauthClientCredentialsSchema
|
756
|
-
.parseAsync(payload, { path: ['body'] })
|
757
|
-
.catch(throwInvalidRequest);
|
758
|
-
const tokenIdentification = await oauth_types_1.oauthTokenIdentificationSchema
|
759
|
-
.parseAsync(payload, { path: ['body'] })
|
760
|
-
.catch(throwInvalidRequest);
|
761
|
-
return server.introspect(credentials, tokenIdentification);
|
762
|
-
}));
|
763
|
-
//- Private authorization endpoints
|
764
|
-
router.use((0, assets_middleware_js_1.authorizeAssetsMiddleware)());
|
765
|
-
router.get('/oauth/authorize', navigationHandler(async function (req, res) {
|
766
|
-
(0, index_js_1.validateFetchSite)(req, res, ['cross-site', 'none']);
|
767
|
-
const query = Object.fromEntries(this.url.searchParams);
|
768
|
-
const clientCredentials = await oauth_types_1.oauthClientCredentialsSchema
|
769
|
-
.parseAsync(query, { path: ['query'] })
|
770
|
-
.catch(throwInvalidRequest);
|
771
|
-
if ('client_secret' in clientCredentials) {
|
772
|
-
throw new invalid_request_error_js_1.InvalidRequestError('Client secret must not be provided');
|
773
|
-
}
|
774
|
-
const authorizationRequest = await oauth_types_1.oauthAuthorizationRequestQuerySchema
|
775
|
-
.parseAsync(query, { path: ['query'] })
|
776
|
-
.catch(throwInvalidRequest);
|
777
|
-
const { deviceId, deviceMetadata } = await server.deviceManager.load(req, res);
|
778
|
-
const result = await server
|
779
|
-
.authorize(clientCredentials, authorizationRequest, deviceId, deviceMetadata)
|
780
|
-
.catch((err) => accessDeniedToRedirectCatcher(req, res, err));
|
781
|
-
if ('redirect' in result) {
|
782
|
-
return (0, send_authorize_redirect_js_1.sendAuthorizeRedirect)(res, result);
|
783
|
-
}
|
784
|
-
else {
|
785
|
-
await (0, index_js_1.setupCsrfToken)(req, res, csrfCookie(result.authorize.uri));
|
786
|
-
return server.outputManager.sendAuthorizePage(res, result, {
|
787
|
-
preferredLocales: (0, request_js_1.extractLocales)(req),
|
788
|
-
});
|
789
|
-
}
|
790
|
-
}));
|
791
|
-
router.post('/oauth/authorize/verify-handle-availability', apiHandler(zod_1.z.object({ handle: account_store_js_1.handleSchema }).strict(), async function (req, res, data) {
|
792
|
-
await server.accountManager.verifyHandleAvailability(data.handle);
|
793
|
-
return { available: true };
|
794
|
-
}));
|
795
|
-
router.post('/oauth/authorize/sign-up', apiHandler(sign_up_input_js_1.signUpInputSchema, async function (req, res, data, ctx) {
|
796
|
-
return server.signUp(ctx, data);
|
797
|
-
}));
|
798
|
-
router.post('/oauth/authorize/sign-in', apiHandler(sign_in_data_js_1.signInDataSchema, async function (req, res, data, ctx) {
|
799
|
-
return server.signIn(ctx, data);
|
800
|
-
}));
|
801
|
-
router.post('/oauth/authorize/reset-password-request', apiHandler(account_store_js_1.resetPasswordRequestDataSchema, async function (req, res, data) {
|
802
|
-
await server.accountManager.resetPasswordRequest(data);
|
803
|
-
return { success: true };
|
804
|
-
}));
|
805
|
-
router.post('/oauth/authorize/reset-password-confirm', apiHandler(account_store_js_1.resetPasswordConfirmDataSchema, async function (req, res, data) {
|
806
|
-
await server.accountManager.resetPasswordConfirm(data);
|
807
|
-
return { success: true };
|
808
|
-
}));
|
809
|
-
router.get('/oauth/authorize/accept', authorizeRedirectNavigationHandler(async function (req, res, ctx) {
|
810
|
-
const sub = this.url.searchParams.get('account_sub');
|
811
|
-
if (!sub)
|
812
|
-
throw new invalid_request_error_js_1.InvalidRequestError('Account sub not provided');
|
813
|
-
return server
|
814
|
-
.acceptRequest(ctx, sub)
|
815
|
-
.catch((err) => accessDeniedToRedirectCatcher(req, res, err));
|
816
|
-
}));
|
817
|
-
router.get('/oauth/authorize/reject', authorizeRedirectNavigationHandler(async function (req, res, ctx) {
|
818
|
-
return server
|
819
|
-
.rejectRequest(ctx)
|
820
|
-
.catch((err) => accessDeniedToRedirectCatcher(req, res, err));
|
821
|
-
}));
|
822
|
-
return router;
|
823
|
-
}
|
824
|
-
}
|
825
|
-
exports.OAuthProvider = OAuthProvider;
|
826
|
-
function throwInvalidGrant(err) {
|
827
|
-
throw new invalid_grant_error_js_1.InvalidGrantError(extractZodErrorMessage(err) || 'Invalid grant', err);
|
828
|
-
}
|
829
|
-
function throwInvalidClient(err) {
|
830
|
-
throw new invalid_client_error_js_1.InvalidClientError(extractZodErrorMessage(err) || 'Client authentication failed', err);
|
831
|
-
}
|
832
|
-
function throwInvalidRequest(err) {
|
833
|
-
throw new invalid_request_error_js_1.InvalidRequestError(extractZodErrorMessage(err) || 'Input validation error', err);
|
834
|
-
}
|
835
|
-
function extractZodErrorMessage(err) {
|
836
|
-
if (err instanceof zod_1.ZodError) {
|
837
|
-
const issue = err.issues[0];
|
838
|
-
if (issue?.path.length) {
|
839
|
-
// "part" will typically be "body" or "query"
|
840
|
-
const [part, ...path] = issue.path;
|
841
|
-
return `Validation of "${path.join('.')}" ${part} parameter failed: ${issue.message}`;
|
412
|
+
if (this.accessTokenMode === access_token_mode_js_1.AccessTokenMode.light) {
|
413
|
+
const { claims } = await super.verifyToken(tokenType, token, dpopJkt,
|
414
|
+
// Do not verify the scope and audience in case of "light" tokens.
|
415
|
+
// these will be checked through the tokenManager hereafter.
|
416
|
+
undefined);
|
417
|
+
const tokenId = claims.jti;
|
418
|
+
// In addition to verifying the signature (through the verifier above), we
|
419
|
+
// also verify the tokenId is still valid using a database to fetch
|
420
|
+
// missing data from "light" token.
|
421
|
+
return this.tokenManager.verifyToken(token, tokenType, tokenId, dpopJkt, verifyOptions);
|
842
422
|
}
|
423
|
+
// Fool-proof
|
424
|
+
throw new Error('Invalid access token mode');
|
843
425
|
}
|
844
|
-
return undefined;
|
845
426
|
}
|
427
|
+
exports.OAuthProvider = OAuthProvider;
|
846
428
|
//# sourceMappingURL=oauth-provider.js.map
|