@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,44 +0,0 @@
|
|
1
|
-
import { assets } from '@atproto/oauth-provider-ui'
|
2
|
-
import {
|
3
|
-
Middleware,
|
4
|
-
validateFetchDest,
|
5
|
-
validateFetchSite,
|
6
|
-
writeStream,
|
7
|
-
} from '../lib/http/index.js'
|
8
|
-
|
9
|
-
export const ASSETS_URL_PREFIX = '/@atproto/oauth-provider/~assets/'
|
10
|
-
|
11
|
-
export function buildAssetUrl(filename: string): string {
|
12
|
-
return `${ASSETS_URL_PREFIX}${encodeURIComponent(filename)}`
|
13
|
-
}
|
14
|
-
|
15
|
-
export function authorizeAssetsMiddleware(): Middleware {
|
16
|
-
return async function assetsMiddleware(req, res, next): Promise<void> {
|
17
|
-
if (req.method !== 'GET' && req.method !== 'HEAD') return next()
|
18
|
-
if (!req.url?.startsWith(ASSETS_URL_PREFIX)) return next()
|
19
|
-
|
20
|
-
const filename = req.url.slice(ASSETS_URL_PREFIX.length)
|
21
|
-
if (!filename) return next()
|
22
|
-
|
23
|
-
const asset = assets.get(filename)
|
24
|
-
if (!asset) return next()
|
25
|
-
|
26
|
-
try {
|
27
|
-
// Allow "null" (ie. no header) to allow loading assets outside of a
|
28
|
-
// fetch context (not from a web page).
|
29
|
-
validateFetchSite(req, res, [null, 'none', 'cross-site', 'same-origin'])
|
30
|
-
validateFetchDest(req, res, [null, 'document', 'style', 'script'])
|
31
|
-
} catch (err) {
|
32
|
-
return next(err)
|
33
|
-
}
|
34
|
-
|
35
|
-
if (req.headers['if-none-match'] === asset.sha256) {
|
36
|
-
return void res.writeHead(304).end()
|
37
|
-
}
|
38
|
-
|
39
|
-
res.setHeader('ETag', asset.sha256)
|
40
|
-
res.setHeader('Cache-Control', 'public, max-age=31536000, immutable')
|
41
|
-
|
42
|
-
writeStream(res, asset.stream(), { contentType: asset.mime })
|
43
|
-
}
|
44
|
-
}
|
package/src/lib/locale.ts
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
import { z } from 'zod'
|
2
|
-
|
3
|
-
export const localeSchema = z
|
4
|
-
.string()
|
5
|
-
.regex(/^[a-z]{2,3}(-[A-Z]{2})?$/, 'Invalid locale')
|
6
|
-
export type Locale = z.infer<typeof localeSchema>
|
7
|
-
|
8
|
-
export const multiLangStringSchema = z.intersection(
|
9
|
-
z.object({ en: z.string() }), // en is required
|
10
|
-
z.record(localeSchema, z.union([z.string(), z.undefined()])),
|
11
|
-
)
|
12
|
-
export type MultiLangString = z.infer<typeof multiLangStringSchema>
|
13
|
-
|
14
|
-
export const AVAILABLE_LOCALES = [
|
15
|
-
// TODO: Add more in this list as translations are added in the PO files
|
16
|
-
'en',
|
17
|
-
'fr',
|
18
|
-
] as const satisfies readonly Locale[]
|
19
|
-
export type AvailableLocale = (typeof AVAILABLE_LOCALES)[number]
|
20
|
-
export const isAvailableLocale = (v: unknown): v is AvailableLocale =>
|
21
|
-
(AVAILABLE_LOCALES as readonly unknown[]).includes(v)
|
@@ -1,53 +0,0 @@
|
|
1
|
-
import type { AuthorizeData, Session } from '@atproto/oauth-provider-api'
|
2
|
-
import { OAuthAuthorizationRequestParameters } from '@atproto/oauth-types'
|
3
|
-
import { DeviceAccountInfo } from '../account/account-store.js'
|
4
|
-
import { Account } from '../account/account.js'
|
5
|
-
import { Client } from '../client/client.js'
|
6
|
-
import { RequestUri } from '../request/request-uri.js'
|
7
|
-
|
8
|
-
export type ScopeDetail = {
|
9
|
-
scope: string
|
10
|
-
description?: string
|
11
|
-
}
|
12
|
-
|
13
|
-
export type AuthorizationResultAuthorize = {
|
14
|
-
issuer: string
|
15
|
-
client: Client
|
16
|
-
parameters: OAuthAuthorizationRequestParameters
|
17
|
-
authorize: {
|
18
|
-
uri: RequestUri
|
19
|
-
scopeDetails?: ScopeDetail[]
|
20
|
-
sessions: readonly {
|
21
|
-
account: Account
|
22
|
-
info: DeviceAccountInfo
|
23
|
-
|
24
|
-
selected: boolean
|
25
|
-
loginRequired: boolean
|
26
|
-
consentRequired: boolean
|
27
|
-
}[]
|
28
|
-
}
|
29
|
-
}
|
30
|
-
|
31
|
-
export type { AuthorizeData, Session }
|
32
|
-
|
33
|
-
export function buildAuthorizeData(
|
34
|
-
data: AuthorizationResultAuthorize,
|
35
|
-
): AuthorizeData {
|
36
|
-
return {
|
37
|
-
clientId: data.client.id,
|
38
|
-
clientMetadata: data.client.metadata,
|
39
|
-
clientTrusted: data.client.info.isTrusted,
|
40
|
-
requestUri: data.authorize.uri,
|
41
|
-
loginHint: data.parameters.login_hint,
|
42
|
-
newSessionsRequireConsent: data.parameters.prompt === 'consent',
|
43
|
-
scopeDetails: data.authorize.scopeDetails,
|
44
|
-
sessions: data.authorize.sessions.map(
|
45
|
-
(session): Session => ({
|
46
|
-
account: session.account,
|
47
|
-
selected: session.selected,
|
48
|
-
loginRequired: session.loginRequired,
|
49
|
-
consentRequired: session.consentRequired,
|
50
|
-
}),
|
51
|
-
),
|
52
|
-
}
|
53
|
-
}
|
@@ -1,217 +0,0 @@
|
|
1
|
-
import { z } from 'zod'
|
2
|
-
import { CustomizationData } from '@atproto/oauth-provider-api'
|
3
|
-
import { hcaptchaConfigSchema } from '../lib/hcaptcha.js'
|
4
|
-
import { isLinkRel } from '../lib/html/build-document.js'
|
5
|
-
import { multiLangStringSchema } from '../lib/locale.js'
|
6
|
-
export { type HcaptchaConfig, hcaptchaConfigSchema } from '../lib/hcaptcha.js'
|
7
|
-
|
8
|
-
// Matches colors defined in tailwind.config.js
|
9
|
-
export const colorNames = ['brand', 'error', 'warning', 'success'] as const
|
10
|
-
export const colorNameSchema = z.enum(colorNames)
|
11
|
-
export type ColorName = z.infer<typeof colorNameSchema>
|
12
|
-
|
13
|
-
const parsedColorSchema = z.string().transform((value, ctx): RgbColor => {
|
14
|
-
try {
|
15
|
-
const { r, g, b, a } = parseColor(value)
|
16
|
-
if (a != null) {
|
17
|
-
ctx.addIssue({
|
18
|
-
code: z.ZodIssueCode.custom,
|
19
|
-
message: 'Alpha values are not supported',
|
20
|
-
})
|
21
|
-
}
|
22
|
-
return { r, g, b }
|
23
|
-
} catch (e) {
|
24
|
-
ctx.addIssue({
|
25
|
-
code: z.ZodIssueCode.custom,
|
26
|
-
message: e instanceof Error ? e.message : 'Invalid color value',
|
27
|
-
})
|
28
|
-
// Won't actually be used (since an issue was added):
|
29
|
-
return { r: 0, g: 0, b: 0 }
|
30
|
-
}
|
31
|
-
})
|
32
|
-
export type ParsedColor = z.infer<typeof parsedColorSchema> // Same as RgbColor
|
33
|
-
|
34
|
-
export const colorsDefinitionSchema = z.record(
|
35
|
-
colorNameSchema,
|
36
|
-
parsedColorSchema.optional(),
|
37
|
-
)
|
38
|
-
export type ColorsDefinition = z.infer<typeof colorsDefinitionSchema>
|
39
|
-
|
40
|
-
export const localizedStringSchema = z.union([
|
41
|
-
z.string(),
|
42
|
-
multiLangStringSchema,
|
43
|
-
])
|
44
|
-
export type LocalizedString = z.infer<typeof localizedStringSchema>
|
45
|
-
|
46
|
-
export const linkRelSchema = z.string().refine(isLinkRel, 'Invalid link rel')
|
47
|
-
export type LinkRel = z.infer<typeof linkRelSchema>
|
48
|
-
|
49
|
-
export const linkDefinitionSchema = z.object({
|
50
|
-
title: localizedStringSchema,
|
51
|
-
href: z.string().url(),
|
52
|
-
rel: linkRelSchema.optional(),
|
53
|
-
})
|
54
|
-
export type LinkDefinition = z.infer<typeof linkDefinitionSchema>
|
55
|
-
|
56
|
-
/**
|
57
|
-
* Aesthetic customization
|
58
|
-
*/
|
59
|
-
export const brandingConfigSchema = z.object({
|
60
|
-
name: z.string().optional(),
|
61
|
-
logo: z.string().optional(),
|
62
|
-
colors: colorsDefinitionSchema.optional(),
|
63
|
-
links: z.array(linkDefinitionSchema).optional(),
|
64
|
-
})
|
65
|
-
export type BrandingInput = z.input<typeof brandingConfigSchema>
|
66
|
-
export type Branding = z.infer<typeof brandingConfigSchema>
|
67
|
-
|
68
|
-
export const customizationSchema = z.object({
|
69
|
-
/**
|
70
|
-
* Available user domains that can be used to sign up. A non-empty array
|
71
|
-
* is required to enable the sign-up feature.
|
72
|
-
*/
|
73
|
-
availableUserDomains: z.array(z.string()).optional(),
|
74
|
-
/**
|
75
|
-
* UI customizations
|
76
|
-
*/
|
77
|
-
branding: brandingConfigSchema.optional(),
|
78
|
-
/**
|
79
|
-
* Is an invite code required to sign up?
|
80
|
-
*/
|
81
|
-
inviteCodeRequired: z.boolean().optional(),
|
82
|
-
/**
|
83
|
-
* Enables hCaptcha during sign-up.
|
84
|
-
*/
|
85
|
-
hcaptcha: hcaptchaConfigSchema.optional(),
|
86
|
-
})
|
87
|
-
export type CustomizationInput = z.input<typeof customizationSchema>
|
88
|
-
export type Customization = z.infer<typeof customizationSchema>
|
89
|
-
|
90
|
-
export function buildCustomizationData({
|
91
|
-
branding,
|
92
|
-
availableUserDomains,
|
93
|
-
inviteCodeRequired,
|
94
|
-
hcaptcha,
|
95
|
-
}: Customization): CustomizationData {
|
96
|
-
// @NOTE the front end does not need colors here as they will be injected as
|
97
|
-
// CSS variables.
|
98
|
-
// @NOTE We only copy the values explicitly needed to avoid leaking sensitive
|
99
|
-
// data (in case the caller passed more than what we expect).
|
100
|
-
return {
|
101
|
-
availableUserDomains,
|
102
|
-
inviteCodeRequired,
|
103
|
-
hcaptchaSiteKey: hcaptcha?.siteKey,
|
104
|
-
name: branding?.name,
|
105
|
-
logo: branding?.logo,
|
106
|
-
links: branding?.links,
|
107
|
-
}
|
108
|
-
}
|
109
|
-
|
110
|
-
export function buildCustomizationCss({ branding }: Customization) {
|
111
|
-
const vars = Array.from(buildCustomizationVars(branding))
|
112
|
-
if (vars.length) return `:root { ${vars.join(' ')} }`
|
113
|
-
|
114
|
-
return ''
|
115
|
-
}
|
116
|
-
|
117
|
-
function* buildCustomizationVars(branding?: Branding) {
|
118
|
-
if (branding?.colors) {
|
119
|
-
for (const name of colorNames) {
|
120
|
-
const value = branding.colors[name]
|
121
|
-
if (!value) continue // Skip missing colors
|
122
|
-
|
123
|
-
const { r, g, b } = value
|
124
|
-
|
125
|
-
const contrast = computeLuma({ r, g, b }) > 128 ? '0 0 0' : '255 255 255'
|
126
|
-
|
127
|
-
yield `--color-${name}: ${r} ${g} ${b};`
|
128
|
-
yield `--color-${name}-c: ${contrast};`
|
129
|
-
}
|
130
|
-
}
|
131
|
-
}
|
132
|
-
|
133
|
-
type RgbColor = { r: number; g: number; b: number }
|
134
|
-
type RgbaColor = { r: number; g: number; b: number; a?: number }
|
135
|
-
function parseColor(color: string): RgbaColor {
|
136
|
-
if (color.startsWith('#')) {
|
137
|
-
return parseHexColor(color)
|
138
|
-
}
|
139
|
-
|
140
|
-
if (color.startsWith('rgba(')) {
|
141
|
-
return parseRgbaColor(color)
|
142
|
-
}
|
143
|
-
|
144
|
-
if (color.startsWith('rgb(')) {
|
145
|
-
return parseRgbColor(color)
|
146
|
-
}
|
147
|
-
|
148
|
-
// Should never happen (as long as the input is a validated WebColor)
|
149
|
-
throw new TypeError(`Invalid color value: ${color}`)
|
150
|
-
}
|
151
|
-
|
152
|
-
function parseHexColor(v: string) {
|
153
|
-
// parseInt('az', 16) does not return NaN so we need to check the format
|
154
|
-
if (!/^#[0-9a-f]+$/i.test(v)) {
|
155
|
-
throw new TypeError(`Invalid hex color value: ${v}`)
|
156
|
-
}
|
157
|
-
|
158
|
-
if (v.length === 4 || v.length === 5) {
|
159
|
-
const r = parseUi8Hex(v.slice(1, 2))
|
160
|
-
const g = parseUi8Hex(v.slice(2, 3))
|
161
|
-
const b = parseUi8Hex(v.slice(3, 4))
|
162
|
-
const a = v.length > 4 ? parseUi8Hex(v.slice(4, 5)) : undefined
|
163
|
-
return { r, g, b, a }
|
164
|
-
}
|
165
|
-
|
166
|
-
if (v.length === 7 || v.length === 9) {
|
167
|
-
const r = parseUi8Hex(v.slice(1, 3))
|
168
|
-
const g = parseUi8Hex(v.slice(3, 5))
|
169
|
-
const b = parseUi8Hex(v.slice(5, 7))
|
170
|
-
const a = v.length > 8 ? parseUi8Hex(v.slice(7, 9)) : undefined
|
171
|
-
return { r, g, b, a }
|
172
|
-
}
|
173
|
-
|
174
|
-
throw new TypeError(`Invalid hex color value: ${v}`)
|
175
|
-
}
|
176
|
-
|
177
|
-
function parseRgbColor(v: string) {
|
178
|
-
const matches = v.match(/^\s*rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/)
|
179
|
-
if (!matches) throw new TypeError(`Invalid rgb color value: ${v}`)
|
180
|
-
|
181
|
-
const r = parseUi8Dec(matches[1])
|
182
|
-
const g = parseUi8Dec(matches[2])
|
183
|
-
const b = parseUi8Dec(matches[3])
|
184
|
-
return { r, g, b }
|
185
|
-
}
|
186
|
-
|
187
|
-
function parseRgbaColor(v: string) {
|
188
|
-
const matches = v.match(
|
189
|
-
/^\s*rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/,
|
190
|
-
)
|
191
|
-
if (!matches) throw new TypeError(`Invalid rgba color value: ${v}`)
|
192
|
-
|
193
|
-
const r = parseUi8Dec(matches[1])
|
194
|
-
const g = parseUi8Dec(matches[2])
|
195
|
-
const b = parseUi8Dec(matches[3])
|
196
|
-
const a = parseUi8Dec(matches[4])
|
197
|
-
return { r, g, b, a }
|
198
|
-
}
|
199
|
-
|
200
|
-
function computeLuma({ r, g, b }: RgbaColor) {
|
201
|
-
return 0.299 * r + 0.587 * g + 0.114 * b
|
202
|
-
}
|
203
|
-
|
204
|
-
function parseUi8Hex(v: string) {
|
205
|
-
return asUi8(parseInt(v, 16))
|
206
|
-
}
|
207
|
-
|
208
|
-
function parseUi8Dec(v: string) {
|
209
|
-
return asUi8(parseInt(v, 10))
|
210
|
-
}
|
211
|
-
|
212
|
-
function asUi8(v: number) {
|
213
|
-
if (v >= 0 && v <= 255 && v === (v | 0)) return v
|
214
|
-
throw new TypeError(
|
215
|
-
`Invalid color component "${v}" (expected an integer between 0 and 255)`,
|
216
|
-
)
|
217
|
-
}
|
@@ -1,8 +0,0 @@
|
|
1
|
-
import { ErrorData } from '@atproto/oauth-provider-api'
|
2
|
-
import { buildErrorPayload } from './build-error-payload.js'
|
3
|
-
|
4
|
-
// @NOTE: The primary role of this function is to ensure that the ErrorPayload
|
5
|
-
// and ErrorData types are in sync.
|
6
|
-
export function buildErrorData(error: unknown): ErrorData {
|
7
|
-
return buildErrorPayload(error)
|
8
|
-
}
|
@@ -1,188 +0,0 @@
|
|
1
|
-
import type { ServerResponse } from 'node:http'
|
2
|
-
import { CustomizationData } from '@atproto/oauth-provider-api'
|
3
|
-
import { assets } from '@atproto/oauth-provider-ui'
|
4
|
-
import { buildAssetUrl } from '../assets/assets-middleware.js'
|
5
|
-
import { CspConfig, mergeCsp } from '../lib/csp/index.js'
|
6
|
-
import {
|
7
|
-
AssetRef,
|
8
|
-
Html,
|
9
|
-
LinkAttrs,
|
10
|
-
MetaAttrs,
|
11
|
-
cssCode,
|
12
|
-
html,
|
13
|
-
isLinkRel,
|
14
|
-
} from '../lib/html/index.js'
|
15
|
-
import { CrossOriginEmbedderPolicy } from '../lib/http/security-headers.js'
|
16
|
-
import { AVAILABLE_LOCALES, Locale, isAvailableLocale } from '../lib/locale.js'
|
17
|
-
import { declareBackendData } from './backend-data.js'
|
18
|
-
import {
|
19
|
-
AuthorizationResultAuthorize,
|
20
|
-
buildAuthorizeData,
|
21
|
-
} from './build-authorize-data.js'
|
22
|
-
import {
|
23
|
-
Customization,
|
24
|
-
LinkDefinition,
|
25
|
-
buildCustomizationCss,
|
26
|
-
buildCustomizationData,
|
27
|
-
} from './build-customization-data.js'
|
28
|
-
import { buildErrorData } from './build-error-data.js'
|
29
|
-
import { buildErrorStatus } from './build-error-payload.js'
|
30
|
-
import { sendWebPage } from './send-web-page.js'
|
31
|
-
|
32
|
-
const BASE_CSP: CspConfig = {
|
33
|
-
// API calls are made to the same origin
|
34
|
-
'connect-src': ["'self'"],
|
35
|
-
// Allow loading of PDS logo & User avatars
|
36
|
-
'img-src': ['data:', 'https:'],
|
37
|
-
// Prevent embedding in iframes
|
38
|
-
'frame-ancestors': ["'none'"],
|
39
|
-
}
|
40
|
-
|
41
|
-
/**
|
42
|
-
* @see {@link https://docs.hcaptcha.com/#content-security-policy-settings}
|
43
|
-
*/
|
44
|
-
const HCAPTCHA_CSP: CspConfig = {
|
45
|
-
'script-src': ['https://hcaptcha.com', 'https://*.hcaptcha.com'],
|
46
|
-
'frame-src': ['https://hcaptcha.com', 'https://*.hcaptcha.com'],
|
47
|
-
'style-src': ['https://hcaptcha.com', 'https://*.hcaptcha.com'],
|
48
|
-
'connect-src': ['https://hcaptcha.com', 'https://*.hcaptcha.com'],
|
49
|
-
}
|
50
|
-
|
51
|
-
export type SendPageOptions = {
|
52
|
-
preferredLocales?: readonly string[]
|
53
|
-
}
|
54
|
-
|
55
|
-
export class OutputManager {
|
56
|
-
readonly links?: readonly LinkDefinition[]
|
57
|
-
readonly meta: readonly MetaAttrs[] = [
|
58
|
-
{ name: 'robots', content: 'noindex' },
|
59
|
-
{ name: 'description', content: 'ATProto OAuth authorization page' },
|
60
|
-
]
|
61
|
-
readonly csp: CspConfig
|
62
|
-
readonly coep: CrossOriginEmbedderPolicy
|
63
|
-
readonly customizationData: CustomizationData
|
64
|
-
readonly customizationCss: Html
|
65
|
-
|
66
|
-
constructor(customization: Customization) {
|
67
|
-
this.links = customization.branding?.links
|
68
|
-
|
69
|
-
// "cache" these:
|
70
|
-
this.customizationData = buildCustomizationData(customization)
|
71
|
-
this.customizationCss = cssCode(buildCustomizationCss(customization))
|
72
|
-
|
73
|
-
this.csp = mergeCsp(
|
74
|
-
BASE_CSP,
|
75
|
-
customization?.hcaptcha ? HCAPTCHA_CSP : undefined,
|
76
|
-
)
|
77
|
-
// Because we are loading avatar images from external sources, that might
|
78
|
-
// not have CORP headers set, we need to use at least "credentialless".
|
79
|
-
this.coep = customization?.hcaptcha
|
80
|
-
? // https://github.com/hCaptcha/react-hcaptcha/issues/259
|
81
|
-
// @TODO Remove the use of `unsafeNone` once the issue above is resolved
|
82
|
-
CrossOriginEmbedderPolicy.unsafeNone
|
83
|
-
: CrossOriginEmbedderPolicy.credentialless
|
84
|
-
}
|
85
|
-
|
86
|
-
buildAssets(
|
87
|
-
name: string,
|
88
|
-
backendData: Record<string, unknown>,
|
89
|
-
): {
|
90
|
-
scripts: (AssetRef | Html)[]
|
91
|
-
styles: (AssetRef | Html)[]
|
92
|
-
} {
|
93
|
-
return {
|
94
|
-
scripts: [
|
95
|
-
declareBackendData(backendData),
|
96
|
-
// After backend injected data
|
97
|
-
...Array.from(assets)
|
98
|
-
.filter(
|
99
|
-
([, item]) =>
|
100
|
-
item.type === 'chunk' && item.isEntry && item.name === name,
|
101
|
-
)
|
102
|
-
.map(([filename]) => ({ url: buildAssetUrl(filename) })),
|
103
|
-
],
|
104
|
-
styles: [
|
105
|
-
...Array.from(assets)
|
106
|
-
.filter(([, item]) => item.mime === 'text/css')
|
107
|
-
.map(([filename]) => ({ url: buildAssetUrl(filename) })),
|
108
|
-
// Last (to be able to override the default styles)
|
109
|
-
this.customizationCss,
|
110
|
-
],
|
111
|
-
}
|
112
|
-
}
|
113
|
-
|
114
|
-
async sendAuthorizePage(
|
115
|
-
res: ServerResponse,
|
116
|
-
data: AuthorizationResultAuthorize,
|
117
|
-
options?: SendPageOptions,
|
118
|
-
): Promise<void> {
|
119
|
-
const locale = negotiateLocale(
|
120
|
-
data.parameters.ui_locales?.split(' ') ?? options?.preferredLocales,
|
121
|
-
)
|
122
|
-
|
123
|
-
const { scripts, styles } = this.buildAssets('authorization-page', {
|
124
|
-
__availableLocales: AVAILABLE_LOCALES,
|
125
|
-
__customizationData: this.customizationData,
|
126
|
-
__authorizeData: buildAuthorizeData(data),
|
127
|
-
})
|
128
|
-
|
129
|
-
return sendWebPage(res, {
|
130
|
-
scripts,
|
131
|
-
styles,
|
132
|
-
meta: this.meta,
|
133
|
-
links: this.buildLinks(locale),
|
134
|
-
htmlAttrs: { lang: locale },
|
135
|
-
body: html`<div id="root"></div>`,
|
136
|
-
csp: this.csp,
|
137
|
-
coep: this.coep,
|
138
|
-
})
|
139
|
-
}
|
140
|
-
|
141
|
-
async sendErrorPage(
|
142
|
-
res: ServerResponse,
|
143
|
-
err: unknown,
|
144
|
-
options?: SendPageOptions,
|
145
|
-
): Promise<void> {
|
146
|
-
const locale = negotiateLocale(options?.preferredLocales)
|
147
|
-
|
148
|
-
const { scripts, styles } = this.buildAssets('error-page', {
|
149
|
-
__availableLocales: AVAILABLE_LOCALES,
|
150
|
-
__customizationData: this.customizationData,
|
151
|
-
__errorData: buildErrorData(err),
|
152
|
-
})
|
153
|
-
|
154
|
-
return sendWebPage(res, {
|
155
|
-
status: buildErrorStatus(err),
|
156
|
-
scripts,
|
157
|
-
styles,
|
158
|
-
meta: this.meta,
|
159
|
-
links: this.buildLinks(locale),
|
160
|
-
htmlAttrs: { lang: locale },
|
161
|
-
body: html`<div id="root"></div>`,
|
162
|
-
csp: this.csp,
|
163
|
-
coep: this.coep,
|
164
|
-
})
|
165
|
-
}
|
166
|
-
|
167
|
-
buildLinks(locale: Locale) {
|
168
|
-
return this.links
|
169
|
-
?.map(({ rel, href, title }: LinkDefinition): LinkAttrs | undefined =>
|
170
|
-
isLinkRel(rel)
|
171
|
-
? typeof title === 'string'
|
172
|
-
? { href, rel, title }
|
173
|
-
: { href, rel, title: title[locale] || title.en }
|
174
|
-
: undefined,
|
175
|
-
)
|
176
|
-
.filter((v) => v != null)
|
177
|
-
}
|
178
|
-
}
|
179
|
-
|
180
|
-
function negotiateLocale(desiredLocales?: readonly string[]): Locale {
|
181
|
-
if (desiredLocales) {
|
182
|
-
for (const locale of desiredLocales) {
|
183
|
-
if (locale === '*') break // use default
|
184
|
-
if (isAvailableLocale(locale)) return locale
|
185
|
-
}
|
186
|
-
}
|
187
|
-
return 'en'
|
188
|
-
}
|
@@ -1,137 +0,0 @@
|
|
1
|
-
import type { ServerResponse } from 'node:http'
|
2
|
-
import {
|
3
|
-
OAuthAuthorizationRequestParameters,
|
4
|
-
OAuthTokenType,
|
5
|
-
} from '@atproto/oauth-types'
|
6
|
-
import { InvalidRequestError } from '../errors/invalid-request-error.js'
|
7
|
-
import { html, js } from '../lib/html/index.js'
|
8
|
-
import { Code } from '../request/code.js'
|
9
|
-
import { sendWebPage } from './send-web-page.js'
|
10
|
-
|
11
|
-
// https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-11#section-7.5.4
|
12
|
-
const REDIRECT_STATUS_CODE = 303
|
13
|
-
|
14
|
-
/**
|
15
|
-
* @note `iss` and `state` will be added from the
|
16
|
-
* {@link AuthorizationResultRedirect} object.
|
17
|
-
*/
|
18
|
-
export type AuthorizationRedirectParameters =
|
19
|
-
| {
|
20
|
-
// iss: string
|
21
|
-
// state?: string
|
22
|
-
code: Code
|
23
|
-
id_token?: string
|
24
|
-
access_token?: string
|
25
|
-
token_type?: OAuthTokenType
|
26
|
-
expires_in?: string
|
27
|
-
}
|
28
|
-
| {
|
29
|
-
// iss: string
|
30
|
-
// state?: string
|
31
|
-
error: string
|
32
|
-
error_description?: string
|
33
|
-
error_uri?: string
|
34
|
-
}
|
35
|
-
|
36
|
-
const SUCCESS_REDIRECT_KEYS = [
|
37
|
-
'code',
|
38
|
-
'id_token',
|
39
|
-
'access_token',
|
40
|
-
'expires_in',
|
41
|
-
'token_type',
|
42
|
-
] as const
|
43
|
-
|
44
|
-
const ERROR_REDIRECT_KEYS = ['error', 'error_description', 'error_uri'] as const
|
45
|
-
|
46
|
-
export type AuthorizationResultRedirect = {
|
47
|
-
issuer: string
|
48
|
-
parameters: OAuthAuthorizationRequestParameters
|
49
|
-
redirect: AuthorizationRedirectParameters
|
50
|
-
}
|
51
|
-
|
52
|
-
export async function sendAuthorizeRedirect(
|
53
|
-
res: ServerResponse,
|
54
|
-
result: AuthorizationResultRedirect,
|
55
|
-
): Promise<void> {
|
56
|
-
const { issuer, parameters, redirect } = result
|
57
|
-
|
58
|
-
const uri = parameters.redirect_uri
|
59
|
-
if (!uri) throw new InvalidRequestError('No redirect_uri')
|
60
|
-
|
61
|
-
const mode = parameters.response_mode || 'query' // @TODO: default should depend on response_type
|
62
|
-
|
63
|
-
const entries: [string, string][] = [
|
64
|
-
['iss', issuer], // rfc9207
|
65
|
-
]
|
66
|
-
|
67
|
-
if (parameters.state != null) {
|
68
|
-
entries.push(['state', parameters.state])
|
69
|
-
}
|
70
|
-
|
71
|
-
const keys = 'code' in redirect ? SUCCESS_REDIRECT_KEYS : ERROR_REDIRECT_KEYS
|
72
|
-
for (const key of keys) {
|
73
|
-
const value = redirect[key]
|
74
|
-
if (value != null) entries.push([key, value])
|
75
|
-
}
|
76
|
-
|
77
|
-
res.setHeader('Cache-Control', 'no-store')
|
78
|
-
|
79
|
-
switch (mode) {
|
80
|
-
case 'query':
|
81
|
-
return writeQuery(res, uri, entries)
|
82
|
-
case 'fragment':
|
83
|
-
return writeFragment(res, uri, entries)
|
84
|
-
case 'form_post':
|
85
|
-
return writeFormPost(res, uri, entries)
|
86
|
-
}
|
87
|
-
|
88
|
-
// @ts-expect-error fool proof
|
89
|
-
throw new Error(`Unsupported mode: ${mode}`)
|
90
|
-
}
|
91
|
-
|
92
|
-
function writeQuery(
|
93
|
-
res: ServerResponse,
|
94
|
-
uri: string,
|
95
|
-
entries: readonly [string, string][],
|
96
|
-
) {
|
97
|
-
const url = new URL(uri)
|
98
|
-
for (const [key, value] of entries) url.searchParams.set(key, value)
|
99
|
-
res.writeHead(REDIRECT_STATUS_CODE, { Location: url.href }).end()
|
100
|
-
}
|
101
|
-
|
102
|
-
function writeFragment(
|
103
|
-
res: ServerResponse,
|
104
|
-
uri: string,
|
105
|
-
entries: readonly [string, string][],
|
106
|
-
) {
|
107
|
-
const url = new URL(uri)
|
108
|
-
const searchParams = new URLSearchParams()
|
109
|
-
for (const [key, value] of entries) searchParams.set(key, value)
|
110
|
-
url.hash = searchParams.toString()
|
111
|
-
res.writeHead(REDIRECT_STATUS_CODE, { Location: url.href }).end()
|
112
|
-
}
|
113
|
-
|
114
|
-
async function writeFormPost(
|
115
|
-
res: ServerResponse,
|
116
|
-
uri: string,
|
117
|
-
entries: readonly [string, string][],
|
118
|
-
) {
|
119
|
-
// Prevent the Chrome from caching this page
|
120
|
-
// see: https://latesthackingnews.com/2023/12/12/google-updates-chrome-bfcache-for-faster-page-viewing/
|
121
|
-
res.setHeader('Set-Cookie', `bfCacheBypass=foo; max-age=1; SameSite=Lax`)
|
122
|
-
res.setHeader('Cache-Control', 'no-store')
|
123
|
-
res.setHeader('Permissions-Policy', 'otp-credentials=*, document-domain=()')
|
124
|
-
|
125
|
-
return sendWebPage(res, {
|
126
|
-
htmlAttrs: { lang: 'en' },
|
127
|
-
body: html`
|
128
|
-
<form method="post" action="${uri}">
|
129
|
-
${entries.map(([key, value]) => [
|
130
|
-
html`<input type="hidden" name="${key}" value="${value}" />`,
|
131
|
-
])}
|
132
|
-
<input type="submit" value="Continue" />
|
133
|
-
</form>
|
134
|
-
`,
|
135
|
-
scripts: [js`document.forms[0].submit();`],
|
136
|
-
})
|
137
|
-
}
|
@@ -1,30 +0,0 @@
|
|
1
|
-
import { z } from 'zod'
|
2
|
-
import { jwtPayloadSchema } from '@atproto/jwk'
|
3
|
-
import { clientIdSchema } from '../client/client-id.js'
|
4
|
-
import { Simplify } from '../lib/util/type.js'
|
5
|
-
import { subSchema } from '../oidc/sub.js'
|
6
|
-
|
7
|
-
export const tokenClaimsSchema = z.intersection(
|
8
|
-
jwtPayloadSchema
|
9
|
-
.pick({
|
10
|
-
iat: true,
|
11
|
-
exp: true,
|
12
|
-
aud: true,
|
13
|
-
})
|
14
|
-
.required(),
|
15
|
-
jwtPayloadSchema
|
16
|
-
.omit({
|
17
|
-
exp: true,
|
18
|
-
iat: true,
|
19
|
-
iss: true,
|
20
|
-
aud: true,
|
21
|
-
jti: true,
|
22
|
-
})
|
23
|
-
.partial()
|
24
|
-
.extend({
|
25
|
-
sub: subSchema,
|
26
|
-
client_id: clientIdSchema,
|
27
|
-
}),
|
28
|
-
)
|
29
|
-
|
30
|
-
export type TokenClaims = Simplify<z.infer<typeof tokenClaimsSchema>>
|