@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,235 @@
|
|
|
1
|
+
import { getBaseURL, isDynamicBaseURLConfig } from "../utils/url.mjs";
|
|
2
|
+
import { matchesOriginPattern } from "../auth/trusted-origins.mjs";
|
|
3
|
+
import { hasServerSessionStore } from "./store-capabilities.mjs";
|
|
4
|
+
import { isPromise } from "../utils/is-promise.mjs";
|
|
5
|
+
import { hashPassword, verifyPassword } from "../crypto/password.mjs";
|
|
6
|
+
import { createCookieGetter, getCookies } from "../cookies/index.mjs";
|
|
7
|
+
import { createInternalAdapter } from "../db/internal-adapter.mjs";
|
|
8
|
+
import { getInternalPlugins, getTrustedOrigins, getTrustedProviders, runPluginInit } from "./helpers.mjs";
|
|
9
|
+
import { checkPassword } from "../utils/password.mjs";
|
|
10
|
+
import { checkEndpointConflicts } from "../api/index.mjs";
|
|
11
|
+
import { DEFAULT_SECRET } from "../utils/constants.mjs";
|
|
12
|
+
import { buildSecretConfig, parseSecretsEnv, validateSecretsArray } from "./secret-utils.mjs";
|
|
13
|
+
import { getBetterAuthVersion } from "@better-auth/core/context";
|
|
14
|
+
import { getAuthTables } from "@better-auth/core/db";
|
|
15
|
+
import { createLogger, env, isProduction, isTest } from "@better-auth/core/env";
|
|
16
|
+
import { BetterAuthError } from "@better-auth/core/error";
|
|
17
|
+
import { generateId } from "@better-auth/core/utils/id";
|
|
18
|
+
import { schemaCheckFor } from "@better-auth/core/db/internal";
|
|
19
|
+
import { socialProviders } from "@better-auth/core/social-providers";
|
|
20
|
+
import { findInvalidTrustedProxies } from "@better-auth/core/utils/ip";
|
|
21
|
+
import { createTelemetry } from "@better-auth/telemetry";
|
|
22
|
+
import defu$1 from "defu";
|
|
23
|
+
//#region src/context/create-context.ts
|
|
24
|
+
/**
|
|
25
|
+
* Estimates the entropy of a string in bits.
|
|
26
|
+
* This is a simple approximation that helps detect low-entropy secrets.
|
|
27
|
+
*/
|
|
28
|
+
function estimateEntropy(str) {
|
|
29
|
+
const unique = new Set(str).size;
|
|
30
|
+
if (unique === 0) return 0;
|
|
31
|
+
return Math.log2(Math.pow(unique, str.length));
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Validates that the secret meets minimum security requirements.
|
|
35
|
+
* Throws BetterAuthError if the secret is invalid.
|
|
36
|
+
* Skips validation for DEFAULT_SECRET in test environments only.
|
|
37
|
+
* Only throws for DEFAULT_SECRET in production environment.
|
|
38
|
+
*/
|
|
39
|
+
function validateSecret(secret, logger) {
|
|
40
|
+
const isDefaultSecret = secret === DEFAULT_SECRET;
|
|
41
|
+
if (isTest()) return;
|
|
42
|
+
if (isDefaultSecret && isProduction) throw new BetterAuthError("You are using the default secret. Please set `BETTER_AUTH_SECRET` in your environment variables or pass `secret` in your auth config.");
|
|
43
|
+
if (!secret) throw new BetterAuthError("BETTER_AUTH_SECRET is missing. Set it in your environment or pass `secret` to betterAuth({ secret }).");
|
|
44
|
+
if (secret.length < 32) logger.warn(`[better-auth] Warning: your BETTER_AUTH_SECRET should be at least 32 characters long for adequate security. Generate one with \`npx auth secret\` or \`openssl rand -base64 32\`.`);
|
|
45
|
+
if (estimateEntropy(secret) < 120) logger.warn("[better-auth] Warning: your BETTER_AUTH_SECRET appears low-entropy. Use a randomly generated secret for production.");
|
|
46
|
+
}
|
|
47
|
+
async function createAuthContext(adapter, options, getDatabaseType) {
|
|
48
|
+
const isStateful = hasServerSessionStore(options);
|
|
49
|
+
if (!isStateful) options = defu$1(options, { session: { cookieCache: {
|
|
50
|
+
enabled: true,
|
|
51
|
+
strategy: "jwe",
|
|
52
|
+
refreshCache: true,
|
|
53
|
+
maxAge: options.session?.expiresIn || 3600 * 24 * 7
|
|
54
|
+
} } });
|
|
55
|
+
if (!options.database) options = defu$1(options, { account: { storeAccountCookie: true } });
|
|
56
|
+
const plugins = options.plugins || [];
|
|
57
|
+
const internalPlugins = getInternalPlugins(options);
|
|
58
|
+
const logger = createLogger(options.logger);
|
|
59
|
+
const isDynamicConfig = isDynamicBaseURLConfig(options.baseURL);
|
|
60
|
+
if (isDynamicBaseURLConfig(options.baseURL)) {
|
|
61
|
+
const { allowedHosts } = options.baseURL;
|
|
62
|
+
if (!allowedHosts || allowedHosts.length === 0) throw new BetterAuthError("baseURL.allowedHosts cannot be empty. Provide at least one allowed host pattern (e.g., [\"myapp.com\", \"*.vercel.app\"]).");
|
|
63
|
+
}
|
|
64
|
+
const baseURL = isDynamicConfig ? void 0 : getBaseURL(typeof options.baseURL === "string" ? options.baseURL : void 0, options.basePath);
|
|
65
|
+
if (!baseURL && !isDynamicConfig) logger.warn(`[better-auth] Base URL is not set. Set the baseURL option or BETTER_AUTH_URL env, or use a dynamic baseURL with allowedHosts for multi-host setups. Without it the origin is derived from the incoming request, and callbacks and redirects may not work correctly.`);
|
|
66
|
+
if (adapter.id === "memory" && options.advanced?.database?.generateId === false) logger.error(`[better-auth] Misconfiguration detected.
|
|
67
|
+
You are using the memory DB with generateId: false.
|
|
68
|
+
This will cause no id to be generated for any model.
|
|
69
|
+
Most of the features of Better Auth will not work correctly.`);
|
|
70
|
+
const secretsArray = options.secrets ?? parseSecretsEnv(env.BETTER_AUTH_SECRETS);
|
|
71
|
+
const legacySecret = options.secret || env.BETTER_AUTH_SECRET || env.AUTH_SECRET || "";
|
|
72
|
+
let secret;
|
|
73
|
+
let secretConfig;
|
|
74
|
+
if (secretsArray) {
|
|
75
|
+
validateSecretsArray(secretsArray, logger);
|
|
76
|
+
secret = secretsArray[0].value;
|
|
77
|
+
secretConfig = buildSecretConfig(secretsArray, legacySecret);
|
|
78
|
+
} else {
|
|
79
|
+
secret = legacySecret || "better-auth-secret-12345678901234567890";
|
|
80
|
+
validateSecret(secret, logger);
|
|
81
|
+
secretConfig = secret;
|
|
82
|
+
}
|
|
83
|
+
options = {
|
|
84
|
+
...options,
|
|
85
|
+
secret,
|
|
86
|
+
baseURL: isDynamicConfig ? options.baseURL : baseURL ? new URL(baseURL).origin : "",
|
|
87
|
+
basePath: options.basePath || "/api/auth",
|
|
88
|
+
plugins: plugins.concat(internalPlugins)
|
|
89
|
+
};
|
|
90
|
+
checkEndpointConflicts(options, logger);
|
|
91
|
+
const trustedProxies = options.advanced?.ipAddress?.trustedProxies;
|
|
92
|
+
if (trustedProxies && trustedProxies.length > 0) {
|
|
93
|
+
const invalid = findInvalidTrustedProxies(trustedProxies);
|
|
94
|
+
if (invalid.length > 0) logger.warn(`Ignoring invalid \`advanced.ipAddress.trustedProxies\` entries: ${invalid.join(", ")}. Each entry must be an IP address or CIDR range.`);
|
|
95
|
+
}
|
|
96
|
+
const cookies = getCookies(options);
|
|
97
|
+
const tables = getAuthTables(options);
|
|
98
|
+
const providers = (await Promise.all(Object.entries(options.socialProviders || {}).map(async ([key, originalConfig]) => {
|
|
99
|
+
const config = typeof originalConfig === "function" ? await originalConfig() : originalConfig;
|
|
100
|
+
if (config == null) return null;
|
|
101
|
+
if (config.enabled === false) return null;
|
|
102
|
+
if (!config.clientId) logger.warn(`Social provider ${key} is missing clientId or clientSecret`);
|
|
103
|
+
const provider = socialProviders[key](config);
|
|
104
|
+
provider.disableImplicitSignUp = config.disableImplicitSignUp;
|
|
105
|
+
return provider;
|
|
106
|
+
}))).filter((x) => x !== null);
|
|
107
|
+
const generateIdFunc = ({ model, size }) => {
|
|
108
|
+
if (typeof options.advanced?.generateId === "function") return options.advanced.generateId({
|
|
109
|
+
model,
|
|
110
|
+
size
|
|
111
|
+
});
|
|
112
|
+
const dbGenerateId = options?.advanced?.database?.generateId;
|
|
113
|
+
if (typeof dbGenerateId === "function") return dbGenerateId({
|
|
114
|
+
model,
|
|
115
|
+
size
|
|
116
|
+
});
|
|
117
|
+
if (dbGenerateId === "uuid") return crypto.randomUUID();
|
|
118
|
+
if (dbGenerateId === "serial" || dbGenerateId === false) return false;
|
|
119
|
+
return generateId(size);
|
|
120
|
+
};
|
|
121
|
+
const { publish } = await createTelemetry(options, {
|
|
122
|
+
adapter: adapter.id,
|
|
123
|
+
database: typeof options.database === "function" ? "adapter" : getDatabaseType(options.database)
|
|
124
|
+
});
|
|
125
|
+
const pluginIds = new Set(options.plugins.map((p) => p.id));
|
|
126
|
+
const getPluginFn = (id) => options.plugins.find((p) => p.id === id) ?? null;
|
|
127
|
+
const hasPluginFn = (id) => pluginIds.has(id);
|
|
128
|
+
const trustedOrigins = await getTrustedOrigins(options);
|
|
129
|
+
const trustedProviders = await getTrustedProviders(options);
|
|
130
|
+
const ctx = {
|
|
131
|
+
appName: options.appName || "Better Auth",
|
|
132
|
+
baseURL: baseURL || "",
|
|
133
|
+
version: getBetterAuthVersion(),
|
|
134
|
+
socialProviders: providers,
|
|
135
|
+
options,
|
|
136
|
+
oauthConfig: {
|
|
137
|
+
storeStateStrategy: options.account?.storeStateStrategy || (isStateful ? "database" : "cookie"),
|
|
138
|
+
skipStateCookieCheck: !!options.account?.skipStateCookieCheck
|
|
139
|
+
},
|
|
140
|
+
tables,
|
|
141
|
+
trustedOrigins,
|
|
142
|
+
trustedProviders,
|
|
143
|
+
isTrustedOrigin(url, settings) {
|
|
144
|
+
return this.trustedOrigins.some((origin) => matchesOriginPattern(url, origin, settings));
|
|
145
|
+
},
|
|
146
|
+
sessionConfig: {
|
|
147
|
+
updateAge: options.session?.updateAge !== void 0 ? options.session.updateAge : 1440 * 60,
|
|
148
|
+
expiresIn: options.session?.expiresIn || 3600 * 24 * 7,
|
|
149
|
+
freshAge: options.session?.freshAge === void 0 ? 3600 * 24 : options.session.freshAge,
|
|
150
|
+
cookieRefreshCache: (() => {
|
|
151
|
+
const refreshCache = options.session?.cookieCache?.refreshCache;
|
|
152
|
+
const maxAge = options.session?.cookieCache?.maxAge || 300;
|
|
153
|
+
if (isStateful && refreshCache) {
|
|
154
|
+
logger.warn("[better-auth] `session.cookieCache.refreshCache` is enabled while `database` or `secondaryStorage` is configured. `refreshCache` is meant for stateless (DB-less) setups. Disabling `refreshCache` — remove it from your config to silence this warning.");
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
if (refreshCache === false || refreshCache === void 0) return false;
|
|
158
|
+
if (refreshCache === true) return {
|
|
159
|
+
enabled: true,
|
|
160
|
+
updateAge: Math.floor(maxAge * .2)
|
|
161
|
+
};
|
|
162
|
+
return {
|
|
163
|
+
enabled: true,
|
|
164
|
+
updateAge: refreshCache.updateAge !== void 0 ? refreshCache.updateAge : Math.floor(maxAge * .2)
|
|
165
|
+
};
|
|
166
|
+
})()
|
|
167
|
+
},
|
|
168
|
+
secret,
|
|
169
|
+
secretConfig,
|
|
170
|
+
rateLimit: {
|
|
171
|
+
...options.rateLimit,
|
|
172
|
+
enabled: options.rateLimit?.enabled ?? isProduction,
|
|
173
|
+
window: options.rateLimit?.window || 10,
|
|
174
|
+
max: options.rateLimit?.max || 100,
|
|
175
|
+
storage: options.rateLimit?.storage || (options.secondaryStorage ? "secondary-storage" : "memory")
|
|
176
|
+
},
|
|
177
|
+
authCookies: cookies,
|
|
178
|
+
logger,
|
|
179
|
+
generateId: generateIdFunc,
|
|
180
|
+
session: null,
|
|
181
|
+
secondaryStorage: options.secondaryStorage,
|
|
182
|
+
password: {
|
|
183
|
+
hash: options.emailAndPassword?.password?.hash || hashPassword,
|
|
184
|
+
verify: options.emailAndPassword?.password?.verify || verifyPassword,
|
|
185
|
+
config: {
|
|
186
|
+
minPasswordLength: options.emailAndPassword?.minPasswordLength || 8,
|
|
187
|
+
maxPasswordLength: options.emailAndPassword?.maxPasswordLength || 128
|
|
188
|
+
},
|
|
189
|
+
checkPassword
|
|
190
|
+
},
|
|
191
|
+
setNewSession(session) {
|
|
192
|
+
this.newSession = session;
|
|
193
|
+
},
|
|
194
|
+
newSession: null,
|
|
195
|
+
adapter,
|
|
196
|
+
internalAdapter: createInternalAdapter(adapter, {
|
|
197
|
+
options,
|
|
198
|
+
logger,
|
|
199
|
+
hooks: options.databaseHooks ? [{
|
|
200
|
+
source: "user",
|
|
201
|
+
hooks: options.databaseHooks
|
|
202
|
+
}] : [],
|
|
203
|
+
generateId: generateIdFunc
|
|
204
|
+
}),
|
|
205
|
+
createAuthCookie: createCookieGetter(options),
|
|
206
|
+
async runMigrations() {
|
|
207
|
+
throw new BetterAuthError("runMigrations will be set by the specific init implementation");
|
|
208
|
+
},
|
|
209
|
+
publishTelemetry: publish,
|
|
210
|
+
skipCSRFCheck: !!options.advanced?.disableCSRFCheck,
|
|
211
|
+
skipOriginCheck: options.advanced?.disableOriginCheck !== void 0 ? options.advanced.disableOriginCheck : isTest() ? true : false,
|
|
212
|
+
runInBackground: options.advanced?.backgroundTasks?.handler ?? ((p) => {
|
|
213
|
+
p.catch(() => {});
|
|
214
|
+
}),
|
|
215
|
+
async runInBackgroundOrAwait(promise) {
|
|
216
|
+
try {
|
|
217
|
+
if (options.advanced?.backgroundTasks?.handler) {
|
|
218
|
+
if (promise instanceof Promise) options.advanced.backgroundTasks.handler(promise.catch((e) => {
|
|
219
|
+
logger.error("Failed to run background task:", e);
|
|
220
|
+
}));
|
|
221
|
+
} else await promise;
|
|
222
|
+
} catch (e) {
|
|
223
|
+
logger.error("Failed to run background task:", e);
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
getPlugin: getPluginFn,
|
|
227
|
+
hasPlugin: hasPluginFn
|
|
228
|
+
};
|
|
229
|
+
const initOrPromise = runPluginInit(ctx);
|
|
230
|
+
if (isPromise(initOrPromise)) await initOrPromise;
|
|
231
|
+
ctx.checkSchema = schemaCheckFor(ctx.adapter);
|
|
232
|
+
return ctx;
|
|
233
|
+
}
|
|
234
|
+
//#endregion
|
|
235
|
+
export { createAuthContext };
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { getBaseURL, getOrigin, isDynamicBaseURLConfig, isRequestLike, resolveBaseURL } from "../utils/url.mjs";
|
|
2
|
+
import { isPromise } from "../utils/is-promise.mjs";
|
|
3
|
+
import { createCookieGetter, getCookies } from "../cookies/index.mjs";
|
|
4
|
+
import { createInternalAdapter } from "../db/internal-adapter.mjs";
|
|
5
|
+
import { env } from "@better-auth/core/env";
|
|
6
|
+
import { BetterAuthError } from "@better-auth/core/error";
|
|
7
|
+
import { defu } from "defu";
|
|
8
|
+
import { isLoopbackHost } from "@better-auth/core/utils/host";
|
|
9
|
+
//#region src/context/helpers.ts
|
|
10
|
+
async function runPluginInit(context) {
|
|
11
|
+
let options = context.options;
|
|
12
|
+
const plugins = options.plugins || [];
|
|
13
|
+
const pluginTrustedOrigins = [];
|
|
14
|
+
const dbHooks = [];
|
|
15
|
+
for (const plugin of plugins) if (plugin.init) {
|
|
16
|
+
const initPromise = plugin.init(context);
|
|
17
|
+
let result;
|
|
18
|
+
if (isPromise(initPromise)) result = await initPromise;
|
|
19
|
+
else result = initPromise;
|
|
20
|
+
if (typeof result === "object") {
|
|
21
|
+
if (result.options) {
|
|
22
|
+
const { databaseHooks, trustedOrigins, ...restOpts } = result.options;
|
|
23
|
+
if (databaseHooks) dbHooks.push({
|
|
24
|
+
source: `plugin:${plugin.id}`,
|
|
25
|
+
hooks: databaseHooks
|
|
26
|
+
});
|
|
27
|
+
if (trustedOrigins) pluginTrustedOrigins.push(trustedOrigins);
|
|
28
|
+
options = defu(options, restOpts);
|
|
29
|
+
}
|
|
30
|
+
if (result.context) Object.assign(context, result.context);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (pluginTrustedOrigins.length > 0) {
|
|
34
|
+
const allSources = [...options.trustedOrigins ? [options.trustedOrigins] : [], ...pluginTrustedOrigins];
|
|
35
|
+
const staticOrigins = allSources.filter(Array.isArray).flat();
|
|
36
|
+
const dynamicOrigins = allSources.filter((s) => typeof s === "function");
|
|
37
|
+
if (dynamicOrigins.length > 0) options.trustedOrigins = async (request) => {
|
|
38
|
+
const resolved = await Promise.all(dynamicOrigins.map((fn) => fn(request)));
|
|
39
|
+
return [...staticOrigins, ...resolved.flat()].filter((v) => typeof v === "string" && v !== "");
|
|
40
|
+
};
|
|
41
|
+
else options.trustedOrigins = staticOrigins;
|
|
42
|
+
}
|
|
43
|
+
if (options.databaseHooks) dbHooks.push({
|
|
44
|
+
source: "user",
|
|
45
|
+
hooks: options.databaseHooks
|
|
46
|
+
});
|
|
47
|
+
context.internalAdapter = createInternalAdapter(context.adapter, {
|
|
48
|
+
options,
|
|
49
|
+
logger: context.logger,
|
|
50
|
+
hooks: dbHooks,
|
|
51
|
+
generateId: context.generateId
|
|
52
|
+
});
|
|
53
|
+
context.options = options;
|
|
54
|
+
}
|
|
55
|
+
function getInternalPlugins(options) {
|
|
56
|
+
const plugins = [];
|
|
57
|
+
if (options.advanced?.crossSubDomainCookies?.enabled) {}
|
|
58
|
+
return plugins;
|
|
59
|
+
}
|
|
60
|
+
async function getTrustedOrigins(options, request) {
|
|
61
|
+
const trustedOrigins = [];
|
|
62
|
+
if (isDynamicBaseURLConfig(options.baseURL)) {
|
|
63
|
+
const allowedHosts = options.baseURL.allowedHosts;
|
|
64
|
+
const proto = options.baseURL.protocol;
|
|
65
|
+
for (const host of allowedHosts) if (!host.includes("://")) {
|
|
66
|
+
if (!proto || proto === "https" || proto === "auto") trustedOrigins.push(`https://${host}`);
|
|
67
|
+
if (proto === "http" || proto === "auto" || isLoopbackHost(host)) trustedOrigins.push(`http://${host}`);
|
|
68
|
+
} else trustedOrigins.push(host);
|
|
69
|
+
if (options.baseURL.fallback) try {
|
|
70
|
+
trustedOrigins.push(new URL(options.baseURL.fallback).origin);
|
|
71
|
+
} catch {}
|
|
72
|
+
} else {
|
|
73
|
+
const baseURL = getBaseURL(typeof options.baseURL === "string" ? options.baseURL : void 0, options.basePath, request);
|
|
74
|
+
if (baseURL) trustedOrigins.push(new URL(baseURL).origin);
|
|
75
|
+
}
|
|
76
|
+
if (options.trustedOrigins) {
|
|
77
|
+
if (Array.isArray(options.trustedOrigins)) trustedOrigins.push(...options.trustedOrigins);
|
|
78
|
+
if (typeof options.trustedOrigins === "function") {
|
|
79
|
+
const validOrigins = await options.trustedOrigins(request);
|
|
80
|
+
trustedOrigins.push(...validOrigins);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const envTrustedOrigins = env.BETTER_AUTH_TRUSTED_ORIGINS;
|
|
84
|
+
if (envTrustedOrigins) trustedOrigins.push(...envTrustedOrigins.split(","));
|
|
85
|
+
return trustedOrigins.filter((v) => Boolean(v));
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Picks a `Request`-like or `Headers` value from a direct `auth.api` call.
|
|
89
|
+
* Headers are only accepted when they carry a host: without one, host
|
|
90
|
+
* resolution would fall back to `null` and the caller should use `fallback`
|
|
91
|
+
* or pass a `Request` instead.
|
|
92
|
+
*/
|
|
93
|
+
function pickSource(input) {
|
|
94
|
+
if (isRequestLike(input?.request)) return input.request;
|
|
95
|
+
if (!input?.headers) return void 0;
|
|
96
|
+
const headers = input.headers instanceof Headers ? input.headers : new Headers(input.headers);
|
|
97
|
+
if (!headers.has("host") && !headers.has("x-forwarded-host")) return;
|
|
98
|
+
return headers;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Returns the effective `trustedProxyHeaders` value for dynamic `baseURL`
|
|
102
|
+
* resolution. Proxy headers (`x-forwarded-host` / `x-forwarded-proto`) are
|
|
103
|
+
* ignored unless the user opts in with `advanced.trustedProxyHeaders: true`,
|
|
104
|
+
* matching the static-config path. Deployments behind a reverse proxy that
|
|
105
|
+
* only exposes the public host via `x-forwarded-host` must set the flag.
|
|
106
|
+
*/
|
|
107
|
+
function resolveDynamicTrustedProxyHeaders(options) {
|
|
108
|
+
return options.advanced?.trustedProxyHeaders ?? false;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Per-request clone with `baseURL`, `trustedOrigins`, `trustedProviders`
|
|
112
|
+
* and cookies rehydrated for the resolved host. Throws `BetterAuthError`
|
|
113
|
+
* when the URL cannot be resolved; callers on the direct-API path convert
|
|
114
|
+
* this to `APIError`.
|
|
115
|
+
*/
|
|
116
|
+
async function resolveRequestContext(ctx, source, trustedProxyHeaders) {
|
|
117
|
+
const dynamicBaseURLConfig = ctx.options.baseURL;
|
|
118
|
+
const baseURL = resolveBaseURL(dynamicBaseURLConfig, ctx.options.basePath || "/api/auth", source, void 0, trustedProxyHeaders);
|
|
119
|
+
if (!baseURL) throw new BetterAuthError("Could not resolve base URL from request. Check your allowedHosts config.");
|
|
120
|
+
const resolved = Object.create(Object.getPrototypeOf(ctx), Object.getOwnPropertyDescriptors(ctx));
|
|
121
|
+
resolved.baseURL = baseURL;
|
|
122
|
+
resolved.options = {
|
|
123
|
+
...ctx.options,
|
|
124
|
+
baseURL: getOrigin(baseURL) || void 0
|
|
125
|
+
};
|
|
126
|
+
const trustedOriginOptions = {
|
|
127
|
+
...resolved.options,
|
|
128
|
+
baseURL: dynamicBaseURLConfig
|
|
129
|
+
};
|
|
130
|
+
const needsRequest = typeof ctx.options.trustedOrigins === "function" || typeof ctx.options.account?.accountLinking?.trustedProviders === "function";
|
|
131
|
+
let callbackRequest;
|
|
132
|
+
if (needsRequest) if (isRequestLike(source)) callbackRequest = source;
|
|
133
|
+
else if (source) callbackRequest = new Request(baseURL, { headers: source });
|
|
134
|
+
else callbackRequest = void 0;
|
|
135
|
+
else callbackRequest = void 0;
|
|
136
|
+
resolved.trustedOrigins = await getTrustedOrigins(trustedOriginOptions, callbackRequest);
|
|
137
|
+
resolved.trustedProviders = await getTrustedProviders(resolved.options, callbackRequest);
|
|
138
|
+
if (ctx.options.advanced?.crossSubDomainCookies?.enabled) {
|
|
139
|
+
resolved.authCookies = getCookies(resolved.options);
|
|
140
|
+
resolved.createAuthCookie = createCookieGetter(resolved.options);
|
|
141
|
+
}
|
|
142
|
+
return resolved;
|
|
143
|
+
}
|
|
144
|
+
async function getAwaitableValue(arr, item) {
|
|
145
|
+
if (!arr) return void 0;
|
|
146
|
+
for (const val of arr) {
|
|
147
|
+
const value = typeof val === "function" ? await val() : val;
|
|
148
|
+
if (value[item.field ?? "id"] === item.value) return value;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
async function getTrustedProviders(options, request) {
|
|
152
|
+
const trustedProviders = options.account?.accountLinking?.trustedProviders;
|
|
153
|
+
if (!trustedProviders) return [];
|
|
154
|
+
if (Array.isArray(trustedProviders)) return trustedProviders.filter((v) => Boolean(v));
|
|
155
|
+
return (await trustedProviders(request) ?? []).filter((v) => Boolean(v));
|
|
156
|
+
}
|
|
157
|
+
//#endregion
|
|
158
|
+
export { getAwaitableValue, getInternalPlugins, getTrustedOrigins, getTrustedProviders, pickSource, resolveDynamicTrustedProxyHeaders, resolveRequestContext, runPluginInit };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { getBaseAdapter } from "../db/adapter-base.mjs";
|
|
2
|
+
import { createAuthContext } from "./create-context.mjs";
|
|
3
|
+
import { BetterAuthError } from "@better-auth/core/error";
|
|
4
|
+
//#region src/context/init-minimal.ts
|
|
5
|
+
const initMinimal = async (options) => {
|
|
6
|
+
const adapter = await getBaseAdapter(options, async () => {
|
|
7
|
+
throw new BetterAuthError("Direct database connection requires Kysely. Please use `better-auth` instead of `better-auth/minimal`, or provide an adapter (drizzleAdapter, prismaAdapter, etc.)");
|
|
8
|
+
});
|
|
9
|
+
const getDatabaseType = (_database) => "unknown";
|
|
10
|
+
const ctx = await createAuthContext(adapter, options, getDatabaseType);
|
|
11
|
+
ctx.runMigrations = async function() {
|
|
12
|
+
throw new BetterAuthError("Migrations are not supported in 'better-auth/minimal'. Please use 'better-auth' for migration support.");
|
|
13
|
+
};
|
|
14
|
+
return ctx;
|
|
15
|
+
};
|
|
16
|
+
//#endregion
|
|
17
|
+
export { initMinimal };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { getAdapter } from "../db/adapter-kysely.mjs";
|
|
2
|
+
import { getMigrations } from "../db/get-migration.mjs";
|
|
3
|
+
import { createAuthContext } from "./create-context.mjs";
|
|
4
|
+
import { BetterAuthError } from "@better-auth/core/error";
|
|
5
|
+
import { getKyselyDatabaseType } from "@better-auth/kysely-adapter";
|
|
6
|
+
//#region src/context/init.ts
|
|
7
|
+
const init = async (options) => {
|
|
8
|
+
const adapter = await getAdapter(options);
|
|
9
|
+
const getDatabaseType = (database) => getKyselyDatabaseType(database) || "unknown";
|
|
10
|
+
const ctx = await createAuthContext(adapter, options, getDatabaseType);
|
|
11
|
+
ctx.runMigrations = async function() {
|
|
12
|
+
if (!options.database || "updateMany" in options.database) throw new BetterAuthError("Database is not provided or it's an adapter. Migrations are only supported with a database instance.");
|
|
13
|
+
const { runMigrations } = await getMigrations(options);
|
|
14
|
+
await runMigrations();
|
|
15
|
+
};
|
|
16
|
+
return ctx;
|
|
17
|
+
};
|
|
18
|
+
//#endregion
|
|
19
|
+
export { init };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import "../utils/constants.mjs";
|
|
2
|
+
import { BetterAuthError } from "@better-auth/core/error";
|
|
3
|
+
//#region src/context/secret-utils.ts
|
|
4
|
+
/**
|
|
5
|
+
* Estimates the entropy of a string in bits.
|
|
6
|
+
* This is a simple approximation that helps detect low-entropy secrets.
|
|
7
|
+
*/
|
|
8
|
+
function estimateEntropy(str) {
|
|
9
|
+
const unique = new Set(str).size;
|
|
10
|
+
if (unique === 0) return 0;
|
|
11
|
+
return Math.log2(Math.pow(unique, str.length));
|
|
12
|
+
}
|
|
13
|
+
function parseSecretsEnv(envValue) {
|
|
14
|
+
if (!envValue) return null;
|
|
15
|
+
return envValue.split(",").map((entry) => {
|
|
16
|
+
entry = entry.trim();
|
|
17
|
+
const colonIdx = entry.indexOf(":");
|
|
18
|
+
if (colonIdx === -1) throw new BetterAuthError(`Invalid BETTER_AUTH_SECRETS entry: "${entry}". Expected format: "<version>:<secret>"`);
|
|
19
|
+
const version = parseInt(entry.slice(0, colonIdx), 10);
|
|
20
|
+
if (!Number.isInteger(version) || version < 0) throw new BetterAuthError(`Invalid version in BETTER_AUTH_SECRETS: "${entry.slice(0, colonIdx)}". Version must be a non-negative integer.`);
|
|
21
|
+
const value = entry.slice(colonIdx + 1).trim();
|
|
22
|
+
if (!value) throw new BetterAuthError(`Empty secret value for version ${version} in BETTER_AUTH_SECRETS.`);
|
|
23
|
+
return {
|
|
24
|
+
version,
|
|
25
|
+
value
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function validateSecretsArray(secrets, logger) {
|
|
30
|
+
if (secrets.length === 0) throw new BetterAuthError("`secrets` array must contain at least one entry.");
|
|
31
|
+
const seen = /* @__PURE__ */ new Set();
|
|
32
|
+
for (const s of secrets) {
|
|
33
|
+
const version = parseInt(String(s.version), 10);
|
|
34
|
+
if (!Number.isInteger(version) || version < 0 || String(version) !== String(s.version).trim()) throw new BetterAuthError(`Invalid version ${s.version} in \`secrets\`. Version must be a non-negative integer.`);
|
|
35
|
+
if (!s.value) throw new BetterAuthError(`Empty secret value for version ${version} in \`secrets\`.`);
|
|
36
|
+
if (seen.has(version)) throw new BetterAuthError(`Duplicate version ${version} in \`secrets\`. Each version must be unique.`);
|
|
37
|
+
seen.add(version);
|
|
38
|
+
}
|
|
39
|
+
const current = secrets[0];
|
|
40
|
+
if (current.value.length < 32) logger.warn(`[better-auth] Warning: the current secret (version ${current.version}) should be at least 32 characters long for adequate security.`);
|
|
41
|
+
if (estimateEntropy(current.value) < 120) logger.warn("[better-auth] Warning: the current secret appears low-entropy. Use a randomly generated secret for production.");
|
|
42
|
+
}
|
|
43
|
+
function buildSecretConfig(secrets, legacySecret) {
|
|
44
|
+
const keys = /* @__PURE__ */ new Map();
|
|
45
|
+
for (const s of secrets) keys.set(parseInt(String(s.version), 10), s.value);
|
|
46
|
+
return {
|
|
47
|
+
keys,
|
|
48
|
+
currentVersion: parseInt(String(secrets[0].version), 10),
|
|
49
|
+
legacySecret: legacySecret && legacySecret !== "better-auth-secret-12345678901234567890" ? legacySecret : void 0
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
export { buildSecretConfig, parseSecretsEnv, validateSecretsArray };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/context/store-capabilities.ts
|
|
2
|
+
function hasServerSessionStore(options) {
|
|
3
|
+
return !!options.database || !!options.secondaryStorage;
|
|
4
|
+
}
|
|
5
|
+
function hasServerAccountStore(options) {
|
|
6
|
+
return !!options.database;
|
|
7
|
+
}
|
|
8
|
+
function shouldBindAccountCookieToSessionUser(options) {
|
|
9
|
+
return hasServerAccountStore(options);
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { hasServerSessionStore, shouldBindAccountCookieToSessionUser };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { sessionSchema, userSchema } from "@better-auth/core/db";
|
|
2
|
+
import { logger } from "@better-auth/core/env";
|
|
3
|
+
import { safeJSONParse } from "@better-auth/core/utils/json";
|
|
4
|
+
import * as z from "zod";
|
|
5
|
+
//#region src/cookies/cache.ts
|
|
6
|
+
const cookieCachePayloadSchema = z.looseObject({
|
|
7
|
+
session: sessionSchema.loose(),
|
|
8
|
+
user: userSchema.loose(),
|
|
9
|
+
updatedAt: z.number(),
|
|
10
|
+
version: z.string().optional()
|
|
11
|
+
});
|
|
12
|
+
const compactCookieCacheSchema = z.object({
|
|
13
|
+
session: z.record(z.string(), z.unknown()),
|
|
14
|
+
expiresAt: z.number(),
|
|
15
|
+
signature: z.string()
|
|
16
|
+
});
|
|
17
|
+
function parseCookieCachePayload(value) {
|
|
18
|
+
const parsed = safeJSONParse(value);
|
|
19
|
+
if (parsed === null) return null;
|
|
20
|
+
const result = cookieCachePayloadSchema.safeParse(parsed);
|
|
21
|
+
if (result.success) return result.data;
|
|
22
|
+
logger.warn("Cookie cache payload failed schema validation", { issues: result.error.issues.map(({ code, path }) => ({
|
|
23
|
+
code,
|
|
24
|
+
path
|
|
25
|
+
})) });
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
function parseCompactCookieCache(value) {
|
|
29
|
+
const result = compactCookieCacheSchema.safeParse(value);
|
|
30
|
+
return result.success ? result.data : null;
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { parseCompactCookieCache, parseCookieCachePayload };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
//#region src/cookies/cookie-utils.d.ts
|
|
2
|
+
interface CookieAttributes {
|
|
3
|
+
value: string;
|
|
4
|
+
"max-age"?: number | undefined;
|
|
5
|
+
expires?: Date | undefined;
|
|
6
|
+
domain?: string | undefined;
|
|
7
|
+
path?: string | undefined;
|
|
8
|
+
secure?: boolean | undefined;
|
|
9
|
+
httponly?: boolean | undefined;
|
|
10
|
+
partitioned?: boolean | undefined;
|
|
11
|
+
samesite?: ("strict" | "lax" | "none") | undefined;
|
|
12
|
+
[key: string]: string | number | boolean | Date | undefined;
|
|
13
|
+
}
|
|
14
|
+
interface ParsedCookieOptions {
|
|
15
|
+
maxAge?: number | undefined;
|
|
16
|
+
expires?: Date | undefined;
|
|
17
|
+
domain?: string | undefined;
|
|
18
|
+
path?: string | undefined;
|
|
19
|
+
secure?: boolean | undefined;
|
|
20
|
+
httpOnly?: boolean | undefined;
|
|
21
|
+
partitioned?: boolean | undefined;
|
|
22
|
+
sameSite?: CookieAttributes["samesite"];
|
|
23
|
+
}
|
|
24
|
+
declare const SECURE_COOKIE_PREFIX = "__Secure-";
|
|
25
|
+
declare const HOST_COOKIE_PREFIX = "__Host-";
|
|
26
|
+
/**
|
|
27
|
+
* Remove __Secure- or __Host- prefix from cookie name.
|
|
28
|
+
*/
|
|
29
|
+
declare function stripSecureCookiePrefix(cookieName: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* Split a comma-joined `Set-Cookie` header string into individual cookies.
|
|
32
|
+
*/
|
|
33
|
+
declare function splitSetCookieHeader(setCookie: string): string[];
|
|
34
|
+
declare function parseSetCookieHeader(setCookie: string): Map<string, CookieAttributes>;
|
|
35
|
+
declare function toCookieOptions(attributes: CookieAttributes): ParsedCookieOptions;
|
|
36
|
+
/**
|
|
37
|
+
* Cookie-name token char set per RFC 7230 §3.2.6.
|
|
38
|
+
*
|
|
39
|
+
* @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.6
|
|
40
|
+
*/
|
|
41
|
+
declare const cookieNameRegex: RegExp;
|
|
42
|
+
/**
|
|
43
|
+
* Tolerates `;` separators without the SP that RFC 6265 §4.2.1 mandates,
|
|
44
|
+
* since proxies and runtimes commonly strip it. Silently drops entries
|
|
45
|
+
* whose name violates RFC 7230 token or whose value violates RFC 6265
|
|
46
|
+
* cookie-octet (plus space and comma). Strips optional surrounding
|
|
47
|
+
* double-quotes per RFC 6265 §4.1.1.
|
|
48
|
+
*/
|
|
49
|
+
declare function parseCookies(cookie: string): Map<string, string>;
|
|
50
|
+
/**
|
|
51
|
+
* Add or replace a cookie in the request `Cookie` header.
|
|
52
|
+
*
|
|
53
|
+
* Cookie pairs are joined with `; `, but `headers.append("cookie", ...)`
|
|
54
|
+
* joins with `, ` in some runtimes (e.g. Deno, Cloudflare Workers) and
|
|
55
|
+
* breaks downstream cookie parsing. This builds the header value via
|
|
56
|
+
* parse-mutate-serialize.
|
|
57
|
+
*/
|
|
58
|
+
declare function setRequestCookie(headers: Headers, name: string, value: string): void;
|
|
59
|
+
/**
|
|
60
|
+
* Merge `Set-Cookie` header values into the target's `Cookie` header.
|
|
61
|
+
* Mutates `target`.
|
|
62
|
+
*
|
|
63
|
+
* Name/value-level merge only. RFC 6265 §5 user-agent semantics
|
|
64
|
+
* (expiration, domain/path scoping, ordering) are out of scope. Suitable
|
|
65
|
+
* for single-request proxy, middleware, and test contexts.
|
|
66
|
+
*/
|
|
67
|
+
declare function applySetCookies(target: Headers, setCookieValues: Iterable<string>): void;
|
|
68
|
+
declare function setCookieToHeader(headers: Headers): (context: {
|
|
69
|
+
response: Response;
|
|
70
|
+
}) => void;
|
|
71
|
+
//#endregion
|
|
72
|
+
export { CookieAttributes, HOST_COOKIE_PREFIX, SECURE_COOKIE_PREFIX, applySetCookies, cookieNameRegex, parseCookies, parseSetCookieHeader, setCookieToHeader, setRequestCookie, splitSetCookieHeader, stripSecureCookiePrefix, toCookieOptions };
|