@masheev/better-auth 0.0.0-stage → 1.7.5
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/LICENSE.md +20 -0
- package/README.md +31 -2
- package/TYPE-PATCH-NOTICE.md +9 -0
- package/TYPE-PATCH-PROVENANCE.json +267 -0
- package/dist/_virtual/_rolldown/runtime.mjs +27 -0
- package/dist/adapters/drizzle-adapter/index.d.mts +1 -0
- package/dist/adapters/drizzle-adapter/index.mjs +2 -0
- package/dist/adapters/index.d.mts +26 -0
- package/dist/adapters/index.mjs +9 -0
- package/dist/adapters/kysely-adapter/index.d.mts +1 -0
- package/dist/adapters/kysely-adapter/index.mjs +2 -0
- package/dist/adapters/memory-adapter/index.d.mts +1 -0
- package/dist/adapters/memory-adapter/index.mjs +2 -0
- package/dist/adapters/mongodb-adapter/index.d.mts +1 -0
- package/dist/adapters/mongodb-adapter/index.mjs +2 -0
- package/dist/adapters/prisma-adapter/index.d.mts +1 -0
- package/dist/adapters/prisma-adapter/index.mjs +2 -0
- package/dist/api/dispatch.d.mts +34 -0
- package/dist/api/dispatch.mjs +275 -0
- package/dist/api/index.d.mts +4053 -0
- package/dist/api/index.mjs +220 -0
- package/dist/api/middlewares/authorization.d.mts +69 -0
- package/dist/api/middlewares/authorization.mjs +78 -0
- package/dist/api/middlewares/index.d.mts +2 -0
- package/dist/api/middlewares/origin-check.d.mts +17 -0
- package/dist/api/middlewares/origin-check.mjs +155 -0
- package/dist/api/rate-limiter/index.mjs +318 -0
- package/dist/api/routes/account.d.mts +413 -0
- package/dist/api/routes/account.mjs +619 -0
- package/dist/api/routes/callback.d.mts +32 -0
- package/dist/api/routes/callback.mjs +261 -0
- package/dist/api/routes/email-verification.d.mts +160 -0
- package/dist/api/routes/email-verification.mjs +324 -0
- package/dist/api/routes/error.d.mts +27 -0
- package/dist/api/routes/error.mjs +387 -0
- package/dist/api/routes/index.d.mts +12 -0
- package/dist/api/routes/ok.d.mts +35 -0
- package/dist/api/routes/ok.mjs +27 -0
- package/dist/api/routes/password.d.mts +182 -0
- package/dist/api/routes/password.mjs +206 -0
- package/dist/api/routes/session.d.mts +450 -0
- package/dist/api/routes/session.mjs +481 -0
- package/dist/api/routes/sign-in.d.mts +186 -0
- package/dist/api/routes/sign-in.mjs +368 -0
- package/dist/api/routes/sign-out.d.mts +51 -0
- package/dist/api/routes/sign-out.mjs +96 -0
- package/dist/api/routes/sign-up.d.mts +159 -0
- package/dist/api/routes/sign-up.mjs +275 -0
- package/dist/api/routes/update-session.d.mts +74 -0
- package/dist/api/routes/update-session.mjs +57 -0
- package/dist/api/routes/update-user.d.mts +428 -0
- package/dist/api/routes/update-user.mjs +522 -0
- package/dist/api/state/oauth.d.mts +53 -0
- package/dist/api/state/oauth.mjs +38 -0
- package/dist/api/state/should-session-refresh.d.mts +12 -0
- package/dist/api/state/should-session-refresh.mjs +13 -0
- package/dist/api/to-auth-endpoints.mjs +60 -0
- package/dist/auth/base.mjs +66 -0
- package/dist/auth/full.d.mts +28 -0
- package/dist/auth/full.mjs +29 -0
- package/dist/auth/minimal.d.mts +10 -0
- package/dist/auth/minimal.mjs +11 -0
- package/dist/auth/trusted-origins.mjs +106 -0
- package/dist/client/broadcast-channel.d.mts +19 -0
- package/dist/client/broadcast-channel.mjs +44 -0
- package/dist/client/config.d.mts +90 -0
- package/dist/client/config.mjs +113 -0
- package/dist/client/equality.d.mts +19 -0
- package/dist/client/equality.mjs +42 -0
- package/dist/client/fetch-plugins.mjs +17 -0
- package/dist/client/focus-manager.d.mts +10 -0
- package/dist/client/focus-manager.mjs +30 -0
- package/dist/client/index.d.mts +35 -0
- package/dist/client/index.mjs +22 -0
- package/dist/client/lynx/index.d.mts +43 -0
- package/dist/client/lynx/index.mjs +22 -0
- package/dist/client/lynx/lynx-store.d.mts +46 -0
- package/dist/client/lynx/lynx-store.mjs +44 -0
- package/dist/client/online-manager.d.mts +11 -0
- package/dist/client/online-manager.mjs +33 -0
- package/dist/client/parser.d.mts +10 -0
- package/dist/client/parser.mjs +70 -0
- package/dist/client/path-to-object.d.mts +113 -0
- package/dist/client/plugins/index.d.mts +44 -0
- package/dist/client/plugins/index.mjs +30 -0
- package/dist/client/plugins/infer-plugin.d.mts +16 -0
- package/dist/client/plugins/infer-plugin.mjs +11 -0
- package/dist/client/proxy.mjs +78 -0
- package/dist/client/query.d.mts +23 -0
- package/dist/client/query.mjs +124 -0
- package/dist/client/react/index.d.mts +44 -0
- package/dist/client/react/index.mjs +22 -0
- package/dist/client/react/react-store.d.mts +46 -0
- package/dist/client/react/react-store.mjs +44 -0
- package/dist/client/session-atom.d.mts +11 -0
- package/dist/client/session-atom.mjs +178 -0
- package/dist/client/session-refresh.d.mts +20 -0
- package/dist/client/session-refresh.mjs +131 -0
- package/dist/client/solid/index.d.mts +44 -0
- package/dist/client/solid/index.mjs +22 -0
- package/dist/client/solid/solid-store.mjs +21 -0
- package/dist/client/svelte/index.d.mts +44 -0
- package/dist/client/svelte/index.mjs +18 -0
- package/dist/client/types.d.mts +51 -0
- package/dist/client/vanilla.d.mts +42 -0
- package/dist/client/vanilla.mjs +18 -0
- package/dist/client/vue/index.d.mts +67 -0
- package/dist/client/vue/index.mjs +54 -0
- package/dist/client/vue/vue-store.mjs +23 -0
- package/dist/context/create-context.mjs +235 -0
- package/dist/context/helpers.mjs +158 -0
- package/dist/context/init-minimal.mjs +17 -0
- package/dist/context/init.mjs +19 -0
- package/dist/context/secret-utils.mjs +53 -0
- package/dist/context/store-capabilities.mjs +12 -0
- package/dist/cookies/cache.mjs +33 -0
- package/dist/cookies/cookie-utils.d.mts +72 -0
- package/dist/cookies/cookie-utils.mjs +203 -0
- package/dist/cookies/index.d.mts +124 -0
- package/dist/cookies/index.mjs +350 -0
- package/dist/cookies/jwt.mjs +44 -0
- package/dist/cookies/session-store.d.mts +32 -0
- package/dist/cookies/session-store.mjs +183 -0
- package/dist/crypto/buffer.d.mts +7 -0
- package/dist/crypto/buffer.mjs +16 -0
- package/dist/crypto/index.d.mts +32 -0
- package/dist/crypto/index.mjs +69 -0
- package/dist/crypto/jwt.d.mts +9 -0
- package/dist/crypto/jwt.mjs +141 -0
- package/dist/crypto/password.d.mts +13 -0
- package/dist/crypto/password.mjs +14 -0
- package/dist/crypto/random.d.mts +4 -0
- package/dist/crypto/random.mjs +5 -0
- package/dist/db/adapter-base.d.mts +7 -0
- package/dist/db/adapter-base.mjs +25 -0
- package/dist/db/adapter-kysely.d.mts +7 -0
- package/dist/db/adapter-kysely.mjs +17 -0
- package/dist/db/field-converter.d.mts +7 -0
- package/dist/db/field-converter.mjs +19 -0
- package/dist/db/field.d.mts +41 -0
- package/dist/db/get-migration.d.mts +56 -0
- package/dist/db/get-migration.mjs +685 -0
- package/dist/db/get-schema.d.mts +13 -0
- package/dist/db/get-schema.mjs +39 -0
- package/dist/db/index.d.mts +10 -0
- package/dist/db/index.mjs +35 -0
- package/dist/db/internal-adapter.d.mts +14 -0
- package/dist/db/internal-adapter.mjs +951 -0
- package/dist/db/revoke-unproven-account-access.d.mts +21 -0
- package/dist/db/revoke-unproven-account-access.mjs +58 -0
- package/dist/db/schema.d.mts +62 -0
- package/dist/db/schema.mjs +161 -0
- package/dist/db/to-zod.d.mts +35 -0
- package/dist/db/to-zod.mjs +23 -0
- package/dist/db/verification-token-storage.mjs +25 -0
- package/dist/db/with-hooks.d.mts +37 -0
- package/dist/db/with-hooks.mjs +255 -0
- package/dist/index.d.mts +30 -0
- package/dist/index.mjs +17 -0
- package/dist/integrations/cookie-plugin-guard.mjs +18 -0
- package/dist/integrations/next-js.d.mts +29 -0
- package/dist/integrations/next-js.mjs +105 -0
- package/dist/integrations/node.d.mts +11 -0
- package/dist/integrations/node.mjs +13 -0
- package/dist/integrations/solid-start.d.mts +22 -0
- package/dist/integrations/solid-start.mjs +15 -0
- package/dist/integrations/svelte-kit.d.mts +38 -0
- package/dist/integrations/svelte-kit.mjs +57 -0
- package/dist/integrations/tanstack-start-solid.d.mts +33 -0
- package/dist/integrations/tanstack-start-solid.mjs +57 -0
- package/dist/integrations/tanstack-start.d.mts +33 -0
- package/dist/integrations/tanstack-start.mjs +57 -0
- package/dist/oauth2/account-key.mjs +43 -0
- package/dist/oauth2/errors.mjs +49 -0
- package/dist/oauth2/index.d.mts +5 -0
- package/dist/oauth2/index.mjs +5 -0
- package/dist/oauth2/link-account.d.mts +96 -0
- package/dist/oauth2/link-account.mjs +329 -0
- package/dist/oauth2/state.d.mts +54 -0
- package/dist/oauth2/state.mjs +67 -0
- package/dist/oauth2/utils.d.mts +11 -0
- package/dist/oauth2/utils.mjs +33 -0
- package/dist/package.mjs +4 -0
- package/dist/plugins/access/access.d.mts +17 -0
- package/dist/plugins/access/access.mjs +78 -0
- package/dist/plugins/access/index.d.mts +3 -0
- package/dist/plugins/access/index.mjs +2 -0
- package/dist/plugins/access/types.d.mts +24 -0
- package/dist/plugins/additional-fields/client.d.mts +100 -0
- package/dist/plugins/additional-fields/client.mjs +11 -0
- package/dist/plugins/admin/access/index.d.mts +2 -0
- package/dist/plugins/admin/access/index.mjs +2 -0
- package/dist/plugins/admin/access/statement.d.mts +51 -0
- package/dist/plugins/admin/access/statement.mjs +52 -0
- package/dist/plugins/admin/admin.d.mts +911 -0
- package/dist/plugins/admin/admin.mjs +89 -0
- package/dist/plugins/admin/client.d.mts +81 -0
- package/dist/plugins/admin/client.mjs +39 -0
- package/dist/plugins/admin/error-codes.d.mts +30 -0
- package/dist/plugins/admin/error-codes.mjs +29 -0
- package/dist/plugins/admin/has-permission.mjs +12 -0
- package/dist/plugins/admin/index.d.mts +3 -0
- package/dist/plugins/admin/index.mjs +2 -0
- package/dist/plugins/admin/routes.mjs +919 -0
- package/dist/plugins/admin/schema.d.mts +40 -0
- package/dist/plugins/admin/schema.mjs +33 -0
- package/dist/plugins/admin/types.d.mts +88 -0
- package/dist/plugins/anonymous/client.d.mts +32 -0
- package/dist/plugins/anonymous/client.mjs +21 -0
- package/dist/plugins/anonymous/error-codes.d.mts +15 -0
- package/dist/plugins/anonymous/error-codes.mjs +14 -0
- package/dist/plugins/anonymous/index.d.mts +175 -0
- package/dist/plugins/anonymous/index.mjs +219 -0
- package/dist/plugins/anonymous/schema.d.mts +15 -0
- package/dist/plugins/anonymous/schema.mjs +9 -0
- package/dist/plugins/anonymous/types.d.mts +65 -0
- package/dist/plugins/bearer/index.d.mts +45 -0
- package/dist/plugins/bearer/index.mjs +74 -0
- package/dist/plugins/captcha/constants.d.mts +9 -0
- package/dist/plugins/captcha/constants.mjs +27 -0
- package/dist/plugins/captcha/error-codes.mjs +13 -0
- package/dist/plugins/captcha/index.d.mts +27 -0
- package/dist/plugins/captcha/index.mjs +79 -0
- package/dist/plugins/captcha/types.d.mts +52 -0
- package/dist/plugins/captcha/utils.mjs +9 -0
- package/dist/plugins/captcha/verify-handlers/captchafox.mjs +27 -0
- package/dist/plugins/captcha/verify-handlers/cloudflare-turnstile.mjs +47 -0
- package/dist/plugins/captcha/verify-handlers/google-recaptcha.mjs +32 -0
- package/dist/plugins/captcha/verify-handlers/h-captcha.mjs +27 -0
- package/dist/plugins/custom-session/client.d.mts +17 -0
- package/dist/plugins/custom-session/client.mjs +7 -0
- package/dist/plugins/custom-session/index.d.mts +73 -0
- package/dist/plugins/custom-session/index.mjs +65 -0
- package/dist/plugins/device-authorization/client.d.mts +17 -0
- package/dist/plugins/device-authorization/client.mjs +18 -0
- package/dist/plugins/device-authorization/error-codes.mjs +19 -0
- package/dist/plugins/device-authorization/index.d.mts +558 -0
- package/dist/plugins/device-authorization/index.mjs +87 -0
- package/dist/plugins/device-authorization/routes.d.mts +32 -0
- package/dist/plugins/device-authorization/routes.mjs +725 -0
- package/dist/plugins/device-authorization/schema.d.mts +18 -0
- package/dist/plugins/device-authorization/schema.mjs +63 -0
- package/dist/plugins/email-otp/client.d.mts +21 -0
- package/dist/plugins/email-otp/client.mjs +17 -0
- package/dist/plugins/email-otp/error-codes.d.mts +10 -0
- package/dist/plugins/email-otp/error-codes.mjs +9 -0
- package/dist/plugins/email-otp/index.d.mts +551 -0
- package/dist/plugins/email-otp/index.mjs +145 -0
- package/dist/plugins/email-otp/otp-token.mjs +55 -0
- package/dist/plugins/email-otp/routes.mjs +784 -0
- package/dist/plugins/email-otp/types.d.mts +109 -0
- package/dist/plugins/email-otp/utils.mjs +17 -0
- package/dist/plugins/generic-oauth/error-codes.mjs +8 -0
- package/dist/plugins/generic-oauth/index.d.mts +52 -0
- package/dist/plugins/generic-oauth/index.mjs +279 -0
- package/dist/plugins/generic-oauth/providers/auth0.d.mts +36 -0
- package/dist/plugins/generic-oauth/providers/auth0.mjs +49 -0
- package/dist/plugins/generic-oauth/providers/gumroad.d.mts +31 -0
- package/dist/plugins/generic-oauth/providers/gumroad.mjs +62 -0
- package/dist/plugins/generic-oauth/providers/hubspot.d.mts +36 -0
- package/dist/plugins/generic-oauth/providers/hubspot.mjs +62 -0
- package/dist/plugins/generic-oauth/providers/index.d.mts +10 -0
- package/dist/plugins/generic-oauth/providers/keycloak.d.mts +36 -0
- package/dist/plugins/generic-oauth/providers/keycloak.mjs +47 -0
- package/dist/plugins/generic-oauth/providers/line.d.mts +54 -0
- package/dist/plugins/generic-oauth/providers/line.mjs +93 -0
- package/dist/plugins/generic-oauth/providers/microsoft-entra-id.d.mts +39 -0
- package/dist/plugins/generic-oauth/providers/microsoft-entra-id.mjs +104 -0
- package/dist/plugins/generic-oauth/providers/okta.d.mts +36 -0
- package/dist/plugins/generic-oauth/providers/okta.mjs +47 -0
- package/dist/plugins/generic-oauth/providers/patreon.d.mts +29 -0
- package/dist/plugins/generic-oauth/providers/patreon.mjs +61 -0
- package/dist/plugins/generic-oauth/providers/slack.d.mts +29 -0
- package/dist/plugins/generic-oauth/providers/slack.mjs +63 -0
- package/dist/plugins/generic-oauth/providers/yandex.d.mts +29 -0
- package/dist/plugins/generic-oauth/providers/yandex.mjs +67 -0
- package/dist/plugins/generic-oauth/types.d.mts +268 -0
- package/dist/plugins/haveibeenpwned/index.d.mts +63 -0
- package/dist/plugins/haveibeenpwned/index.mjs +81 -0
- package/dist/plugins/index.d.mts +69 -0
- package/dist/plugins/index.mjs +49 -0
- package/dist/plugins/jwt/adapter.mjs +68 -0
- package/dist/plugins/jwt/client.d.mts +41 -0
- package/dist/plugins/jwt/client.mjs +19 -0
- package/dist/plugins/jwt/cookie-cache.mjs +77 -0
- package/dist/plugins/jwt/index.d.mts +246 -0
- package/dist/plugins/jwt/index.mjs +214 -0
- package/dist/plugins/jwt/schema.d.mts +33 -0
- package/dist/plugins/jwt/schema.mjs +29 -0
- package/dist/plugins/jwt/sign.d.mts +128 -0
- package/dist/plugins/jwt/sign.mjs +130 -0
- package/dist/plugins/jwt/types.d.mts +256 -0
- package/dist/plugins/jwt/utils.d.mts +41 -0
- package/dist/plugins/jwt/utils.mjs +64 -0
- package/dist/plugins/jwt/verify.d.mts +11 -0
- package/dist/plugins/jwt/verify.mjs +45 -0
- package/dist/plugins/last-login-method/client.d.mts +48 -0
- package/dist/plugins/last-login-method/client.mjs +48 -0
- package/dist/plugins/last-login-method/index.d.mts +127 -0
- package/dist/plugins/last-login-method/index.mjs +98 -0
- package/dist/plugins/magic-link/client.d.mts +10 -0
- package/dist/plugins/magic-link/client.mjs +11 -0
- package/dist/plugins/magic-link/index.d.mts +213 -0
- package/dist/plugins/magic-link/index.mjs +208 -0
- package/dist/plugins/magic-link/utils.mjs +9 -0
- package/dist/plugins/multi-session/client.d.mts +19 -0
- package/dist/plugins/multi-session/client.mjs +19 -0
- package/dist/plugins/multi-session/error-codes.d.mts +8 -0
- package/dist/plugins/multi-session/error-codes.mjs +5 -0
- package/dist/plugins/multi-session/index.d.mts +212 -0
- package/dist/plugins/multi-session/index.mjs +217 -0
- package/dist/plugins/oauth-popup/client.d.mts +82 -0
- package/dist/plugins/oauth-popup/client.mjs +203 -0
- package/dist/plugins/oauth-popup/constants.d.mts +11 -0
- package/dist/plugins/oauth-popup/constants.mjs +11 -0
- package/dist/plugins/oauth-popup/error-codes.d.mts +11 -0
- package/dist/plugins/oauth-popup/error-codes.mjs +10 -0
- package/dist/plugins/oauth-popup/index.d.mts +67 -0
- package/dist/plugins/oauth-popup/index.mjs +232 -0
- package/dist/plugins/oauth-popup/types.d.mts +30 -0
- package/dist/plugins/oauth-proxy/index.d.mts +130 -0
- package/dist/plugins/oauth-proxy/index.mjs +407 -0
- package/dist/plugins/oauth-proxy/utils.mjs +55 -0
- package/dist/plugins/one-tap/client.d.mts +174 -0
- package/dist/plugins/one-tap/client.mjs +208 -0
- package/dist/plugins/one-tap/index.d.mts +82 -0
- package/dist/plugins/one-tap/index.mjs +100 -0
- package/dist/plugins/one-time-token/client.d.mts +10 -0
- package/dist/plugins/one-time-token/client.mjs +11 -0
- package/dist/plugins/one-time-token/index.d.mts +132 -0
- package/dist/plugins/one-time-token/index.mjs +107 -0
- package/dist/plugins/one-time-token/utils.mjs +9 -0
- package/dist/plugins/open-api/generator.d.mts +126 -0
- package/dist/plugins/open-api/generator.mjs +557 -0
- package/dist/plugins/open-api/index.d.mts +97 -0
- package/dist/plugins/open-api/index.mjs +65 -0
- package/dist/plugins/open-api/logo.mjs +13 -0
- package/dist/plugins/organization/access/index.d.mts +2 -0
- package/dist/plugins/organization/access/index.mjs +2 -0
- package/dist/plugins/organization/access/statement.d.mts +113 -0
- package/dist/plugins/organization/access/statement.mjs +77 -0
- package/dist/plugins/organization/adapter.d.mts +815 -0
- package/dist/plugins/organization/adapter.mjs +813 -0
- package/dist/plugins/organization/call.mjs +15 -0
- package/dist/plugins/organization/client.d.mts +375 -0
- package/dist/plugins/organization/client.mjs +104 -0
- package/dist/plugins/organization/error-codes.d.mts +66 -0
- package/dist/plugins/organization/error-codes.mjs +65 -0
- package/dist/plugins/organization/has-permission.d.mts +17 -0
- package/dist/plugins/organization/has-permission.mjs +34 -0
- package/dist/plugins/organization/index.d.mts +6 -0
- package/dist/plugins/organization/index.mjs +4 -0
- package/dist/plugins/organization/organization.d.mts +420 -0
- package/dist/plugins/organization/organization.mjs +886 -0
- package/dist/plugins/organization/permission.d.mts +15 -0
- package/dist/plugins/organization/permission.mjs +14 -0
- package/dist/plugins/organization/routes/crud-access-control.d.mts +511 -0
- package/dist/plugins/organization/routes/crud-access-control.mjs +674 -0
- package/dist/plugins/organization/routes/crud-invites.d.mts +1154 -0
- package/dist/plugins/organization/routes/crud-invites.mjs +602 -0
- package/dist/plugins/organization/routes/crud-members.d.mts +1057 -0
- package/dist/plugins/organization/routes/crud-members.mjs +518 -0
- package/dist/plugins/organization/routes/crud-org.d.mts +918 -0
- package/dist/plugins/organization/routes/crud-org.mjs +455 -0
- package/dist/plugins/organization/routes/crud-team.d.mts +1238 -0
- package/dist/plugins/organization/routes/crud-team.mjs +766 -0
- package/dist/plugins/organization/schema.d.mts +390 -0
- package/dist/plugins/organization/schema.mjs +65 -0
- package/dist/plugins/organization/types.d.mts +691 -0
- package/dist/plugins/phone-number/client.d.mts +31 -0
- package/dist/plugins/phone-number/client.mjs +19 -0
- package/dist/plugins/phone-number/error-codes.d.mts +19 -0
- package/dist/plugins/phone-number/error-codes.mjs +18 -0
- package/dist/plugins/phone-number/index.d.mts +360 -0
- package/dist/plugins/phone-number/index.mjs +57 -0
- package/dist/plugins/phone-number/routes.mjs +529 -0
- package/dist/plugins/phone-number/schema.d.mts +22 -0
- package/dist/plugins/phone-number/schema.mjs +18 -0
- package/dist/plugins/phone-number/types.d.mts +116 -0
- package/dist/plugins/siwe/client.d.mts +14 -0
- package/dist/plugins/siwe/client.mjs +15 -0
- package/dist/plugins/siwe/index.d.mts +62 -0
- package/dist/plugins/siwe/index.mjs +272 -0
- package/dist/plugins/siwe/parse-message.mjs +60 -0
- package/dist/plugins/siwe/schema.d.mts +35 -0
- package/dist/plugins/siwe/schema.mjs +30 -0
- package/dist/plugins/siwe/types.d.mts +43 -0
- package/dist/plugins/test-utils/auth-helpers.mjs +33 -0
- package/dist/plugins/test-utils/cookie-builder.mjs +55 -0
- package/dist/plugins/test-utils/db-helpers.mjs +65 -0
- package/dist/plugins/test-utils/factories.mjs +38 -0
- package/dist/plugins/test-utils/index.d.mts +73 -0
- package/dist/plugins/test-utils/index.mjs +97 -0
- package/dist/plugins/test-utils/otp-sink.mjs +21 -0
- package/dist/plugins/test-utils/types.d.mts +51 -0
- package/dist/plugins/two-factor/backup-codes/index.d.mts +291 -0
- package/dist/plugins/two-factor/backup-codes/index.mjs +341 -0
- package/dist/plugins/two-factor/client.d.mts +76 -0
- package/dist/plugins/two-factor/client.mjs +41 -0
- package/dist/plugins/two-factor/constant.mjs +6 -0
- package/dist/plugins/two-factor/error-code.d.mts +20 -0
- package/dist/plugins/two-factor/error-code.mjs +19 -0
- package/dist/plugins/two-factor/index.d.mts +720 -0
- package/dist/plugins/two-factor/index.mjs +349 -0
- package/dist/plugins/two-factor/otp/index.d.mts +216 -0
- package/dist/plugins/two-factor/otp/index.mjs +252 -0
- package/dist/plugins/two-factor/schema.d.mts +59 -0
- package/dist/plugins/two-factor/schema.mjs +53 -0
- package/dist/plugins/two-factor/totp/index.d.mts +219 -0
- package/dist/plugins/two-factor/totp/index.mjs +230 -0
- package/dist/plugins/two-factor/types.d.mts +111 -0
- package/dist/plugins/two-factor/utils.mjs +9 -0
- package/dist/plugins/two-factor/verify-two-factor.mjs +205 -0
- package/dist/plugins/username/client.d.mts +38 -0
- package/dist/plugins/username/client.mjs +17 -0
- package/dist/plugins/username/error-codes.d.mts +16 -0
- package/dist/plugins/username/error-codes.mjs +15 -0
- package/dist/plugins/username/index.d.mts +326 -0
- package/dist/plugins/username/index.mjs +312 -0
- package/dist/plugins/username/schema.d.mts +50 -0
- package/dist/plugins/username/schema.mjs +25 -0
- package/dist/social-providers/index.d.mts +1 -0
- package/dist/social-providers/index.mjs +2 -0
- package/dist/state.d.mts +48 -0
- package/dist/state.mjs +149 -0
- package/dist/test-utils/headers.d.mts +8 -0
- package/dist/test-utils/headers.mjs +17 -0
- package/dist/test-utils/http-test-instance.d.mts +413 -0
- package/dist/test-utils/http-test-instance.mjs +107 -0
- package/dist/test-utils/index.d.mts +4 -0
- package/dist/test-utils/index.mjs +4 -0
- package/dist/test-utils/test-instance.d.mts +56 -0
- package/dist/test-utils/test-instance.mjs +242 -0
- package/dist/types/adapter.d.mts +2 -0
- package/dist/types/api.d.mts +28 -0
- package/dist/types/auth.d.mts +32 -0
- package/dist/types/helper.d.mts +26 -0
- package/dist/types/index.d.mts +10 -0
- package/dist/types/index.mjs +1 -0
- package/dist/types/models.d.mts +10 -0
- package/dist/types/plugins.d.mts +19 -0
- package/dist/utils/boolean.mjs +6 -0
- package/dist/utils/constants.mjs +4 -0
- package/dist/utils/date.mjs +6 -0
- package/dist/utils/hashing.mjs +18 -0
- package/dist/utils/hide-metadata.d.mts +6 -0
- package/dist/utils/hide-metadata.mjs +4 -0
- package/dist/utils/index.d.mts +4 -0
- package/dist/utils/is-api-error.d.mts +2 -0
- package/dist/utils/is-api-error.mjs +2 -0
- package/dist/utils/is-atom.mjs +6 -0
- package/dist/utils/is-promise.mjs +6 -0
- package/dist/utils/middleware-response.mjs +7 -0
- package/dist/utils/password.mjs +32 -0
- package/dist/utils/plugin-helper.mjs +14 -0
- package/dist/utils/request.mjs +23 -0
- package/dist/utils/shim.mjs +22 -0
- package/dist/utils/time.d.mts +48 -0
- package/dist/utils/time.mjs +98 -0
- package/dist/utils/url.d.mts +78 -0
- package/dist/utils/url.mjs +238 -0
- package/dist/utils/validate-user-info.mjs +44 -0
- package/dist/utils/wildcard.mjs +106 -0
- package/dist/version.mjs +5 -0
- package/package.json +595 -3
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { mergeSchema } from "../../db/schema.mjs";
|
|
2
|
+
import { sessionMiddleware } from "../../api/routes/session.mjs";
|
|
3
|
+
import { APIError as APIError$1 } from "../../api/index.mjs";
|
|
4
|
+
import { PACKAGE_VERSION } from "../../version.mjs";
|
|
5
|
+
import { getJwksAdapter } from "./adapter.mjs";
|
|
6
|
+
import { createJwk, generateExportedKeyPair, toExpJWT } from "./utils.mjs";
|
|
7
|
+
import { getJwtToken, resolveSigningKey, signJWT } from "./sign.mjs";
|
|
8
|
+
import { createCookieCacheSigner } from "./cookie-cache.mjs";
|
|
9
|
+
import { schema } from "./schema.mjs";
|
|
10
|
+
import { verifyJWT } from "./verify.mjs";
|
|
11
|
+
import { BetterAuthError } from "@better-auth/core/error";
|
|
12
|
+
import { createAuthEndpoint, createAuthMiddleware } from "@better-auth/core/api";
|
|
13
|
+
import * as z from "zod";
|
|
14
|
+
//#region src/plugins/jwt/index.ts
|
|
15
|
+
const signJWTBodySchema = z.object({
|
|
16
|
+
payload: z.record(z.string(), z.any()),
|
|
17
|
+
overrideOptions: z.record(z.string(), z.any()).optional()
|
|
18
|
+
});
|
|
19
|
+
const verifyJWTBodySchema = z.object({
|
|
20
|
+
token: z.string(),
|
|
21
|
+
issuer: z.string().optional()
|
|
22
|
+
});
|
|
23
|
+
const jwt = (options) => {
|
|
24
|
+
if (options?.jwt?.sign && !options.jwks?.remoteUrl) throw new BetterAuthError("options.jwks.remoteUrl must be set when using options.jwt.sign");
|
|
25
|
+
if (options?.jwks?.remoteUrl && !options.jwks?.keyPairConfig?.alg) throw new BetterAuthError("options.jwks.keyPairConfig.alg must be specified when options.jwks.remoteUrl is used for OpenID metadata");
|
|
26
|
+
const jwksPath = options?.jwks?.jwksPath ?? "/jwks";
|
|
27
|
+
if (typeof jwksPath !== "string" || jwksPath.length === 0 || !jwksPath.startsWith("/") || jwksPath.includes("..")) throw new BetterAuthError("options.jwks.jwksPath must be a non-empty string starting with '/' and not contain '..'");
|
|
28
|
+
return {
|
|
29
|
+
id: "jwt",
|
|
30
|
+
version: PACKAGE_VERSION,
|
|
31
|
+
options,
|
|
32
|
+
init(ctx) {
|
|
33
|
+
if (!options?.sessionCookieCache) return;
|
|
34
|
+
if (ctx.options.session?.cookieCache?.strategy !== "jwt") throw new BetterAuthError("`jwt({ sessionCookieCache: true })` requires `session.cookieCache.strategy = \"jwt\"`.");
|
|
35
|
+
if (options.jwt?.sign) throw new BetterAuthError("`jwt({ sessionCookieCache: true })` requires locally managed JWT plugin keys and does not support `jwt.sign`.");
|
|
36
|
+
const gracePeriod = options.jwks?.gracePeriod;
|
|
37
|
+
const cookieMaxAge = ctx.options.session.cookieCache.maxAge || 300;
|
|
38
|
+
if (gracePeriod !== void 0 && cookieMaxAge > gracePeriod) ctx.logger.warn(`[better-auth] \`session.cookieCache.maxAge\` (${cookieMaxAge}s) exceeds the JWT plugin JWKS grace period (${gracePeriod}s). Rotated keys may stop verifying cookie-cache JWTs before the cookie expires.`);
|
|
39
|
+
return { context: { sessionConfig: {
|
|
40
|
+
...ctx.sessionConfig,
|
|
41
|
+
cookieCacheSigner: createCookieCacheSigner(options)
|
|
42
|
+
} } };
|
|
43
|
+
},
|
|
44
|
+
endpoints: {
|
|
45
|
+
getJwks: createAuthEndpoint(jwksPath, {
|
|
46
|
+
method: "GET",
|
|
47
|
+
metadata: { openapi: {
|
|
48
|
+
operationId: "getJSONWebKeySet",
|
|
49
|
+
description: "Get the JSON Web Key Set",
|
|
50
|
+
responses: { "200": {
|
|
51
|
+
description: "JSON Web Key Set retrieved successfully",
|
|
52
|
+
content: { "application/json": { schema: {
|
|
53
|
+
type: "object",
|
|
54
|
+
properties: { keys: {
|
|
55
|
+
type: "array",
|
|
56
|
+
description: "Array of public JSON Web Keys",
|
|
57
|
+
items: {
|
|
58
|
+
type: "object",
|
|
59
|
+
properties: {
|
|
60
|
+
kid: {
|
|
61
|
+
type: "string",
|
|
62
|
+
description: "Key ID uniquely identifying the key, corresponds to the 'id' from the stored Jwk"
|
|
63
|
+
},
|
|
64
|
+
kty: {
|
|
65
|
+
type: "string",
|
|
66
|
+
description: "Key type (e.g., 'RSA', 'EC', 'OKP')"
|
|
67
|
+
},
|
|
68
|
+
alg: {
|
|
69
|
+
type: "string",
|
|
70
|
+
description: "Algorithm intended for use with the key (e.g., 'EdDSA', 'RS256')"
|
|
71
|
+
},
|
|
72
|
+
use: {
|
|
73
|
+
type: "string",
|
|
74
|
+
description: "Intended use of the public key (e.g., 'sig' for signature)",
|
|
75
|
+
enum: ["sig"],
|
|
76
|
+
nullable: true
|
|
77
|
+
},
|
|
78
|
+
n: {
|
|
79
|
+
type: "string",
|
|
80
|
+
description: "Modulus for RSA keys (base64url-encoded)",
|
|
81
|
+
nullable: true
|
|
82
|
+
},
|
|
83
|
+
e: {
|
|
84
|
+
type: "string",
|
|
85
|
+
description: "Exponent for RSA keys (base64url-encoded)",
|
|
86
|
+
nullable: true
|
|
87
|
+
},
|
|
88
|
+
crv: {
|
|
89
|
+
type: "string",
|
|
90
|
+
description: "Curve name for elliptic curve keys (e.g., 'Ed25519', 'P-256')",
|
|
91
|
+
nullable: true
|
|
92
|
+
},
|
|
93
|
+
x: {
|
|
94
|
+
type: "string",
|
|
95
|
+
description: "X coordinate for elliptic curve keys (base64url-encoded)",
|
|
96
|
+
nullable: true
|
|
97
|
+
},
|
|
98
|
+
y: {
|
|
99
|
+
type: "string",
|
|
100
|
+
description: "Y coordinate for elliptic curve keys (base64url-encoded)",
|
|
101
|
+
nullable: true
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
required: [
|
|
105
|
+
"kid",
|
|
106
|
+
"kty",
|
|
107
|
+
"alg"
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
} },
|
|
111
|
+
required: ["keys"]
|
|
112
|
+
} } }
|
|
113
|
+
} }
|
|
114
|
+
} }
|
|
115
|
+
}, async (ctx) => {
|
|
116
|
+
if (options?.jwks?.remoteUrl) throw new APIError$1("NOT_FOUND");
|
|
117
|
+
const adapter = getJwksAdapter(ctx.context.adapter, options);
|
|
118
|
+
let keySets = await adapter.getAllKeys(ctx);
|
|
119
|
+
if (!keySets || keySets?.length === 0) {
|
|
120
|
+
await createJwk(ctx, options);
|
|
121
|
+
keySets = await adapter.getAllKeys(ctx);
|
|
122
|
+
}
|
|
123
|
+
if (!keySets?.length) throw new BetterAuthError("No key sets found. Make sure you have a key in your database.");
|
|
124
|
+
const now = Date.now();
|
|
125
|
+
const gracePeriod = (options?.jwks?.gracePeriod ?? 3600 * 24 * 30) * 1e3;
|
|
126
|
+
const keys = keySets.filter((key) => {
|
|
127
|
+
if (!key.expiresAt) return true;
|
|
128
|
+
return key.expiresAt.getTime() + gracePeriod > now;
|
|
129
|
+
});
|
|
130
|
+
const keyPairConfig = options?.jwks?.keyPairConfig;
|
|
131
|
+
const defaultCrv = keyPairConfig ? "crv" in keyPairConfig ? keyPairConfig.crv : void 0 : void 0;
|
|
132
|
+
return ctx.json({ keys: keys.map((keySet) => {
|
|
133
|
+
return {
|
|
134
|
+
alg: keySet.alg ?? options?.jwks?.keyPairConfig?.alg ?? "EdDSA",
|
|
135
|
+
crv: keySet.crv ?? defaultCrv,
|
|
136
|
+
...JSON.parse(keySet.publicKey),
|
|
137
|
+
kid: keySet.id
|
|
138
|
+
};
|
|
139
|
+
}) });
|
|
140
|
+
}),
|
|
141
|
+
getToken: createAuthEndpoint("/token", {
|
|
142
|
+
method: "GET",
|
|
143
|
+
requireHeaders: true,
|
|
144
|
+
use: [sessionMiddleware],
|
|
145
|
+
metadata: { openapi: {
|
|
146
|
+
operationId: "getJSONWebToken",
|
|
147
|
+
description: "Get a JWT token",
|
|
148
|
+
responses: { 200: {
|
|
149
|
+
description: "Success",
|
|
150
|
+
content: { "application/json": { schema: {
|
|
151
|
+
type: "object",
|
|
152
|
+
properties: { token: { type: "string" } }
|
|
153
|
+
} } }
|
|
154
|
+
} }
|
|
155
|
+
} }
|
|
156
|
+
}, async (ctx) => {
|
|
157
|
+
const jwt = await getJwtToken(ctx, options);
|
|
158
|
+
return ctx.json({ token: jwt });
|
|
159
|
+
}),
|
|
160
|
+
signJWT: createAuthEndpoint.serverOnly({
|
|
161
|
+
method: "POST",
|
|
162
|
+
metadata: { $Infer: { body: {} } },
|
|
163
|
+
body: signJWTBodySchema
|
|
164
|
+
}, async (c) => {
|
|
165
|
+
const jwt = await signJWT(c, {
|
|
166
|
+
options: {
|
|
167
|
+
...options,
|
|
168
|
+
...c.body.overrideOptions
|
|
169
|
+
},
|
|
170
|
+
payload: c.body.payload
|
|
171
|
+
});
|
|
172
|
+
return c.json({ token: jwt });
|
|
173
|
+
}),
|
|
174
|
+
verifyJWT: createAuthEndpoint.serverOnly({
|
|
175
|
+
method: "POST",
|
|
176
|
+
metadata: { $Infer: {
|
|
177
|
+
body: {},
|
|
178
|
+
response: {}
|
|
179
|
+
} },
|
|
180
|
+
body: verifyJWTBodySchema
|
|
181
|
+
}, async (ctx) => {
|
|
182
|
+
const overrideOptions = ctx.body.issuer ? {
|
|
183
|
+
...options,
|
|
184
|
+
jwt: {
|
|
185
|
+
...options?.jwt,
|
|
186
|
+
issuer: ctx.body.issuer
|
|
187
|
+
}
|
|
188
|
+
} : options;
|
|
189
|
+
const payload = await verifyJWT(ctx.body.token, overrideOptions);
|
|
190
|
+
return ctx.json({ payload });
|
|
191
|
+
})
|
|
192
|
+
},
|
|
193
|
+
hooks: { after: [{
|
|
194
|
+
matcher(context) {
|
|
195
|
+
return context.path === "/get-session";
|
|
196
|
+
},
|
|
197
|
+
handler: createAuthMiddleware(async (ctx) => {
|
|
198
|
+
if (options?.disableSettingJwtHeader) return;
|
|
199
|
+
const session = ctx.context.session || ctx.context.newSession;
|
|
200
|
+
if (session && session.session) {
|
|
201
|
+
const jwt = await getJwtToken(ctx, options);
|
|
202
|
+
const exposedHeaders = ctx.context.responseHeaders?.get("access-control-expose-headers") || "";
|
|
203
|
+
const headersSet = new Set(exposedHeaders.split(",").map((header) => header.trim()).filter(Boolean));
|
|
204
|
+
headersSet.add("set-auth-jwt");
|
|
205
|
+
ctx.setHeader("set-auth-jwt", jwt);
|
|
206
|
+
ctx.setHeader("Access-Control-Expose-Headers", Array.from(headersSet).join(", "));
|
|
207
|
+
}
|
|
208
|
+
})
|
|
209
|
+
}] },
|
|
210
|
+
schema: mergeSchema(schema, options?.schema)
|
|
211
|
+
};
|
|
212
|
+
};
|
|
213
|
+
//#endregion
|
|
214
|
+
export { createJwk, generateExportedKeyPair, getJwtToken, jwt, resolveSigningKey, signJWT, toExpJWT, verifyJWT };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//#region src/plugins/jwt/schema.d.ts
|
|
2
|
+
declare const schema: {
|
|
3
|
+
jwks: {
|
|
4
|
+
fields: {
|
|
5
|
+
publicKey: {
|
|
6
|
+
type: "string";
|
|
7
|
+
required: true;
|
|
8
|
+
};
|
|
9
|
+
privateKey: {
|
|
10
|
+
type: "string";
|
|
11
|
+
required: true;
|
|
12
|
+
};
|
|
13
|
+
createdAt: {
|
|
14
|
+
type: "date";
|
|
15
|
+
required: true;
|
|
16
|
+
};
|
|
17
|
+
expiresAt: {
|
|
18
|
+
type: "date";
|
|
19
|
+
required: false;
|
|
20
|
+
};
|
|
21
|
+
alg: {
|
|
22
|
+
type: "string";
|
|
23
|
+
required: false;
|
|
24
|
+
};
|
|
25
|
+
crv: {
|
|
26
|
+
type: "string";
|
|
27
|
+
required: false;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
//#endregion
|
|
33
|
+
export { schema };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//#region src/plugins/jwt/schema.ts
|
|
2
|
+
const schema = { jwks: { fields: {
|
|
3
|
+
publicKey: {
|
|
4
|
+
type: "string",
|
|
5
|
+
required: true
|
|
6
|
+
},
|
|
7
|
+
privateKey: {
|
|
8
|
+
type: "string",
|
|
9
|
+
required: true
|
|
10
|
+
},
|
|
11
|
+
createdAt: {
|
|
12
|
+
type: "date",
|
|
13
|
+
required: true
|
|
14
|
+
},
|
|
15
|
+
expiresAt: {
|
|
16
|
+
type: "date",
|
|
17
|
+
required: false
|
|
18
|
+
},
|
|
19
|
+
alg: {
|
|
20
|
+
type: "string",
|
|
21
|
+
required: false
|
|
22
|
+
},
|
|
23
|
+
crv: {
|
|
24
|
+
type: "string",
|
|
25
|
+
required: false
|
|
26
|
+
}
|
|
27
|
+
} } };
|
|
28
|
+
//#endregion
|
|
29
|
+
export { schema };
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { JWSAlgorithms, JwtOptions, ResolvedSigningKey } from "./types.mjs";
|
|
2
|
+
import { GenericEndpointContext } from "@better-auth/core";
|
|
3
|
+
|
|
4
|
+
//#region src/plugins/jwt/sign.d.ts
|
|
5
|
+
type JWTPayloadWithOptional = {
|
|
6
|
+
/**
|
|
7
|
+
* JWT Issuer
|
|
8
|
+
*
|
|
9
|
+
* @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.1 RFC7519#section-4.1.1}
|
|
10
|
+
*/
|
|
11
|
+
iss?: string | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* JWT Subject
|
|
14
|
+
*
|
|
15
|
+
* @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.2 RFC7519#section-4.1.2}
|
|
16
|
+
*/
|
|
17
|
+
sub?: string | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* JWT Audience
|
|
20
|
+
*
|
|
21
|
+
* @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.3 RFC7519#section-4.1.3}
|
|
22
|
+
*/
|
|
23
|
+
aud?: string | string[] | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* JWT ID
|
|
26
|
+
*
|
|
27
|
+
* @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.7 RFC7519#section-4.1.7}
|
|
28
|
+
*/
|
|
29
|
+
jti?: string | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* JWT Not Before
|
|
32
|
+
*
|
|
33
|
+
* @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.5 RFC7519#section-4.1.5}
|
|
34
|
+
*/
|
|
35
|
+
nbf?: number | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* JWT Expiration Time
|
|
38
|
+
*
|
|
39
|
+
* @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.4 RFC7519#section-4.1.4}
|
|
40
|
+
*/
|
|
41
|
+
exp?: number | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* JWT Issued At
|
|
44
|
+
*
|
|
45
|
+
* @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.6 RFC7519#section-4.1.6}
|
|
46
|
+
*/
|
|
47
|
+
iat?: number | undefined; /** Any other JWT Claim Set member. */
|
|
48
|
+
[propName: string]: unknown | undefined;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Per-call signing overrides shared by `resolveSigningKey()` and `signJWT()`.
|
|
52
|
+
*
|
|
53
|
+
* Both fields are optional. When set, they shift key selection away from the
|
|
54
|
+
* default "most recently created live key" behavior:
|
|
55
|
+
*
|
|
56
|
+
* - `signingKeyId` — load the exact JWKS row whose `id` equals this value
|
|
57
|
+
* (matches the JWS `kid` header). Throws if not found; never auto-mints
|
|
58
|
+
* a replacement (admin-provisioned key is the contract).
|
|
59
|
+
* - `signingAlgorithm` — load the most recent live key with that `alg`. If
|
|
60
|
+
* none exists AND the algorithm is declared in `options.jwks.keyPairConfigs`
|
|
61
|
+
* (or equals the primary `keyPairConfig.alg`), the key is lazy-minted on
|
|
62
|
+
* demand. Otherwise throws with a descriptive error naming what IS
|
|
63
|
+
* provisioned.
|
|
64
|
+
*
|
|
65
|
+
* Used by the OAuth provider plugin to honor per-resource `signingAlgorithm` /
|
|
66
|
+
* `signingKeyId` overrides without re-implementing key resolution.
|
|
67
|
+
*/
|
|
68
|
+
interface SigningKeyOverrides {
|
|
69
|
+
signingKeyId?: string | undefined;
|
|
70
|
+
signingAlgorithm?: JWSAlgorithms | undefined;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Resolves the JWKS signing key, decrypts it, and imports it
|
|
74
|
+
* for use with jose's SignJWT. Returns null when signing is
|
|
75
|
+
* delegated to a custom jwt.sign callback.
|
|
76
|
+
*
|
|
77
|
+
* Callers that need the signing algorithm before constructing
|
|
78
|
+
* the JWT payload (e.g. for OIDC at_hash) should call this
|
|
79
|
+
* first, read `.alg`, then pass the result to `signJWT` via
|
|
80
|
+
* the `resolvedKey` option to avoid a redundant DB lookup.
|
|
81
|
+
*
|
|
82
|
+
* When `overrides.signingKeyId` or `overrides.signingAlgorithm` is set, key
|
|
83
|
+
* selection follows the contract documented on {@link SigningKeyOverrides};
|
|
84
|
+
* without overrides this returns the most recently created live key, falling
|
|
85
|
+
* back to the primary `keyPairConfig.alg` when even that's absent so unpinned
|
|
86
|
+
* tokens stay on the configured default algorithm even after extra algorithms
|
|
87
|
+
* have been lazy-minted for audience pinning.
|
|
88
|
+
*/
|
|
89
|
+
declare function resolveSigningKey(ctx: GenericEndpointContext, options?: JwtOptions, overrides?: SigningKeyOverrides): Promise<ResolvedSigningKey | null>;
|
|
90
|
+
declare function signJWT(ctx: GenericEndpointContext, config: {
|
|
91
|
+
options?: JwtOptions | undefined;
|
|
92
|
+
payload: JWTPayloadWithOptional; /** Pre-resolved key from resolveSigningKey. Skips redundant DB lookup. */
|
|
93
|
+
resolvedKey?: ResolvedSigningKey;
|
|
94
|
+
/**
|
|
95
|
+
* Extra JWS Protected Header parameters to merge with the defaults
|
|
96
|
+
* (`alg` and `kid`). Used by token profiles that require an explicit
|
|
97
|
+
* media type, such as OIDC Back-Channel Logout's `typ: "logout+jwt"`.
|
|
98
|
+
*
|
|
99
|
+
* @see https://www.rfc-editor.org/rfc/rfc8725#section-3.11
|
|
100
|
+
*/
|
|
101
|
+
header?: {
|
|
102
|
+
typ?: string;
|
|
103
|
+
cty?: string;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Optional override for the signing key. When set, looks up the key
|
|
107
|
+
* by its `id` (matches the JWS `kid` header) via the JWKS adapter.
|
|
108
|
+
* Throws if no key with that id exists.
|
|
109
|
+
*
|
|
110
|
+
* When unset, falls back to the most recently created key with the
|
|
111
|
+
* primary `keyPairConfig.alg` (the historical default).
|
|
112
|
+
*/
|
|
113
|
+
signingKeyId?: string | undefined;
|
|
114
|
+
/**
|
|
115
|
+
* Optional override for the signing algorithm. Selects the most
|
|
116
|
+
* recent key with this algorithm. When neither this nor
|
|
117
|
+
* `signingKeyId` is set, the most recent key matching
|
|
118
|
+
* `keyPairConfig.alg` is used (historical default).
|
|
119
|
+
*
|
|
120
|
+
* If both `signingKeyId` and `signingAlgorithm` are set, `signingKeyId`
|
|
121
|
+
* wins; the algorithm is validated to match the resolved key and
|
|
122
|
+
* the call throws on mismatch.
|
|
123
|
+
*/
|
|
124
|
+
signingAlgorithm?: JWSAlgorithms | undefined;
|
|
125
|
+
}): Promise<string>;
|
|
126
|
+
declare function getJwtToken(ctx: GenericEndpointContext, options?: JwtOptions | undefined): Promise<string>;
|
|
127
|
+
//#endregion
|
|
128
|
+
export { getJwtToken, resolveSigningKey, signJWT };
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { symmetricDecrypt } from "../../crypto/index.mjs";
|
|
2
|
+
import { getJwksAdapter } from "./adapter.mjs";
|
|
3
|
+
import { createJwk, toExpJWT } from "./utils.mjs";
|
|
4
|
+
import { BetterAuthError } from "@better-auth/core/error";
|
|
5
|
+
import { SignJWT, importJWK } from "jose";
|
|
6
|
+
//#region src/plugins/jwt/sign.ts
|
|
7
|
+
/**
|
|
8
|
+
* Resolves the JWKS signing key, decrypts it, and imports it
|
|
9
|
+
* for use with jose's SignJWT. Returns null when signing is
|
|
10
|
+
* delegated to a custom jwt.sign callback.
|
|
11
|
+
*
|
|
12
|
+
* Callers that need the signing algorithm before constructing
|
|
13
|
+
* the JWT payload (e.g. for OIDC at_hash) should call this
|
|
14
|
+
* first, read `.alg`, then pass the result to `signJWT` via
|
|
15
|
+
* the `resolvedKey` option to avoid a redundant DB lookup.
|
|
16
|
+
*
|
|
17
|
+
* When `overrides.signingKeyId` or `overrides.signingAlgorithm` is set, key
|
|
18
|
+
* selection follows the contract documented on {@link SigningKeyOverrides};
|
|
19
|
+
* without overrides this returns the most recently created live key, falling
|
|
20
|
+
* back to the primary `keyPairConfig.alg` when even that's absent so unpinned
|
|
21
|
+
* tokens stay on the configured default algorithm even after extra algorithms
|
|
22
|
+
* have been lazy-minted for audience pinning.
|
|
23
|
+
*/
|
|
24
|
+
async function resolveSigningKey(ctx, options, overrides) {
|
|
25
|
+
if (options?.jwt?.sign) return null;
|
|
26
|
+
const adapter = getJwksAdapter(ctx.context.adapter, options);
|
|
27
|
+
let key;
|
|
28
|
+
if (overrides?.signingKeyId !== void 0) {
|
|
29
|
+
key = await adapter.getKeyById(ctx, overrides.signingKeyId);
|
|
30
|
+
if (!key) throw new BetterAuthError(`signJWT: signingKeyId "${overrides.signingKeyId}" not found in JWKS. The key must be provisioned before it can be referenced.`);
|
|
31
|
+
if (overrides.signingAlgorithm !== void 0) {
|
|
32
|
+
const configAlg = options?.jwks?.keyPairConfig?.alg ?? "EdDSA";
|
|
33
|
+
if ((key.alg ?? configAlg) !== overrides.signingAlgorithm) throw new BetterAuthError(`signJWT: signingKeyId "${overrides.signingKeyId}" has alg "${key.alg ?? `unset (inherits keyPairConfig.alg "${configAlg}")`}" but signingAlgorithm was set to "${overrides.signingAlgorithm}".`);
|
|
34
|
+
}
|
|
35
|
+
} else if (overrides?.signingAlgorithm !== void 0) {
|
|
36
|
+
key = await adapter.getLatestKeyByAlg(ctx, overrides.signingAlgorithm);
|
|
37
|
+
if (!key) {
|
|
38
|
+
const primaryAlg = options?.jwks?.keyPairConfig?.alg ?? "EdDSA";
|
|
39
|
+
const preconfig = options?.jwks?.keyPairConfigs?.find((c) => c.alg === overrides.signingAlgorithm);
|
|
40
|
+
const isPrimary = primaryAlg === overrides.signingAlgorithm;
|
|
41
|
+
if (preconfig || isPrimary) key = await createJwk(ctx, {
|
|
42
|
+
...options,
|
|
43
|
+
jwks: {
|
|
44
|
+
...options?.jwks,
|
|
45
|
+
keyPairConfig: preconfig ?? options?.jwks?.keyPairConfig
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
else {
|
|
49
|
+
const advertisedExtra = options?.jwks?.keyPairConfigs?.map((c) => c.alg).join(", ") || "none";
|
|
50
|
+
throw new BetterAuthError(`signJWT: no key with alg "${overrides.signingAlgorithm}" found in JWKS. The plugin auto-mints only one key matching keyPairConfig.alg="${primaryAlg}"; additional algs configured via keyPairConfigs: ${advertisedExtra}. Add "${overrides.signingAlgorithm}" to jwks.keyPairConfigs so the plugin provisions it on first use, or mint the key explicitly via createJwk().`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
const primaryAlg = options?.jwks?.keyPairConfig?.alg ?? "EdDSA";
|
|
55
|
+
key = await adapter.getLatestKeyByAlg(ctx, primaryAlg) ?? await adapter.getLatestKey(ctx);
|
|
56
|
+
}
|
|
57
|
+
if (!key || key.expiresAt && key.expiresAt < /* @__PURE__ */ new Date()) {
|
|
58
|
+
if (overrides?.signingKeyId !== void 0 || overrides?.signingAlgorithm !== void 0) throw new BetterAuthError("signJWT: requested signing key is expired and an explicit kid/alg was provided; not auto-minting a replacement. Rotate the key explicitly.");
|
|
59
|
+
key = await createJwk(ctx, options);
|
|
60
|
+
}
|
|
61
|
+
const privateWebKey = !options?.jwks?.disablePrivateKeyEncryption ? await symmetricDecrypt({
|
|
62
|
+
key: ctx.context.secretConfig,
|
|
63
|
+
data: JSON.parse(key.privateKey)
|
|
64
|
+
}).catch(() => {
|
|
65
|
+
throw new BetterAuthError("Failed to decrypt private key. Make sure the secret currently in use is the same as the one used to encrypt the private key. If you are using a different secret, either clean up your JWKS or disable private key encryption.");
|
|
66
|
+
}) : key.privateKey;
|
|
67
|
+
const alg = key.alg ?? options?.jwks?.keyPairConfig?.alg ?? "EdDSA";
|
|
68
|
+
const privateKey = await importJWK(JSON.parse(privateWebKey), alg);
|
|
69
|
+
return {
|
|
70
|
+
alg,
|
|
71
|
+
kid: key.id,
|
|
72
|
+
privateKey
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
async function signJWT(ctx, config) {
|
|
76
|
+
const { options } = config;
|
|
77
|
+
const payload = config.payload;
|
|
78
|
+
const nowSeconds = Math.floor(Date.now() / 1e3);
|
|
79
|
+
const iat = payload.iat;
|
|
80
|
+
let exp = payload.exp;
|
|
81
|
+
const defaultExp = toExpJWT(options?.jwt?.expirationTime ?? "15m", iat ?? nowSeconds);
|
|
82
|
+
exp = exp ?? defaultExp;
|
|
83
|
+
const nbf = payload.nbf;
|
|
84
|
+
const baseURLOrigin = typeof ctx.context.options.baseURL === "string" ? ctx.context.options.baseURL : "";
|
|
85
|
+
const iss = payload.iss;
|
|
86
|
+
const defaultIss = options?.jwt?.issuer ?? baseURLOrigin;
|
|
87
|
+
const aud = payload.aud;
|
|
88
|
+
const defaultAud = options?.jwt?.audience ?? baseURLOrigin;
|
|
89
|
+
if (options?.jwt?.sign) {
|
|
90
|
+
const jwtPayload = {
|
|
91
|
+
...payload,
|
|
92
|
+
iat,
|
|
93
|
+
exp,
|
|
94
|
+
nbf,
|
|
95
|
+
iss: iss ?? defaultIss,
|
|
96
|
+
aud: aud ?? defaultAud
|
|
97
|
+
};
|
|
98
|
+
return options.jwt.sign(jwtPayload, config.header, {
|
|
99
|
+
signingKeyId: config.signingKeyId,
|
|
100
|
+
signingAlgorithm: config.signingAlgorithm
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
const { alg, kid, privateKey } = config.resolvedKey ?? await resolveSigningKey(ctx, options, {
|
|
104
|
+
signingKeyId: config.signingKeyId,
|
|
105
|
+
signingAlgorithm: config.signingAlgorithm
|
|
106
|
+
});
|
|
107
|
+
const jwt = new SignJWT(payload).setProtectedHeader({
|
|
108
|
+
...config.header,
|
|
109
|
+
alg,
|
|
110
|
+
kid
|
|
111
|
+
}).setExpirationTime(exp).setIssuer(iss ?? defaultIss).setAudience(aud ?? defaultAud);
|
|
112
|
+
if (iat) jwt.setIssuedAt(iat);
|
|
113
|
+
if (payload.sub) jwt.setSubject(payload.sub);
|
|
114
|
+
if (payload.nbf) jwt.setNotBefore(payload.nbf);
|
|
115
|
+
if (payload.jti) jwt.setJti(payload.jti);
|
|
116
|
+
return await jwt.sign(privateKey);
|
|
117
|
+
}
|
|
118
|
+
async function getJwtToken(ctx, options) {
|
|
119
|
+
const payload = !options?.jwt?.definePayload ? ctx.context.session.user : await options.jwt.definePayload(ctx.context.session);
|
|
120
|
+
return await signJWT(ctx, {
|
|
121
|
+
options,
|
|
122
|
+
payload: {
|
|
123
|
+
iat: Math.floor(Date.now() / 1e3),
|
|
124
|
+
...payload,
|
|
125
|
+
sub: await options?.jwt?.getSubject?.(ctx.context.session) ?? ctx.context.session.user.id
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
//#endregion
|
|
130
|
+
export { getJwtToken, resolveSigningKey, signJWT };
|