@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,203 @@
|
|
|
1
|
+
import { getBaseURL } from "../../utils/url.mjs";
|
|
2
|
+
import { PACKAGE_VERSION } from "../../version.mjs";
|
|
3
|
+
import { POPUP_TOKEN_STORAGE_KEY } from "./constants.mjs";
|
|
4
|
+
import { OAUTH_POPUP_ERROR_CODES } from "./error-codes.mjs";
|
|
5
|
+
//#region src/plugins/oauth-popup/client.ts
|
|
6
|
+
const POPUP_NAME = "better-auth-oauth";
|
|
7
|
+
const POPUP_WIDTH = 500;
|
|
8
|
+
const POPUP_HEIGHT = 600;
|
|
9
|
+
const CLOSED_POLL_MS = 500;
|
|
10
|
+
const DEFAULT_TIMEOUT_MS = 300 * 1e3;
|
|
11
|
+
/** True when embedded cross-origin, where the cookie may be partitioned. */
|
|
12
|
+
function isEmbedded() {
|
|
13
|
+
if (typeof window === "undefined" || window.self === window.top) return false;
|
|
14
|
+
try {
|
|
15
|
+
window.top?.location.href;
|
|
16
|
+
return false;
|
|
17
|
+
} catch {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Reads the stored popup token (browser-only; null otherwise). */
|
|
22
|
+
function getStoredPopupToken() {
|
|
23
|
+
if (typeof window === "undefined") return null;
|
|
24
|
+
try {
|
|
25
|
+
return window.localStorage.getItem(POPUP_TOKEN_STORAGE_KEY);
|
|
26
|
+
} catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function storePopupToken(token) {
|
|
31
|
+
try {
|
|
32
|
+
window.localStorage?.setItem(POPUP_TOKEN_STORAGE_KEY, token);
|
|
33
|
+
} catch {}
|
|
34
|
+
}
|
|
35
|
+
function clearPopupToken() {
|
|
36
|
+
try {
|
|
37
|
+
window.localStorage?.removeItem(POPUP_TOKEN_STORAGE_KEY);
|
|
38
|
+
} catch {}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Attaches the popup token as a bearer header when embedded (where the cookie is
|
|
42
|
+
* partitioned), and clears it once the session ends so it can't be reused.
|
|
43
|
+
*/
|
|
44
|
+
const popupBearerFetchPlugin = {
|
|
45
|
+
id: "better-auth-popup-bearer",
|
|
46
|
+
name: "Popup Bearer",
|
|
47
|
+
hooks: {
|
|
48
|
+
onRequest(context) {
|
|
49
|
+
if (!isEmbedded()) return context;
|
|
50
|
+
const token = getStoredPopupToken();
|
|
51
|
+
if (!token) return context;
|
|
52
|
+
const headers = new Headers(context.headers);
|
|
53
|
+
if (!headers.has("authorization")) headers.set("authorization", `Bearer ${token}`);
|
|
54
|
+
return {
|
|
55
|
+
...context,
|
|
56
|
+
headers
|
|
57
|
+
};
|
|
58
|
+
},
|
|
59
|
+
onSuccess(context) {
|
|
60
|
+
const path = new URL(context.request.url).pathname;
|
|
61
|
+
if (path.endsWith("/sign-out") || path.endsWith("/revoke-session") || path.endsWith("/revoke-sessions") || path.endsWith("/revoke-other-sessions") || path.endsWith("/delete-user")) clearPopupToken();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
let activePopup = null;
|
|
66
|
+
function popupError(code, status) {
|
|
67
|
+
return {
|
|
68
|
+
data: null,
|
|
69
|
+
error: {
|
|
70
|
+
code,
|
|
71
|
+
message: String(OAUTH_POPUP_ERROR_CODES[code]),
|
|
72
|
+
...status ? { status } : {}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function centeredFeatures() {
|
|
77
|
+
return `width=${POPUP_WIDTH},height=${POPUP_HEIGHT},left=${window.screenX + (window.outerWidth - POPUP_WIDTH) / 2},top=${window.screenY + (window.outerHeight - POPUP_HEIGHT) / 2},menubar=no,toolbar=no`;
|
|
78
|
+
}
|
|
79
|
+
function randomNonce() {
|
|
80
|
+
const bytes = new Uint8Array(16);
|
|
81
|
+
crypto.getRandomValues(bytes);
|
|
82
|
+
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Resolves with the token (or relayed error) once the completion page posts
|
|
86
|
+
* back, gating on origin, type, and nonce.
|
|
87
|
+
*/
|
|
88
|
+
function waitForPopupResult(popup, expectedOrigin, nonce, timeoutMs) {
|
|
89
|
+
return new Promise((resolve) => {
|
|
90
|
+
let settled = false;
|
|
91
|
+
const settle = (outcome) => {
|
|
92
|
+
if (settled) return;
|
|
93
|
+
settled = true;
|
|
94
|
+
window.removeEventListener("message", onMessage);
|
|
95
|
+
clearInterval(closedPoll);
|
|
96
|
+
clearTimeout(timeout);
|
|
97
|
+
try {
|
|
98
|
+
if (!popup.closed) popup.close();
|
|
99
|
+
} catch {}
|
|
100
|
+
resolve(outcome);
|
|
101
|
+
};
|
|
102
|
+
const onMessage = (event) => {
|
|
103
|
+
if (event.origin !== expectedOrigin) return;
|
|
104
|
+
const data = event.data;
|
|
105
|
+
if (data?.type !== "better-auth:oauth-popup") return;
|
|
106
|
+
if (data.nonce !== nonce) return;
|
|
107
|
+
if (data.error) {
|
|
108
|
+
settle({
|
|
109
|
+
status: "error",
|
|
110
|
+
error: data.error
|
|
111
|
+
});
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (typeof data.token !== "string" || !data.token) return;
|
|
115
|
+
settle({
|
|
116
|
+
status: "success",
|
|
117
|
+
token: data.token
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
const closedPoll = setInterval(() => {
|
|
121
|
+
if (popup.closed) settle({ status: "cancelled" });
|
|
122
|
+
}, CLOSED_POLL_MS);
|
|
123
|
+
const timeout = setTimeout(() => settle({ status: "timeout" }), timeoutMs);
|
|
124
|
+
window.addEventListener("message", onMessage);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function resolveAuthURL(options) {
|
|
128
|
+
const configured = getBaseURL(options?.baseURL, options?.basePath) ?? options?.basePath ?? "/api/auth";
|
|
129
|
+
return new URL(configured, window.location.origin);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Builds `signIn.popup`. Runs the sign-in in the popup's own first-party
|
|
133
|
+
* context (so the OAuth state cookie lands there), waits for the completion
|
|
134
|
+
* page to post the session token back, stores it for the bearer fetch plugin,
|
|
135
|
+
* and refreshes the reactive session.
|
|
136
|
+
*/
|
|
137
|
+
function createSignInPopup({ $fetch, options, notifySessionSignal }) {
|
|
138
|
+
return async function signInPopup(opts) {
|
|
139
|
+
if (typeof window === "undefined") return popupError("POPUP_SIGN_IN_FAILED");
|
|
140
|
+
const { provider, providerId, additionalData, windowFeatures, timeoutMs = DEFAULT_TIMEOUT_MS, callbackURL, errorCallbackURL, newUserCallbackURL, scopes, requestSignUp } = opts;
|
|
141
|
+
if (!provider && !providerId) return popupError("POPUP_SIGN_IN_FAILED");
|
|
142
|
+
if (activePopup && !activePopup.closed) {
|
|
143
|
+
activePopup.focus();
|
|
144
|
+
return popupError("POPUP_SIGN_IN_FAILED");
|
|
145
|
+
}
|
|
146
|
+
const nonce = randomNonce();
|
|
147
|
+
const authUrl = resolveAuthURL(options);
|
|
148
|
+
const authOrigin = authUrl.origin;
|
|
149
|
+
const startUrl = new URL(`${authUrl.href.replace(/\/$/, "")}/oauth-popup/start`);
|
|
150
|
+
startUrl.searchParams.set("provider", provider ?? providerId);
|
|
151
|
+
startUrl.searchParams.set("popupOrigin", window.location.origin);
|
|
152
|
+
startUrl.searchParams.set("popupNonce", nonce);
|
|
153
|
+
if (callbackURL) startUrl.searchParams.set("callbackURL", callbackURL);
|
|
154
|
+
if (errorCallbackURL) startUrl.searchParams.set("errorCallbackURL", errorCallbackURL);
|
|
155
|
+
if (newUserCallbackURL) startUrl.searchParams.set("newUserCallbackURL", newUserCallbackURL);
|
|
156
|
+
if (scopes?.length) startUrl.searchParams.set("scopes", scopes.join(","));
|
|
157
|
+
if (requestSignUp) startUrl.searchParams.set("requestSignUp", "true");
|
|
158
|
+
if (additionalData) startUrl.searchParams.set("additionalData", JSON.stringify(additionalData));
|
|
159
|
+
const popup = window.open(startUrl.toString(), POPUP_NAME, windowFeatures ?? centeredFeatures());
|
|
160
|
+
if (!popup) return popupError("POPUP_BLOCKED");
|
|
161
|
+
activePopup = popup;
|
|
162
|
+
const outcome = await waitForPopupResult(popup, authOrigin, nonce, timeoutMs);
|
|
163
|
+
activePopup = null;
|
|
164
|
+
if (outcome.status === "timeout") return popupError("POPUP_TIMEOUT");
|
|
165
|
+
if (outcome.status === "cancelled") return popupError("POPUP_CLOSED");
|
|
166
|
+
if (outcome.status === "error") return {
|
|
167
|
+
data: null,
|
|
168
|
+
error: {
|
|
169
|
+
code: outcome.error.code,
|
|
170
|
+
message: outcome.error.description || outcome.error.code
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
if (isEmbedded()) storePopupToken(outcome.token);
|
|
174
|
+
else clearPopupToken();
|
|
175
|
+
const session = await $fetch("/get-session");
|
|
176
|
+
if (session.error || !session.data) return popupError("POPUP_SIGN_IN_FAILED", session.error?.status);
|
|
177
|
+
notifySessionSignal();
|
|
178
|
+
return {
|
|
179
|
+
data: { success: true },
|
|
180
|
+
error: null
|
|
181
|
+
};
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Client plugin for popup OAuth sign-in. Adds `authClient.signIn.popup`. Pair
|
|
186
|
+
* with the server `oauthPopup` and `bearer` plugins.
|
|
187
|
+
*/
|
|
188
|
+
const oauthPopupClient = () => {
|
|
189
|
+
return {
|
|
190
|
+
id: "oauth-popup",
|
|
191
|
+
version: PACKAGE_VERSION,
|
|
192
|
+
$InferServerPlugin: {},
|
|
193
|
+
$ERROR_CODES: OAUTH_POPUP_ERROR_CODES,
|
|
194
|
+
fetchPlugins: [popupBearerFetchPlugin],
|
|
195
|
+
getActions: ($fetch, $store, options) => ({ signIn: { popup: createSignInPopup({
|
|
196
|
+
$fetch,
|
|
197
|
+
options,
|
|
198
|
+
notifySessionSignal: () => $store.notify("$sessionSignal")
|
|
199
|
+
}) } })
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
//#endregion
|
|
203
|
+
export { createSignInPopup, getStoredPopupToken, oauthPopupClient, popupBearerFetchPlugin };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/plugins/oauth-popup/constants.d.ts
|
|
2
|
+
/** postMessage `type` the completion page posts to its opener. */
|
|
3
|
+
declare const OAUTH_POPUP_MESSAGE_TYPE = "better-auth:oauth-popup";
|
|
4
|
+
/** DOM id of the inert JSON data block the completion page reads. */
|
|
5
|
+
declare const OAUTH_POPUP_DATA_ELEMENT_ID = "better-auth-oauth-popup";
|
|
6
|
+
/** Signed cookie carrying the opener origin/nonce from sign-in to callback. */
|
|
7
|
+
declare const POPUP_MARKER_COOKIE = "oauth_popup";
|
|
8
|
+
/** localStorage key the popup session token is persisted under. */
|
|
9
|
+
declare const POPUP_TOKEN_STORAGE_KEY = "better-auth.popup_token";
|
|
10
|
+
//#endregion
|
|
11
|
+
export { OAUTH_POPUP_DATA_ELEMENT_ID, OAUTH_POPUP_MESSAGE_TYPE, POPUP_MARKER_COOKIE, POPUP_TOKEN_STORAGE_KEY };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/plugins/oauth-popup/constants.ts
|
|
2
|
+
/** postMessage `type` the completion page posts to its opener. */
|
|
3
|
+
const OAUTH_POPUP_MESSAGE_TYPE = "better-auth:oauth-popup";
|
|
4
|
+
/** DOM id of the inert JSON data block the completion page reads. */
|
|
5
|
+
const OAUTH_POPUP_DATA_ELEMENT_ID = "better-auth-oauth-popup";
|
|
6
|
+
/** Signed cookie carrying the opener origin/nonce from sign-in to callback. */
|
|
7
|
+
const POPUP_MARKER_COOKIE = "oauth_popup";
|
|
8
|
+
/** localStorage key the popup session token is persisted under. */
|
|
9
|
+
const POPUP_TOKEN_STORAGE_KEY = "better-auth.popup_token";
|
|
10
|
+
//#endregion
|
|
11
|
+
export { OAUTH_POPUP_DATA_ELEMENT_ID, OAUTH_POPUP_MESSAGE_TYPE, POPUP_MARKER_COOKIE, POPUP_TOKEN_STORAGE_KEY };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as _$_better_auth_core_utils_error_codes0 from "@better-auth/core/utils/error-codes";
|
|
2
|
+
|
|
3
|
+
//#region src/plugins/oauth-popup/error-codes.d.ts
|
|
4
|
+
declare const OAUTH_POPUP_ERROR_CODES: {
|
|
5
|
+
POPUP_SIGN_IN_FAILED: _$_better_auth_core_utils_error_codes0.RawError<"POPUP_SIGN_IN_FAILED">;
|
|
6
|
+
POPUP_BLOCKED: _$_better_auth_core_utils_error_codes0.RawError<"POPUP_BLOCKED">;
|
|
7
|
+
POPUP_CLOSED: _$_better_auth_core_utils_error_codes0.RawError<"POPUP_CLOSED">;
|
|
8
|
+
POPUP_TIMEOUT: _$_better_auth_core_utils_error_codes0.RawError<"POPUP_TIMEOUT">;
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { OAUTH_POPUP_ERROR_CODES };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { defineErrorCodes } from "@better-auth/core/utils/error-codes";
|
|
2
|
+
//#region src/plugins/oauth-popup/error-codes.ts
|
|
3
|
+
const OAUTH_POPUP_ERROR_CODES = defineErrorCodes({
|
|
4
|
+
POPUP_SIGN_IN_FAILED: "Popup sign-in failed",
|
|
5
|
+
POPUP_BLOCKED: "Sign-in popup was blocked by the browser",
|
|
6
|
+
POPUP_CLOSED: "Sign-in popup was closed before completing",
|
|
7
|
+
POPUP_TIMEOUT: "Sign-in popup timed out"
|
|
8
|
+
});
|
|
9
|
+
//#endregion
|
|
10
|
+
export { OAUTH_POPUP_ERROR_CODES };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { OAUTH_POPUP_DATA_ELEMENT_ID, OAUTH_POPUP_MESSAGE_TYPE, POPUP_MARKER_COOKIE } from "./constants.mjs";
|
|
2
|
+
import { OAUTH_POPUP_ERROR_CODES } from "./error-codes.mjs";
|
|
3
|
+
import { OAuthPopupData, OAuthPopupMessage } from "./types.mjs";
|
|
4
|
+
import * as _$_better_auth_core0 from "@better-auth/core";
|
|
5
|
+
import * as _$_better_auth_core_utils_error_codes0 from "@better-auth/core/utils/error-codes";
|
|
6
|
+
import * as _$better_call0 from "better-call";
|
|
7
|
+
import * as z from "zod";
|
|
8
|
+
|
|
9
|
+
//#region src/plugins/oauth-popup/index.d.ts
|
|
10
|
+
declare module "@better-auth/core" {
|
|
11
|
+
interface BetterAuthPluginRegistry<AuthOptions, Options> {
|
|
12
|
+
"oauth-popup": {
|
|
13
|
+
creator: typeof oauthPopup;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The completion-page script.
|
|
19
|
+
*/
|
|
20
|
+
declare const OAUTH_POPUP_COMPLETE_SCRIPT: string;
|
|
21
|
+
/**
|
|
22
|
+
* sha256 of `OAUTH_POPUP_COMPLETE_SCRIPT`, pinned in the completion CSP.
|
|
23
|
+
*/
|
|
24
|
+
declare const OAUTH_POPUP_SCRIPT_CSP_HASH = "sha256-tIo2K8VBC9SnhvdZ+9GsGkQoZm+jm/JcxL+d+i8b8KQ=";
|
|
25
|
+
/**
|
|
26
|
+
* Server plugin for popup-based OAuth. `signIn.popup` navigates the popup to
|
|
27
|
+
* `/oauth-popup/start`; on the OAuth callback this plugin swaps the redirect for
|
|
28
|
+
* a page that posts the session token (or error) back to the opener. Pair with
|
|
29
|
+
* the `bearer` plugin and `oauthPopupClient`.
|
|
30
|
+
*/
|
|
31
|
+
declare const oauthPopup: () => {
|
|
32
|
+
id: "oauth-popup";
|
|
33
|
+
version: string;
|
|
34
|
+
$ERROR_CODES: {
|
|
35
|
+
POPUP_SIGN_IN_FAILED: _$_better_auth_core_utils_error_codes0.RawError<"POPUP_SIGN_IN_FAILED">;
|
|
36
|
+
POPUP_BLOCKED: _$_better_auth_core_utils_error_codes0.RawError<"POPUP_BLOCKED">;
|
|
37
|
+
POPUP_CLOSED: _$_better_auth_core_utils_error_codes0.RawError<"POPUP_CLOSED">;
|
|
38
|
+
POPUP_TIMEOUT: _$_better_auth_core_utils_error_codes0.RawError<"POPUP_TIMEOUT">;
|
|
39
|
+
};
|
|
40
|
+
endpoints: {
|
|
41
|
+
oauthPopupStart: _$better_call0.StrictEndpoint<"/oauth-popup/start", {
|
|
42
|
+
method: "GET";
|
|
43
|
+
query: z.ZodObject<{
|
|
44
|
+
provider: z.ZodString;
|
|
45
|
+
popupOrigin: z.ZodString;
|
|
46
|
+
popupNonce: z.ZodOptional<z.ZodString>;
|
|
47
|
+
callbackURL: z.ZodOptional<z.ZodString>;
|
|
48
|
+
errorCallbackURL: z.ZodOptional<z.ZodString>;
|
|
49
|
+
newUserCallbackURL: z.ZodOptional<z.ZodString>;
|
|
50
|
+
scopes: z.ZodOptional<z.ZodString>;
|
|
51
|
+
requestSignUp: z.ZodOptional<z.ZodString>;
|
|
52
|
+
additionalData: z.ZodOptional<z.ZodString>;
|
|
53
|
+
}, z.core.$strip>;
|
|
54
|
+
metadata: {
|
|
55
|
+
readonly scope: "server";
|
|
56
|
+
};
|
|
57
|
+
}, Response>;
|
|
58
|
+
};
|
|
59
|
+
hooks: {
|
|
60
|
+
after: {
|
|
61
|
+
matcher(context: _$_better_auth_core0.HookEndpointContext): boolean;
|
|
62
|
+
handler: _$better_call0.Middleware<_$better_call0.MiddlewareOptions, (inputContext: _$better_call0.MiddlewareInputContext<_$better_call0.MiddlewareOptions>) => Promise<void>>;
|
|
63
|
+
}[];
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
//#endregion
|
|
67
|
+
export { OAUTH_POPUP_COMPLETE_SCRIPT, OAUTH_POPUP_SCRIPT_CSP_HASH, oauthPopup };
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { parseSetCookieHeader, splitSetCookieHeader } from "../../cookies/cookie-utils.mjs";
|
|
2
|
+
import { generateRandomString } from "../../crypto/random.mjs";
|
|
3
|
+
import { expireCookie } from "../../cookies/index.mjs";
|
|
4
|
+
import { getAwaitableValue } from "../../context/helpers.mjs";
|
|
5
|
+
import { setOAuthState } from "../../api/state/oauth.mjs";
|
|
6
|
+
import { INTERNAL_STATE_KEYS, generateGenericState } from "../../state.mjs";
|
|
7
|
+
import { generateIdTokenNonce } from "../../oauth2/state.mjs";
|
|
8
|
+
import { HIDE_METADATA } from "../../utils/hide-metadata.mjs";
|
|
9
|
+
import { PACKAGE_VERSION } from "../../version.mjs";
|
|
10
|
+
import { OAUTH_POPUP_DATA_ELEMENT_ID, OAUTH_POPUP_MESSAGE_TYPE, POPUP_MARKER_COOKIE } from "./constants.mjs";
|
|
11
|
+
import { OAUTH_POPUP_ERROR_CODES } from "./error-codes.mjs";
|
|
12
|
+
import { APIError, BASE_ERROR_CODES } from "@better-auth/core/error";
|
|
13
|
+
import { safeJSONParse } from "@better-auth/core/utils/json";
|
|
14
|
+
import { createAuthEndpoint, createAuthMiddleware } from "@better-auth/core/api";
|
|
15
|
+
import * as z from "zod";
|
|
16
|
+
//#region src/plugins/oauth-popup/index.ts
|
|
17
|
+
let warnedMissingBearer = false;
|
|
18
|
+
/**
|
|
19
|
+
* Escapes `<\/script>` and JS line separators for embedding in a script element.
|
|
20
|
+
*/
|
|
21
|
+
function inlineJSON(value) {
|
|
22
|
+
return JSON.stringify(value).replace(/[<\u2028\u2029]/g, (c) => `\\u${c.charCodeAt(0).toString(16).padStart(4, "0")}`);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The completion-page script.
|
|
26
|
+
*/
|
|
27
|
+
const OAUTH_POPUP_COMPLETE_SCRIPT = `(function () {
|
|
28
|
+
var el = document.getElementById(${JSON.stringify(OAUTH_POPUP_DATA_ELEMENT_ID)});
|
|
29
|
+
if (!el) return;
|
|
30
|
+
var payload;
|
|
31
|
+
try {
|
|
32
|
+
payload = JSON.parse(el.textContent || "");
|
|
33
|
+
} catch (e) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
var target = window.opener || window.parent;
|
|
37
|
+
if (target && target !== window) {
|
|
38
|
+
try {
|
|
39
|
+
target.postMessage(
|
|
40
|
+
{
|
|
41
|
+
type: payload.type,
|
|
42
|
+
nonce: payload.nonce,
|
|
43
|
+
token: payload.token,
|
|
44
|
+
redirectTo: payload.redirectTo,
|
|
45
|
+
error: payload.error,
|
|
46
|
+
},
|
|
47
|
+
payload.targetOrigin,
|
|
48
|
+
);
|
|
49
|
+
} catch (e) {}
|
|
50
|
+
}
|
|
51
|
+
window.close();
|
|
52
|
+
})();
|
|
53
|
+
`;
|
|
54
|
+
/**
|
|
55
|
+
* sha256 of `OAUTH_POPUP_COMPLETE_SCRIPT`, pinned in the completion CSP.
|
|
56
|
+
*/
|
|
57
|
+
const OAUTH_POPUP_SCRIPT_CSP_HASH = "sha256-tIo2K8VBC9SnhvdZ+9GsGkQoZm+jm/JcxL+d+i8b8KQ=";
|
|
58
|
+
/**
|
|
59
|
+
* Renders the page that posts the outcome (token or error) to the opener. The
|
|
60
|
+
* caller must pass a trusted `popupOrigin` — validated at `/oauth-popup/start`
|
|
61
|
+
* and preserved in the signed marker cookie the callback reads.
|
|
62
|
+
*/
|
|
63
|
+
function renderCompletion(c, popupOrigin, message) {
|
|
64
|
+
if (message.token && !warnedMissingBearer && !c.context.hasPlugin("bearer")) {
|
|
65
|
+
warnedMissingBearer = true;
|
|
66
|
+
c.context.logger.warn("OAuth popup hands the session token back via postMessage, but the `bearer` plugin is not registered, so an embedded (cross-site iframe) app cannot authenticate with it. Add bearer() to your auth `plugins`.");
|
|
67
|
+
}
|
|
68
|
+
const html = `<!doctype html>
|
|
69
|
+
<html>
|
|
70
|
+
<head><meta charset="utf-8"><title>Completing sign-in</title></head>
|
|
71
|
+
<body>
|
|
72
|
+
<script type="application/json" id="${OAUTH_POPUP_DATA_ELEMENT_ID}">${inlineJSON({
|
|
73
|
+
type: OAUTH_POPUP_MESSAGE_TYPE,
|
|
74
|
+
targetOrigin: popupOrigin,
|
|
75
|
+
...message
|
|
76
|
+
})}<\/script>
|
|
77
|
+
<script>${OAUTH_POPUP_COMPLETE_SCRIPT}<\/script>
|
|
78
|
+
</body>
|
|
79
|
+
</html>`;
|
|
80
|
+
return new Response(html, {
|
|
81
|
+
status: 200,
|
|
82
|
+
headers: {
|
|
83
|
+
"content-type": "text/html; charset=utf-8",
|
|
84
|
+
"content-security-policy": `default-src 'none'; script-src '${OAUTH_POPUP_SCRIPT_CSP_HASH}'; base-uri 'none'`,
|
|
85
|
+
"cache-control": "no-store",
|
|
86
|
+
pragma: "no-cache"
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Starts the OAuth flow for a popup. The popup navigates here (top-level, so it
|
|
92
|
+
* is first-party to the auth origin even when the app is on another origin),
|
|
93
|
+
* the server sets the state + opener-marker cookies in the right partition, then
|
|
94
|
+
* redirects to the provider. The callback then renders the completion page.
|
|
95
|
+
*/
|
|
96
|
+
const oauthPopupStart = createAuthEndpoint("/oauth-popup/start", {
|
|
97
|
+
method: "GET",
|
|
98
|
+
query: z.object({
|
|
99
|
+
provider: z.string(),
|
|
100
|
+
popupOrigin: z.string(),
|
|
101
|
+
popupNonce: z.string().optional(),
|
|
102
|
+
callbackURL: z.string().optional(),
|
|
103
|
+
errorCallbackURL: z.string().optional(),
|
|
104
|
+
newUserCallbackURL: z.string().optional(),
|
|
105
|
+
scopes: z.string().optional(),
|
|
106
|
+
requestSignUp: z.string().optional(),
|
|
107
|
+
additionalData: z.string().optional()
|
|
108
|
+
}),
|
|
109
|
+
metadata: HIDE_METADATA
|
|
110
|
+
}, async (c) => {
|
|
111
|
+
const { popupOrigin } = c.query;
|
|
112
|
+
if (!c.context.isTrustedOrigin(popupOrigin, { allowRelativePaths: false })) {
|
|
113
|
+
c.context.logger.error(`OAuth popup origin is not a trusted origin. Add ${popupOrigin} to trustedOrigins.`);
|
|
114
|
+
throw APIError.from("FORBIDDEN", BASE_ERROR_CODES.INVALID_ORIGIN);
|
|
115
|
+
}
|
|
116
|
+
const fail = (code, description) => renderCompletion(c, popupOrigin, {
|
|
117
|
+
nonce: c.query.popupNonce ?? "",
|
|
118
|
+
error: {
|
|
119
|
+
code,
|
|
120
|
+
description
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
const validateRedirect = (url, code) => {
|
|
124
|
+
if (!url || c.context.isTrustedOrigin(url, { allowRelativePaths: true })) return;
|
|
125
|
+
c.context.logger.error(`Invalid redirect URL: ${url}`);
|
|
126
|
+
return fail(code, `Untrusted URL: ${url}`);
|
|
127
|
+
};
|
|
128
|
+
const invalidRedirect = validateRedirect(c.query.callbackURL, "invalid_callback_url") ?? validateRedirect(c.query.errorCallbackURL, "invalid_error_callback_url") ?? validateRedirect(c.query.newUserCallbackURL, "invalid_new_user_callback_url");
|
|
129
|
+
if (invalidRedirect) return invalidRedirect;
|
|
130
|
+
const provider = await getAwaitableValue(c.context.socialProviders, { value: c.query.provider });
|
|
131
|
+
if (!provider) return fail("provider_not_found", `Unknown provider: ${c.query.provider}`);
|
|
132
|
+
const callbackURL = c.query.callbackURL || c.context.baseURL;
|
|
133
|
+
let url;
|
|
134
|
+
try {
|
|
135
|
+
const codeVerifier = generateRandomString(128);
|
|
136
|
+
const idTokenNonce = generateIdTokenNonce(provider);
|
|
137
|
+
const parsedAdditionalData = c.query.additionalData ? safeJSONParse(c.query.additionalData) ?? {} : {};
|
|
138
|
+
const stateData = {
|
|
139
|
+
...Object.fromEntries(Object.entries(parsedAdditionalData).filter(([key]) => !INTERNAL_STATE_KEYS.has(key))),
|
|
140
|
+
callbackURL,
|
|
141
|
+
codeVerifier,
|
|
142
|
+
idTokenNonce,
|
|
143
|
+
errorURL: c.query.errorCallbackURL,
|
|
144
|
+
newUserURL: c.query.newUserCallbackURL,
|
|
145
|
+
requestSignUp: c.query.requestSignUp === "true" ? true : void 0,
|
|
146
|
+
expiresAt: Date.now() + 600 * 1e3
|
|
147
|
+
};
|
|
148
|
+
await setOAuthState(stateData);
|
|
149
|
+
const { state } = await generateGenericState(c, stateData);
|
|
150
|
+
const marker = c.context.createAuthCookie(POPUP_MARKER_COOKIE, { maxAge: 600 });
|
|
151
|
+
await c.setSignedCookie(marker.name, JSON.stringify({
|
|
152
|
+
popupOrigin,
|
|
153
|
+
popupNonce: c.query.popupNonce ?? ""
|
|
154
|
+
}), c.context.secret, marker.attributes);
|
|
155
|
+
url = await provider.createAuthorizationURL({
|
|
156
|
+
state,
|
|
157
|
+
codeVerifier,
|
|
158
|
+
idTokenNonce,
|
|
159
|
+
redirectURI: `${c.context.baseURL}/callback/${provider.id}`,
|
|
160
|
+
scopes: c.query.scopes ? c.query.scopes.split(",") : void 0
|
|
161
|
+
});
|
|
162
|
+
} catch (error) {
|
|
163
|
+
c.context.logger.error("OAuth popup failed to start", error);
|
|
164
|
+
return fail("popup_sign_in_failed", "Failed to start the OAuth flow.");
|
|
165
|
+
}
|
|
166
|
+
throw c.redirect(url.toString());
|
|
167
|
+
});
|
|
168
|
+
/**
|
|
169
|
+
* Server plugin for popup-based OAuth. `signIn.popup` navigates the popup to
|
|
170
|
+
* `/oauth-popup/start`; on the OAuth callback this plugin swaps the redirect for
|
|
171
|
+
* a page that posts the session token (or error) back to the opener. Pair with
|
|
172
|
+
* the `bearer` plugin and `oauthPopupClient`.
|
|
173
|
+
*/
|
|
174
|
+
const oauthPopup = () => {
|
|
175
|
+
return {
|
|
176
|
+
id: "oauth-popup",
|
|
177
|
+
version: PACKAGE_VERSION,
|
|
178
|
+
$ERROR_CODES: OAUTH_POPUP_ERROR_CODES,
|
|
179
|
+
endpoints: { oauthPopupStart },
|
|
180
|
+
hooks: { after: [{
|
|
181
|
+
matcher(context) {
|
|
182
|
+
return !!(context.path?.startsWith("/callback/") || context.path?.startsWith("/oauth2/callback/"));
|
|
183
|
+
},
|
|
184
|
+
handler: createAuthMiddleware(async (c) => {
|
|
185
|
+
const redirectTo = c.context.responseHeaders?.get("location");
|
|
186
|
+
if (!redirectTo) return;
|
|
187
|
+
const cookie = c.context.createAuthCookie(POPUP_MARKER_COOKIE);
|
|
188
|
+
const marker = await c.getSignedCookie(cookie.name, c.context.secret);
|
|
189
|
+
if (!marker) return;
|
|
190
|
+
expireCookie(c, cookie);
|
|
191
|
+
let popupOrigin;
|
|
192
|
+
let popupNonce;
|
|
193
|
+
try {
|
|
194
|
+
const parsed = JSON.parse(marker);
|
|
195
|
+
popupOrigin = parsed.popupOrigin;
|
|
196
|
+
popupNonce = parsed.popupNonce ?? "";
|
|
197
|
+
} catch {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const setCookies = c.context.responseHeaders?.getSetCookie?.() ?? splitSetCookieHeader(c.context.responseHeaders?.get("set-cookie") ?? "");
|
|
201
|
+
let token;
|
|
202
|
+
for (const raw of setCookies) {
|
|
203
|
+
const value = parseSetCookieHeader(raw).get(c.context.authCookies.sessionToken.name)?.value;
|
|
204
|
+
if (value !== void 0) {
|
|
205
|
+
token = value;
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
let response;
|
|
210
|
+
if (token) response = renderCompletion(c, popupOrigin, {
|
|
211
|
+
nonce: popupNonce,
|
|
212
|
+
token,
|
|
213
|
+
redirectTo
|
|
214
|
+
});
|
|
215
|
+
else {
|
|
216
|
+
const error = new URL(redirectTo, c.context.baseURL).searchParams.get("error");
|
|
217
|
+
if (!error) return;
|
|
218
|
+
response = renderCompletion(c, popupOrigin, {
|
|
219
|
+
nonce: popupNonce,
|
|
220
|
+
error: {
|
|
221
|
+
code: error,
|
|
222
|
+
description: new URL(redirectTo, c.context.baseURL).searchParams.get("error_description") ?? void 0
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
c.context.returned = response;
|
|
227
|
+
})
|
|
228
|
+
}] }
|
|
229
|
+
};
|
|
230
|
+
};
|
|
231
|
+
//#endregion
|
|
232
|
+
export { OAUTH_POPUP_COMPLETE_SCRIPT, OAUTH_POPUP_SCRIPT_CSP_HASH, oauthPopup };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { OAUTH_POPUP_MESSAGE_TYPE } from "./constants.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/plugins/oauth-popup/types.d.ts
|
|
4
|
+
/** OAuth error relayed to the opener when the flow fails. */
|
|
5
|
+
interface OAuthPopupError {
|
|
6
|
+
code: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Message the completion page posts to its opener — success carries the token,
|
|
11
|
+
* failure carries the error.
|
|
12
|
+
*/
|
|
13
|
+
interface OAuthPopupMessage {
|
|
14
|
+
type: typeof OAUTH_POPUP_MESSAGE_TYPE;
|
|
15
|
+
/** Echoes the request nonce so the opener can correlate the handoff. */
|
|
16
|
+
nonce: string;
|
|
17
|
+
/** The session token, sent as `Authorization: Bearer <token>` (on success). */
|
|
18
|
+
token?: string;
|
|
19
|
+
/** Where the flow would have redirected (callbackURL / newUserURL). */
|
|
20
|
+
redirectTo?: string;
|
|
21
|
+
/** The OAuth error (on failure). */
|
|
22
|
+
error?: OAuthPopupError;
|
|
23
|
+
}
|
|
24
|
+
/** Payload embedded in the completion page's data block. */
|
|
25
|
+
interface OAuthPopupData extends OAuthPopupMessage {
|
|
26
|
+
/** Exact origin the message is posted to (the trusted popup opener). */
|
|
27
|
+
targetOrigin: string;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { OAuthPopupData, OAuthPopupMessage };
|