better-auth 1.7.0-beta.2 → 1.7.0-beta.4
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/README.md +14 -15
- package/dist/_virtual/_rolldown/runtime.mjs +10 -1
- package/dist/api/index.d.mts +18 -48
- package/dist/api/routes/account.d.mts +4 -23
- package/dist/api/routes/account.mjs +102 -75
- package/dist/api/routes/callback.mjs +42 -20
- package/dist/api/routes/email-verification.d.mts +1 -0
- package/dist/api/routes/email-verification.mjs +6 -5
- package/dist/api/routes/error.mjs +1 -1
- package/dist/api/routes/password.mjs +1 -1
- package/dist/api/routes/session.mjs +15 -10
- package/dist/api/routes/sign-in.d.mts +3 -1
- package/dist/api/routes/sign-in.mjs +13 -15
- package/dist/api/routes/sign-up.d.mts +1 -0
- package/dist/api/routes/sign-up.mjs +10 -8
- package/dist/api/routes/update-user.mjs +8 -8
- package/dist/api/to-auth-endpoints.mjs +7 -1
- package/dist/auth/base.mjs +30 -27
- package/dist/client/config.mjs +8 -1
- package/dist/client/fetch-plugins.mjs +2 -1
- package/dist/client/index.d.mts +2 -2
- package/dist/client/lynx/index.d.mts +13 -0
- package/dist/client/lynx/index.mjs +2 -1
- package/dist/client/parser.mjs +0 -1
- package/dist/client/plugins/index.d.mts +4 -17
- package/dist/client/plugins/index.mjs +1 -4
- package/dist/client/proxy.mjs +2 -1
- package/dist/client/react/index.d.mts +13 -0
- package/dist/client/react/index.mjs +2 -1
- package/dist/client/session-atom.mjs +12 -1
- package/dist/client/solid/index.d.mts +13 -0
- package/dist/client/solid/index.mjs +3 -2
- package/dist/client/svelte/index.d.mts +13 -0
- package/dist/client/svelte/index.mjs +2 -1
- package/dist/client/vanilla.d.mts +13 -0
- package/dist/client/vanilla.mjs +2 -1
- package/dist/client/vue/index.d.mts +13 -0
- package/dist/client/vue/index.mjs +2 -1
- package/dist/context/create-context.mjs +10 -14
- package/dist/context/helpers.mjs +3 -2
- package/dist/cookies/cookie-utils.d.mts +33 -1
- package/dist/cookies/cookie-utils.mjs +95 -14
- package/dist/cookies/index.d.mts +2 -3
- package/dist/cookies/index.mjs +39 -11
- package/dist/cookies/session-store.mjs +4 -23
- package/dist/db/get-migration.mjs +4 -4
- package/dist/db/index.d.mts +2 -2
- package/dist/db/index.mjs +3 -2
- package/dist/db/internal-adapter.mjs +129 -27
- package/dist/db/schema.d.mts +14 -1
- package/dist/db/schema.mjs +26 -1
- package/dist/db/with-hooks.d.mts +1 -0
- package/dist/db/with-hooks.mjs +58 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/integrations/cookie-plugin-guard.mjs +18 -0
- package/dist/integrations/next-js.mjs +6 -0
- package/dist/integrations/svelte-kit.mjs +6 -0
- package/dist/integrations/tanstack-start-solid.mjs +6 -0
- package/dist/integrations/tanstack-start.mjs +6 -0
- package/dist/node_modules/.pnpm/clipboardy@4.0.0/node_modules/clipboardy/index.mjs +32 -0
- package/dist/node_modules/.pnpm/clipboardy@4.0.0/node_modules/clipboardy/lib/linux.mjs +55 -0
- package/dist/node_modules/.pnpm/clipboardy@4.0.0/node_modules/clipboardy/lib/macos.mjs +26 -0
- package/dist/node_modules/.pnpm/clipboardy@4.0.0/node_modules/clipboardy/lib/termux.mjs +39 -0
- package/dist/node_modules/.pnpm/clipboardy@4.0.0/node_modules/clipboardy/lib/windows.mjs +19 -0
- package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/chunks/prompt.mjs +845 -0
- package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/core.mjs +386 -0
- package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/index.mjs +320 -0
- package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/shared/consola.DRwqZj3T.mjs +62 -0
- package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/shared/consola.DXBYu-KD.mjs +190 -0
- package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/utils.mjs +2 -0
- package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/index.mjs +29 -0
- package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/enoent.mjs +42 -0
- package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.mjs +67 -0
- package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/escape.mjs +23 -0
- package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.mjs +22 -0
- package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.mjs +36 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/adapters/node.d.mts +292 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/adapters/node.mjs +127 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/index.d.mts +145 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/shared/crossws.BQXMA5bH.d.mts +298 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/shared/crossws.By9qWDAI.mjs +9 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/shared/crossws.CipVM6lf.mjs +3549 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/shared/crossws.D9ehKjSh.mjs +66 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/shared/crossws.DfCzGthR.mjs +227 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/index.mjs +224 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/command.mjs +52 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/error.mjs +54 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/kill.mjs +62 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/pipe.mjs +26 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/promise.mjs +32 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/stdio.mjs +19 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/stream.mjs +98 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/verbose.mjs +15 -0
- package/dist/node_modules/.pnpm/get-port-please@3.2.0/node_modules/get-port-please/dist/index.d.mts +15 -0
- package/dist/node_modules/.pnpm/get-port-please@3.2.0/node_modules/get-port-please/dist/index.mjs +220 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/array-buffer.mjs +54 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/array.mjs +2 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/buffer.mjs +14 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/contents.mjs +76 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/index.mjs +6 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/string.mjs +35 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/utils.mjs +10 -0
- package/dist/node_modules/.pnpm/http-shutdown@1.2.2/node_modules/http-shutdown/index.mjs +76 -0
- package/dist/node_modules/.pnpm/human-signals@5.0.0/node_modules/human-signals/build/src/core.mjs +274 -0
- package/dist/node_modules/.pnpm/human-signals@5.0.0/node_modules/human-signals/build/src/main.mjs +44 -0
- package/dist/node_modules/.pnpm/human-signals@5.0.0/node_modules/human-signals/build/src/realtime.mjs +15 -0
- package/dist/node_modules/.pnpm/human-signals@5.0.0/node_modules/human-signals/build/src/signals.mjs +23 -0
- package/dist/node_modules/.pnpm/is-docker@3.0.0/node_modules/is-docker/index.mjs +24 -0
- package/dist/node_modules/.pnpm/is-inside-container@1.0.0/node_modules/is-inside-container/index.mjs +18 -0
- package/dist/node_modules/.pnpm/is-stream@3.0.0/node_modules/is-stream/index.mjs +9 -0
- package/dist/node_modules/.pnpm/is-wsl@3.1.1/node_modules/is-wsl/index.mjs +20 -0
- package/dist/node_modules/.pnpm/is64bit@2.0.0/node_modules/is64bit/index.mjs +13 -0
- package/dist/node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.mjs +47 -0
- package/dist/node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/mode.mjs +33 -0
- package/dist/node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/windows.mjs +33 -0
- package/dist/node_modules/.pnpm/listhen@1.9.0/node_modules/listhen/dist/chunks/xdg-open.mjs +1070 -0
- package/dist/node_modules/.pnpm/listhen@1.9.0/node_modules/listhen/dist/index.mjs +619 -0
- package/dist/node_modules/.pnpm/listhen@1.9.0/node_modules/listhen/dist/shared/listhen.1c46e31d.d.mts +83 -0
- package/dist/node_modules/.pnpm/merge-stream@2.0.0/node_modules/merge-stream/index.mjs +38 -0
- package/dist/node_modules/.pnpm/mimic-fn@4.0.0/node_modules/mimic-fn/index.mjs +38 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/aes.mjs +597 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/aesCipherSuites.mjs +195 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/asn1-validator.mjs +76 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/asn1.mjs +967 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/baseN.mjs +137 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/cipher.mjs +186 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/cipherModes.mjs +597 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/des.mjs +1187 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/ed25519.mjs +1029 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/forge.mjs +15 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/hmac.mjs +107 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/index.mjs +66 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/jsbn.mjs +1334 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/kem.mjs +146 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/log.mjs +241 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/md.all.mjs +24 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/md.mjs +18 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/md5.mjs +324 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/mgf.mjs +20 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/mgf1.mjs +44 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/oids.mjs +154 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pbe.mjs +815 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pbkdf2.mjs +125 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pem.mjs +175 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pkcs1.mjs +200 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pkcs12.mjs +724 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pkcs7.mjs +642 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pkcs7asn1.mjs +405 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pki.mjs +101 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/prime.mjs +193 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/prng.mjs +290 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pss.mjs +141 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/random.mjs +141 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/rc2.mjs +538 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/rsa.mjs +1309 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/sha1.mjs +230 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/sha256.mjs +267 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/sha512.mjs +413 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/ssh.mjs +194 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/tls.mjs +3655 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/util.mjs +2117 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/x509.mjs +2168 -0
- package/dist/node_modules/.pnpm/npm-run-path@5.3.0/node_modules/npm-run-path/index.mjs +34 -0
- package/dist/node_modules/.pnpm/onetime@6.0.0/node_modules/onetime/index.mjs +26 -0
- package/dist/node_modules/.pnpm/path-key@3.1.1/node_modules/path-key/index.mjs +14 -0
- package/dist/node_modules/.pnpm/path-key@4.0.0/node_modules/path-key/index.mjs +8 -0
- package/dist/node_modules/.pnpm/pathe@1.1.2/node_modules/pathe/dist/shared/pathe.ff20891b.mjs +176 -0
- package/dist/node_modules/.pnpm/shebang-command@2.0.0/node_modules/shebang-command/index.mjs +17 -0
- package/dist/node_modules/.pnpm/shebang-regex@3.0.0/node_modules/shebang-regex/index.mjs +8 -0
- package/dist/node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/index.mjs +169 -0
- package/dist/node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/signals.mjs +33 -0
- package/dist/node_modules/.pnpm/std-env@3.10.0/node_modules/std-env/dist/index.mjs +171 -0
- package/dist/node_modules/.pnpm/strip-final-newline@3.0.0/node_modules/strip-final-newline/index.mjs +10 -0
- package/dist/node_modules/.pnpm/system-architecture@0.1.0/node_modules/system-architecture/index.mjs +16 -0
- package/dist/node_modules/.pnpm/uncrypto@0.1.3/node_modules/uncrypto/dist/crypto.node.mjs +7 -0
- package/dist/node_modules/.pnpm/untun@0.1.3/node_modules/untun/dist/chunks/index.mjs +154 -0
- package/dist/node_modules/.pnpm/untun@0.1.3/node_modules/untun/dist/index.mjs +34 -0
- package/dist/node_modules/.pnpm/uqr@0.1.2/node_modules/uqr/dist/index.mjs +896 -0
- package/dist/node_modules/.pnpm/which@2.0.2/node_modules/which/which.mjs +76 -0
- package/dist/oauth2/errors.mjs +27 -0
- package/dist/oauth2/index.d.mts +2 -2
- package/dist/oauth2/index.mjs +3 -3
- package/dist/oauth2/link-account.d.mts +27 -1
- package/dist/oauth2/link-account.mjs +30 -5
- package/dist/oauth2/state.mjs +8 -2
- package/dist/{package.mjs → packages/better-auth/package.mjs} +1 -1
- package/dist/plugins/access/access.d.mts +3 -15
- package/dist/plugins/access/access.mjs +11 -6
- package/dist/plugins/access/index.d.mts +2 -2
- package/dist/plugins/access/types.d.mts +11 -4
- package/dist/plugins/admin/access/statement.d.mts +29 -93
- package/dist/plugins/admin/admin.mjs +0 -4
- package/dist/plugins/admin/client.d.mts +6 -1
- package/dist/plugins/admin/client.mjs +5 -0
- package/dist/plugins/admin/routes.mjs +3 -2
- package/dist/plugins/anonymous/client.d.mts +1 -0
- package/dist/plugins/anonymous/error-codes.d.mts +1 -0
- package/dist/plugins/anonymous/error-codes.mjs +1 -0
- package/dist/plugins/anonymous/index.d.mts +1 -0
- package/dist/plugins/anonymous/index.mjs +16 -2
- package/dist/plugins/bearer/index.mjs +5 -12
- package/dist/plugins/captcha/index.mjs +14 -1
- package/dist/plugins/device-authorization/error-codes.mjs +1 -0
- package/dist/plugins/device-authorization/index.d.mts +1 -0
- package/dist/plugins/device-authorization/routes.mjs +34 -3
- package/dist/plugins/email-otp/routes.mjs +4 -4
- package/dist/plugins/generic-oauth/error-codes.mjs +0 -1
- package/dist/plugins/generic-oauth/index.d.mts +2 -4
- package/dist/plugins/generic-oauth/index.mjs +23 -17
- package/dist/plugins/generic-oauth/providers/auth0.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/gumroad.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/hubspot.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/keycloak.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/line.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/microsoft-entra-id.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/okta.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/patreon.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/slack.mjs +1 -0
- package/dist/plugins/generic-oauth/types.d.mts +30 -8
- package/dist/plugins/index.d.mts +2 -2
- package/dist/plugins/jwt/utils.d.mts +1 -1
- package/dist/plugins/last-login-method/client.mjs +2 -2
- package/dist/plugins/magic-link/index.d.mts +8 -1
- package/dist/plugins/magic-link/index.mjs +4 -17
- package/dist/plugins/mcp/authorize.mjs +8 -2
- package/dist/plugins/mcp/index.mjs +75 -35
- package/dist/plugins/multi-session/index.mjs +2 -2
- package/dist/plugins/oauth-proxy/index.mjs +45 -32
- package/dist/plugins/oauth-proxy/utils.mjs +3 -10
- package/dist/plugins/oidc-provider/authorize.mjs +8 -2
- package/dist/plugins/oidc-provider/index.mjs +65 -38
- package/dist/plugins/one-tap/client.mjs +9 -2
- package/dist/plugins/one-tap/index.mjs +19 -36
- package/dist/plugins/open-api/generator.mjs +25 -5
- package/dist/plugins/organization/access/statement.d.mts +68 -201
- package/dist/plugins/organization/adapter.d.mts +1 -1
- package/dist/plugins/organization/adapter.mjs +65 -58
- package/dist/plugins/organization/client.d.mts +3 -1
- package/dist/plugins/organization/client.mjs +1 -1
- package/dist/plugins/organization/error-codes.d.mts +2 -0
- package/dist/plugins/organization/error-codes.mjs +3 -1
- package/dist/plugins/organization/routes/crud-access-control.d.mts +2 -2
- package/dist/plugins/organization/routes/crud-invites.d.mts +8 -1
- package/dist/plugins/organization/routes/crud-invites.mjs +8 -3
- package/dist/plugins/organization/routes/crud-org.d.mts +4 -4
- package/dist/plugins/organization/routes/crud-org.mjs +2 -2
- package/dist/plugins/organization/routes/crud-team.mjs +7 -2
- package/dist/plugins/organization/schema.d.mts +1 -1
- package/dist/plugins/organization/types.d.mts +15 -5
- package/dist/plugins/phone-number/routes.mjs +1 -1
- package/dist/plugins/siwe/client.d.mts +4 -0
- package/dist/plugins/siwe/client.mjs +5 -1
- package/dist/plugins/siwe/index.d.mts +13 -2
- package/dist/plugins/siwe/index.mjs +179 -165
- package/dist/plugins/two-factor/backup-codes/index.d.mts +4 -3
- package/dist/plugins/two-factor/client.mjs +2 -1
- package/dist/plugins/two-factor/index.mjs +3 -2
- package/dist/plugins/username/client.d.mts +1 -0
- package/dist/plugins/username/error-codes.d.mts +1 -0
- package/dist/plugins/username/error-codes.mjs +2 -1
- package/dist/plugins/username/index.d.mts +43 -2
- package/dist/plugins/username/index.mjs +73 -6
- package/dist/state.d.mts +2 -2
- package/dist/state.mjs +18 -4
- package/dist/test-utils/headers.mjs +2 -7
- package/dist/test-utils/http-test-instance.d.mts +397 -0
- package/dist/test-utils/http-test-instance.mjs +54 -0
- package/dist/test-utils/index.d.mts +2 -1
- package/dist/test-utils/index.mjs +2 -1
- package/dist/test-utils/test-instance.d.mts +4110 -224
- package/dist/test-utils/test-instance.mjs +11 -2
- package/dist/types/auth.d.mts +4 -0
- package/dist/utils/index.d.mts +1 -1
- package/dist/utils/url.d.mts +2 -1
- package/dist/utils/url.mjs +9 -3
- package/dist/version.mjs +1 -1
- package/package.json +14 -14
- package/dist/oauth2/error-codes.d.mts +0 -20
- package/dist/plugins/generic-oauth/client.d.mts +0 -32
- package/dist/plugins/generic-oauth/client.mjs +0 -19
- package/dist/plugins/generic-oauth/error-codes.d.mts +0 -10
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { isAPIError } from "../../utils/is-api-error.mjs";
|
|
1
2
|
import { setSessionCookie } from "../../cookies/index.mjs";
|
|
2
3
|
import { getAwaitableValue } from "../../context/helpers.mjs";
|
|
3
|
-
import {
|
|
4
|
+
import { missingEmailLogMessage } from "../../oauth2/errors.mjs";
|
|
4
5
|
import { setTokenUtil } from "../../oauth2/utils.mjs";
|
|
6
|
+
import { applyUpdateUserInfoOnLink, handleOAuthUserInfo } from "../../oauth2/link-account.mjs";
|
|
7
|
+
import { generateState, parseState } from "../../oauth2/state.mjs";
|
|
5
8
|
import { OAUTH_CALLBACK_ERROR_CODES } from "../../oauth2/error-codes.mjs";
|
|
6
|
-
import { handleOAuthUserInfo } from "../../oauth2/link-account.mjs";
|
|
7
9
|
import { HIDE_METADATA } from "../../utils/hide-metadata.mjs";
|
|
8
10
|
import { safeJSONParse } from "@better-auth/core/utils/json";
|
|
9
11
|
import { createAuthEndpoint } from "@better-auth/core/api";
|
|
@@ -51,9 +53,21 @@ const callbackOAuth = createAuthEndpoint("/callback/:id", {
|
|
|
51
53
|
throw c.redirect(`${defaultErrorURL}?error=invalid_callback_request`);
|
|
52
54
|
}
|
|
53
55
|
const { code, error, state, error_description, device_id, user: userData, iss } = queryOrBody;
|
|
56
|
+
if (state === void 0 && code) {
|
|
57
|
+
const provider = await getAwaitableValue(c.context.socialProviders, { value: c.params.id });
|
|
58
|
+
if (provider?.allowIdpInitiated) {
|
|
59
|
+
const { state: freshState, codeVerifier } = await generateState(c, void 0, void 0);
|
|
60
|
+
const authUrl = await provider.createAuthorizationURL({
|
|
61
|
+
state: freshState,
|
|
62
|
+
codeVerifier,
|
|
63
|
+
redirectURI: `${c.context.baseURL}/callback/${provider.id}`
|
|
64
|
+
});
|
|
65
|
+
throw c.redirect(authUrl.toString());
|
|
66
|
+
}
|
|
67
|
+
}
|
|
54
68
|
if (!state) {
|
|
55
69
|
c.context.logger.error("State not found", error);
|
|
56
|
-
const url = `${defaultErrorURL}${defaultErrorURL.includes("?") ? "&" : "?"}
|
|
70
|
+
const url = `${defaultErrorURL}${defaultErrorURL.includes("?") ? "&" : "?"}error=state_not_found`;
|
|
57
71
|
throw c.redirect(url);
|
|
58
72
|
}
|
|
59
73
|
const { codeVerifier, callbackURL, link, errorURL, newUserURL, requestSignUp } = await parseState(c);
|
|
@@ -99,10 +113,11 @@ const callbackOAuth = createAuthEndpoint("/callback/:id", {
|
|
|
99
113
|
...tokens,
|
|
100
114
|
user: parsedUserData ?? void 0
|
|
101
115
|
}).then((res) => res?.user);
|
|
102
|
-
if (!userInfo) {
|
|
116
|
+
if (!userInfo || userInfo.id === void 0 || userInfo.id === null) {
|
|
103
117
|
c.context.logger.error("Unable to get user info");
|
|
104
118
|
return redirectOnError(OAUTH_CALLBACK_ERROR_CODES.UNABLE_TO_GET_USER_INFO);
|
|
105
119
|
}
|
|
120
|
+
const providerAccountId = String(userInfo.id);
|
|
106
121
|
if (!callbackURL) {
|
|
107
122
|
c.context.logger.error("No callback URL found");
|
|
108
123
|
throw redirectOnError(OAUTH_CALLBACK_ERROR_CODES.NO_CALLBACK_URL);
|
|
@@ -113,7 +128,7 @@ const callbackOAuth = createAuthEndpoint("/callback/:id", {
|
|
|
113
128
|
return redirectOnError(OAUTH_CALLBACK_ERROR_CODES.UNABLE_TO_LINK_ACCOUNT);
|
|
114
129
|
}
|
|
115
130
|
if (userInfo.email?.toLowerCase() !== link.email.toLowerCase() && c.context.options.account?.accountLinking?.allowDifferentEmails !== true) return redirectOnError(OAUTH_CALLBACK_ERROR_CODES.EMAIL_DOES_NOT_MATCH);
|
|
116
|
-
const existingAccount = await c.context.internalAdapter.findAccountByProviderId(
|
|
131
|
+
const existingAccount = await c.context.internalAdapter.findAccountByProviderId(providerAccountId, provider.id);
|
|
117
132
|
if (existingAccount) {
|
|
118
133
|
if (existingAccount.userId.toString() !== link.userId.toString()) return redirectOnError(OAUTH_CALLBACK_ERROR_CODES.ACCOUNT_ALREADY_LINKED_TO_DIFFERENT_USER);
|
|
119
134
|
const updateData = Object.fromEntries(Object.entries({
|
|
@@ -128,12 +143,13 @@ const callbackOAuth = createAuthEndpoint("/callback/:id", {
|
|
|
128
143
|
} else if (!await c.context.internalAdapter.createAccount({
|
|
129
144
|
userId: link.userId,
|
|
130
145
|
providerId: provider.id,
|
|
131
|
-
accountId:
|
|
146
|
+
accountId: providerAccountId,
|
|
132
147
|
...tokens,
|
|
133
148
|
accessToken: await setTokenUtil(tokens.accessToken, c.context),
|
|
134
149
|
refreshToken: await setTokenUtil(tokens.refreshToken, c.context),
|
|
135
150
|
scope: tokens.scopes?.join(",")
|
|
136
151
|
})) return redirectOnError(OAUTH_CALLBACK_ERROR_CODES.UNABLE_TO_LINK_ACCOUNT);
|
|
152
|
+
await applyUpdateUserInfoOnLink(c, link.userId, userInfo);
|
|
137
153
|
let toRedirectTo;
|
|
138
154
|
try {
|
|
139
155
|
toRedirectTo = callbackURL.toString();
|
|
@@ -143,27 +159,33 @@ const callbackOAuth = createAuthEndpoint("/callback/:id", {
|
|
|
143
159
|
throw c.redirect(toRedirectTo);
|
|
144
160
|
}
|
|
145
161
|
if (!userInfo.email) {
|
|
146
|
-
c.context.logger.error(
|
|
162
|
+
c.context.logger.error(missingEmailLogMessage(provider.id));
|
|
147
163
|
return redirectOnError(OAUTH_CALLBACK_ERROR_CODES.EMAIL_NOT_FOUND);
|
|
148
164
|
}
|
|
149
165
|
const accountData = {
|
|
150
166
|
providerId: provider.id,
|
|
151
|
-
accountId:
|
|
167
|
+
accountId: providerAccountId,
|
|
152
168
|
...tokens,
|
|
153
169
|
scope: tokens.scopes?.join(",")
|
|
154
170
|
};
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
171
|
+
let result;
|
|
172
|
+
try {
|
|
173
|
+
result = await handleOAuthUserInfo(c, {
|
|
174
|
+
userInfo: {
|
|
175
|
+
...userInfo,
|
|
176
|
+
id: providerAccountId,
|
|
177
|
+
email: userInfo.email,
|
|
178
|
+
name: userInfo.name || ""
|
|
179
|
+
},
|
|
180
|
+
account: accountData,
|
|
181
|
+
callbackURL,
|
|
182
|
+
disableSignUp: provider.disableImplicitSignUp && !requestSignUp || provider.options?.disableSignUp,
|
|
183
|
+
overrideUserInfo: provider.options?.overrideUserInfoOnSignIn
|
|
184
|
+
});
|
|
185
|
+
} catch (e) {
|
|
186
|
+
if (isAPIError(e) && e.body?.code) redirectOnError(e.body.code, e.body.message);
|
|
187
|
+
throw e;
|
|
188
|
+
}
|
|
167
189
|
if (result.error) {
|
|
168
190
|
c.context.logger.error(result.error.split(" ").join("_"));
|
|
169
191
|
return redirectOnError(result.error.split(" ").join("_"));
|
|
@@ -27,6 +27,7 @@ declare function sendVerificationEmailFn(ctx: GenericEndpointContext, user: User
|
|
|
27
27
|
declare const sendVerificationEmail: better_call0.StrictEndpoint<"/send-verification-email", {
|
|
28
28
|
method: "POST";
|
|
29
29
|
operationId: string;
|
|
30
|
+
cloneRequest: true;
|
|
30
31
|
body: z.ZodObject<{
|
|
31
32
|
email: z.ZodEmail;
|
|
32
33
|
callbackURL: z.ZodOptional<z.ZodString>;
|
|
@@ -12,7 +12,7 @@ import { JWTExpired } from "jose/errors";
|
|
|
12
12
|
async function createEmailVerificationToken(secret, email, updateTo, expiresIn = 3600, extraPayload) {
|
|
13
13
|
return await signJWT({
|
|
14
14
|
email: email.toLowerCase(),
|
|
15
|
-
updateTo,
|
|
15
|
+
updateTo: updateTo?.toLowerCase(),
|
|
16
16
|
...extraPayload
|
|
17
17
|
}, secret, expiresIn);
|
|
18
18
|
}
|
|
@@ -31,11 +31,12 @@ async function sendVerificationEmailFn(ctx, user) {
|
|
|
31
31
|
user,
|
|
32
32
|
url,
|
|
33
33
|
token
|
|
34
|
-
}, ctx.request));
|
|
34
|
+
}, ctx.request?.clone()));
|
|
35
35
|
}
|
|
36
36
|
const sendVerificationEmail = createAuthEndpoint("/send-verification-email", {
|
|
37
37
|
method: "POST",
|
|
38
38
|
operationId: "sendVerificationEmail",
|
|
39
|
+
cloneRequest: true,
|
|
39
40
|
body: z.object({
|
|
40
41
|
email: z.email().meta({ description: "The email to send the verification email to" }),
|
|
41
42
|
callbackURL: z.string().meta({ description: "The URL to use for email verification callback" }).optional()
|
|
@@ -101,7 +102,7 @@ const sendVerificationEmail = createAuthEndpoint("/send-verification-email", {
|
|
|
101
102
|
await sendVerificationEmailFn(ctx, user.user);
|
|
102
103
|
return ctx.json({ status: true });
|
|
103
104
|
}
|
|
104
|
-
if (session?.user.email !== email) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.EMAIL_MISMATCH);
|
|
105
|
+
if (session?.user.email.toLowerCase() !== email.toLowerCase()) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.EMAIL_MISMATCH);
|
|
105
106
|
if (session?.user.emailVerified) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.EMAIL_ALREADY_VERIFIED);
|
|
106
107
|
await sendVerificationEmailFn(ctx, session.user);
|
|
107
108
|
return ctx.json({ status: true });
|
|
@@ -185,7 +186,7 @@ const verifyEmail = createAuthEndpoint("/verify-email", {
|
|
|
185
186
|
},
|
|
186
187
|
url,
|
|
187
188
|
token: newToken
|
|
188
|
-
}, ctx.request));
|
|
189
|
+
}, ctx.request?.clone()));
|
|
189
190
|
if (ctx.query.callbackURL) throw ctx.redirect(ctx.query.callbackURL);
|
|
190
191
|
return ctx.json({ status: true });
|
|
191
192
|
}
|
|
@@ -238,7 +239,7 @@ const verifyEmail = createAuthEndpoint("/verify-email", {
|
|
|
238
239
|
user: updatedUser,
|
|
239
240
|
url: `${ctx.context.baseURL}/verify-email?token=${newToken}&callbackURL=${updateCallbackURL}`,
|
|
240
241
|
token: newToken
|
|
241
|
-
}, ctx.request));
|
|
242
|
+
}, ctx.request?.clone()));
|
|
242
243
|
await setSessionCookie(ctx, {
|
|
243
244
|
session: activeSession.session,
|
|
244
245
|
user: {
|
|
@@ -282,7 +282,7 @@ ${custom?.disableBackgroundGrid ? "" : `
|
|
|
282
282
|
text-wrap: pretty;
|
|
283
283
|
"
|
|
284
284
|
>
|
|
285
|
-
${!description ? `We encountered an unexpected error. Please try again or return to the home page. If you're a developer, you can find
|
|
285
|
+
${!description ? `We encountered an unexpected error. Please try again or return to the home page. If you're a developer, you can find <a href='https://better-auth.com/docs/reference/errors/${encodeURIComponent(code)}' target='_blank' rel="noopener noreferrer" style='color: var(--foreground); text-decoration: underline;'>more information about the error</a>.` : description}
|
|
286
286
|
</p>
|
|
287
287
|
</div>
|
|
288
288
|
|
|
@@ -161,7 +161,7 @@ const resetPassword = createAuthEndpoint("/reset-password", {
|
|
|
161
161
|
const user = await ctx.context.internalAdapter.findUserById(userId);
|
|
162
162
|
if (user) await ctx.context.options.emailAndPassword.onPasswordReset({ user }, ctx.request);
|
|
163
163
|
}
|
|
164
|
-
if (ctx.context.options.emailAndPassword?.revokeSessionsOnPasswordReset) await ctx.context.internalAdapter.
|
|
164
|
+
if (ctx.context.options.emailAndPassword?.revokeSessionsOnPasswordReset) await ctx.context.internalAdapter.deleteUserSessions(userId);
|
|
165
165
|
return ctx.json({ status: true });
|
|
166
166
|
});
|
|
167
167
|
const verifyPassword = createAuthEndpoint("/verify-password", {
|
|
@@ -129,12 +129,8 @@ const getSession = () => createAuthEndpoint("/get-session", {
|
|
|
129
129
|
const updateAge = cookieRefreshCache.updateAge * 1e3;
|
|
130
130
|
const shouldSkipSessionRefresh = await getShouldSkipSessionRefresh();
|
|
131
131
|
if (timeUntilExpiry < updateAge && !shouldSkipSessionRefresh) {
|
|
132
|
-
const newExpiresAt = getDate(ctx.context.options.session?.cookieCache?.maxAge || 300, "sec");
|
|
133
132
|
const refreshedSession = {
|
|
134
|
-
session: {
|
|
135
|
-
...session.session,
|
|
136
|
-
expiresAt: newExpiresAt
|
|
137
|
-
},
|
|
133
|
+
session: { ...session.session },
|
|
138
134
|
user: session.user,
|
|
139
135
|
updatedAt: Date.now()
|
|
140
136
|
};
|
|
@@ -276,17 +272,26 @@ const getSessionFromCtx = async (ctx, config) => {
|
|
|
276
272
|
method: "GET",
|
|
277
273
|
asResponse: false,
|
|
278
274
|
headers: ctx.headers,
|
|
279
|
-
returnHeaders:
|
|
275
|
+
returnHeaders: true,
|
|
280
276
|
returnStatus: false,
|
|
281
277
|
query: {
|
|
282
278
|
...config,
|
|
283
279
|
...ctx.query
|
|
284
280
|
}
|
|
285
|
-
}).catch((
|
|
281
|
+
}).catch(() => {
|
|
286
282
|
return null;
|
|
287
283
|
});
|
|
288
|
-
|
|
289
|
-
|
|
284
|
+
if (!session) {
|
|
285
|
+
ctx.context.session = null;
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
if (session.headers) session.headers.forEach((value, key) => {
|
|
289
|
+
if (!ctx.context.responseHeaders) ctx.context.responseHeaders = new Headers({ [key]: value });
|
|
290
|
+
else if (key.toLowerCase() === "set-cookie") ctx.context.responseHeaders.append(key, value);
|
|
291
|
+
else ctx.context.responseHeaders.set(key, value);
|
|
292
|
+
});
|
|
293
|
+
ctx.context.session = session.response;
|
|
294
|
+
return session.response;
|
|
290
295
|
};
|
|
291
296
|
/**
|
|
292
297
|
* The middleware forces the endpoint to require a valid session.
|
|
@@ -440,7 +445,7 @@ const revokeSessions = createAuthEndpoint("/revoke-sessions", {
|
|
|
440
445
|
} }
|
|
441
446
|
}, async (ctx) => {
|
|
442
447
|
try {
|
|
443
|
-
await ctx.context.internalAdapter.
|
|
448
|
+
await ctx.context.internalAdapter.deleteUserSessions(ctx.context.session.user.id);
|
|
444
449
|
} catch (error) {
|
|
445
450
|
ctx.context.logger.error(error && typeof error === "object" && "name" in error ? error.name : "", error);
|
|
446
451
|
throw APIError.from("INTERNAL_SERVER_ERROR", {
|
|
@@ -27,6 +27,7 @@ declare const socialSignInBodySchema: z.ZodObject<{
|
|
|
27
27
|
scopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
28
28
|
requestSignUp: z.ZodOptional<z.ZodBoolean>;
|
|
29
29
|
loginHint: z.ZodOptional<z.ZodString>;
|
|
30
|
+
additionalParams: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
30
31
|
additionalData: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
31
32
|
}, z.core.$strip>;
|
|
32
33
|
declare const signInSocial: <O extends BetterAuthOptions>() => better_call0.StrictEndpoint<"/sign-in/social", {
|
|
@@ -55,6 +56,7 @@ declare const signInSocial: <O extends BetterAuthOptions>() => better_call0.Stri
|
|
|
55
56
|
scopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
56
57
|
requestSignUp: z.ZodOptional<z.ZodBoolean>;
|
|
57
58
|
loginHint: z.ZodOptional<z.ZodString>;
|
|
59
|
+
additionalParams: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
58
60
|
additionalData: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
59
61
|
}, z.core.$strip>;
|
|
60
62
|
metadata: {
|
|
@@ -91,7 +93,6 @@ declare const signInSocial: <O extends BetterAuthOptions>() => better_call0.Stri
|
|
|
91
93
|
};
|
|
92
94
|
redirect: {
|
|
93
95
|
type: string;
|
|
94
|
-
enum: boolean[];
|
|
95
96
|
};
|
|
96
97
|
};
|
|
97
98
|
required: string[];
|
|
@@ -115,6 +116,7 @@ declare const signInEmail: <O extends BetterAuthOptions>() => better_call0.Stric
|
|
|
115
116
|
method: "POST";
|
|
116
117
|
operationId: string;
|
|
117
118
|
use: ((inputContext: better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>) => Promise<void>)[];
|
|
119
|
+
cloneRequest: true;
|
|
118
120
|
body: z.ZodObject<{
|
|
119
121
|
email: z.ZodString;
|
|
120
122
|
password: z.ZodString;
|
|
@@ -2,10 +2,12 @@ import { formCsrfMiddleware } from "../middlewares/origin-check.mjs";
|
|
|
2
2
|
import { parseUserOutput } from "../../db/schema.mjs";
|
|
3
3
|
import { setSessionCookie } from "../../cookies/index.mjs";
|
|
4
4
|
import { getAwaitableValue } from "../../context/helpers.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { missingEmailLogMessage } from "../../oauth2/errors.mjs";
|
|
6
6
|
import { handleOAuthUserInfo } from "../../oauth2/link-account.mjs";
|
|
7
|
+
import { generateState } from "../../oauth2/state.mjs";
|
|
7
8
|
import { createEmailVerificationToken } from "./email-verification.mjs";
|
|
8
9
|
import { APIError, BASE_ERROR_CODES } from "@better-auth/core/error";
|
|
10
|
+
import { additionalAuthorizationParamsSchema } from "@better-auth/core/oauth2";
|
|
9
11
|
import { SocialProviderListEnum } from "@better-auth/core/social-providers";
|
|
10
12
|
import { createAuthEndpoint } from "@better-auth/core/api";
|
|
11
13
|
import * as z from "zod";
|
|
@@ -33,6 +35,7 @@ const socialSignInBodySchema = z.object({
|
|
|
33
35
|
scopes: z.array(z.string()).meta({ description: "Array of scopes to request from the provider. This will override the default scopes passed." }).optional(),
|
|
34
36
|
requestSignUp: z.boolean().meta({ description: "Explicitly request sign-up. Useful when disableImplicitSignUp is true for this provider" }).optional(),
|
|
35
37
|
loginHint: z.string().meta({ description: "The login hint to use for the authorization code request" }).optional(),
|
|
38
|
+
additionalParams: additionalAuthorizationParamsSchema,
|
|
36
39
|
additionalData: z.record(z.string(), z.any()).optional().meta({ description: "Additional data to be passed through the OAuth flow" })
|
|
37
40
|
});
|
|
38
41
|
const signInSocial = () => createAuthEndpoint("/sign-in/social", {
|
|
@@ -48,10 +51,10 @@ const signInSocial = () => createAuthEndpoint("/sign-in/social", {
|
|
|
48
51
|
description: "Sign in with a social provider",
|
|
49
52
|
operationId: "socialSignIn",
|
|
50
53
|
responses: { "200": {
|
|
51
|
-
description: "Success - Returns
|
|
54
|
+
description: "Success - Returns session details (idToken branch) or an authorize URL (redirect branch)",
|
|
52
55
|
content: { "application/json": { schema: {
|
|
53
56
|
type: "object",
|
|
54
|
-
description: "
|
|
57
|
+
description: "Returns session details when idToken is provided, or an authorize URL otherwise",
|
|
55
58
|
properties: {
|
|
56
59
|
token: { type: "string" },
|
|
57
60
|
user: {
|
|
@@ -59,16 +62,9 @@ const signInSocial = () => createAuthEndpoint("/sign-in/social", {
|
|
|
59
62
|
$ref: "#/components/schemas/User"
|
|
60
63
|
},
|
|
61
64
|
url: { type: "string" },
|
|
62
|
-
redirect: {
|
|
63
|
-
type: "boolean",
|
|
64
|
-
enum: [false]
|
|
65
|
-
}
|
|
65
|
+
redirect: { type: "boolean" }
|
|
66
66
|
},
|
|
67
|
-
required: [
|
|
68
|
-
"redirect",
|
|
69
|
-
"token",
|
|
70
|
-
"user"
|
|
71
|
-
]
|
|
67
|
+
required: ["redirect"]
|
|
72
68
|
} } }
|
|
73
69
|
} }
|
|
74
70
|
}
|
|
@@ -100,7 +96,7 @@ const signInSocial = () => createAuthEndpoint("/sign-in/social", {
|
|
|
100
96
|
throw APIError.from("UNAUTHORIZED", BASE_ERROR_CODES.FAILED_TO_GET_USER_INFO);
|
|
101
97
|
}
|
|
102
98
|
if (!userInfo.user.email) {
|
|
103
|
-
c.context.logger.error(
|
|
99
|
+
c.context.logger.error(missingEmailLogMessage(c.body.provider, { source: "id_token" }), { provider: c.body.provider });
|
|
104
100
|
throw APIError.from("UNAUTHORIZED", BASE_ERROR_CODES.USER_EMAIL_NOT_FOUND);
|
|
105
101
|
}
|
|
106
102
|
const data = await handleOAuthUserInfo(c, {
|
|
@@ -138,7 +134,8 @@ const signInSocial = () => createAuthEndpoint("/sign-in/social", {
|
|
|
138
134
|
codeVerifier,
|
|
139
135
|
redirectURI: `${c.context.baseURL}/callback/${provider.id}`,
|
|
140
136
|
scopes: c.body.scopes,
|
|
141
|
-
loginHint: c.body.loginHint
|
|
137
|
+
loginHint: c.body.loginHint,
|
|
138
|
+
additionalParams: c.body.additionalParams
|
|
142
139
|
});
|
|
143
140
|
if (!c.body.disableRedirect) c.setHeader("Location", url.toString());
|
|
144
141
|
return c.json({
|
|
@@ -150,6 +147,7 @@ const signInEmail = () => createAuthEndpoint("/sign-in/email", {
|
|
|
150
147
|
method: "POST",
|
|
151
148
|
operationId: "signInEmail",
|
|
152
149
|
use: [formCsrfMiddleware],
|
|
150
|
+
cloneRequest: true,
|
|
153
151
|
body: z.object({
|
|
154
152
|
email: z.string().meta({ description: "Email of the user" }),
|
|
155
153
|
password: z.string().meta({ description: "Password of the user" }),
|
|
@@ -242,7 +240,7 @@ const signInEmail = () => createAuthEndpoint("/sign-in/email", {
|
|
|
242
240
|
user: user.user,
|
|
243
241
|
url,
|
|
244
242
|
token
|
|
245
|
-
}, ctx.request));
|
|
243
|
+
}, ctx.request?.clone()));
|
|
246
244
|
}
|
|
247
245
|
throw APIError.from("FORBIDDEN", BASE_ERROR_CODES.EMAIL_NOT_VERIFIED);
|
|
248
246
|
}
|
|
@@ -16,6 +16,7 @@ declare const signUpEmail: <O extends BetterAuthOptions>() => better_call0.Stric
|
|
|
16
16
|
callbackURL: z.ZodOptional<z.ZodString>;
|
|
17
17
|
rememberMe: z.ZodOptional<z.ZodBoolean>;
|
|
18
18
|
}, z.core.$strip>, z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
19
|
+
cloneRequest: true;
|
|
19
20
|
metadata: {
|
|
20
21
|
allowedMediaTypes: string[];
|
|
21
22
|
$Infer: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isAPIError } from "../../utils/is-api-error.mjs";
|
|
2
2
|
import { formCsrfMiddleware } from "../middlewares/origin-check.mjs";
|
|
3
|
-
import { parseUserInput, parseUserOutput } from "../../db/schema.mjs";
|
|
3
|
+
import { buildSyntheticUserOutput, parseUserInput, parseUserOutput } from "../../db/schema.mjs";
|
|
4
4
|
import { setSessionCookie } from "../../cookies/index.mjs";
|
|
5
5
|
import { createEmailVerificationToken } from "./email-verification.mjs";
|
|
6
6
|
import { runWithTransaction } from "@better-auth/core/context";
|
|
@@ -23,6 +23,7 @@ const signUpEmail = () => createAuthEndpoint("/sign-up/email", {
|
|
|
23
23
|
operationId: "signUpWithEmailAndPassword",
|
|
24
24
|
use: [formCsrfMiddleware],
|
|
25
25
|
body: signUpEmailBodySchema,
|
|
26
|
+
cloneRequest: true,
|
|
26
27
|
metadata: {
|
|
27
28
|
allowedMediaTypes: ["application/x-www-form-urlencoded", "application/json"],
|
|
28
29
|
$Infer: {
|
|
@@ -157,7 +158,7 @@ const signUpEmail = () => createAuthEndpoint("/sign-up/email", {
|
|
|
157
158
|
ctx.context.logger.error("Password is too long");
|
|
158
159
|
throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.PASSWORD_TOO_LONG);
|
|
159
160
|
}
|
|
160
|
-
const shouldReturnGenericDuplicateResponse = ctx.context.options.emailAndPassword.requireEmailVerification;
|
|
161
|
+
const shouldReturnGenericDuplicateResponse = ctx.context.options.emailAndPassword.requireEmailVerification || ctx.context.options.emailAndPassword.autoSignIn === false;
|
|
161
162
|
const shouldSkipAutoSignIn = ctx.context.options.emailAndPassword.autoSignIn === false || shouldReturnGenericDuplicateResponse;
|
|
162
163
|
const additionalUserFields = parseUserInput(ctx.context.options, rest, "create");
|
|
163
164
|
const normalizedEmail = email.toLowerCase();
|
|
@@ -170,14 +171,14 @@ const signUpEmail = () => createAuthEndpoint("/sign-up/email", {
|
|
|
170
171
|
* between existing and non-existing emails.
|
|
171
172
|
*/
|
|
172
173
|
await ctx.context.password.hash(password);
|
|
173
|
-
if (ctx.context.options.emailAndPassword?.onExistingUserSignUp) await ctx.context.runInBackgroundOrAwait(ctx.context.options.emailAndPassword.onExistingUserSignUp({ user: dbUser.user }, ctx.request));
|
|
174
|
+
if (ctx.context.options.emailAndPassword?.onExistingUserSignUp) await ctx.context.runInBackgroundOrAwait(ctx.context.options.emailAndPassword.onExistingUserSignUp({ user: dbUser.user }, ctx.request?.clone()));
|
|
174
175
|
const now = /* @__PURE__ */ new Date();
|
|
175
176
|
const generatedId = ctx.context.generateId({ model: "user" }) || generateId();
|
|
176
177
|
const coreFields = {
|
|
177
178
|
name,
|
|
178
179
|
email: normalizedEmail,
|
|
179
180
|
emailVerified: false,
|
|
180
|
-
image: image
|
|
181
|
+
image: image ?? null,
|
|
181
182
|
createdAt: now,
|
|
182
183
|
updatedAt: now
|
|
183
184
|
};
|
|
@@ -187,16 +188,17 @@ const signUpEmail = () => createAuthEndpoint("/sign-up/email", {
|
|
|
187
188
|
const additionalFieldKeys = Object.keys(ctx.context.options.user?.additionalFields ?? {});
|
|
188
189
|
const additionalFields = {};
|
|
189
190
|
for (const key of additionalFieldKeys) if (key in additionalUserFields) additionalFields[key] = additionalUserFields[key];
|
|
190
|
-
|
|
191
|
+
const customResult = customSyntheticUser({
|
|
191
192
|
coreFields,
|
|
192
193
|
additionalFields,
|
|
193
194
|
id: generatedId
|
|
194
195
|
});
|
|
195
|
-
|
|
196
|
+
syntheticUser = buildSyntheticUserOutput(ctx.context.options, customResult);
|
|
197
|
+
} else syntheticUser = buildSyntheticUserOutput(ctx.context.options, {
|
|
196
198
|
...coreFields,
|
|
197
199
|
...additionalUserFields,
|
|
198
200
|
id: generatedId
|
|
199
|
-
};
|
|
201
|
+
});
|
|
200
202
|
return ctx.json({
|
|
201
203
|
token: null,
|
|
202
204
|
user: parseUserOutput(ctx.context.options, syntheticUser)
|
|
@@ -244,7 +246,7 @@ const signUpEmail = () => createAuthEndpoint("/sign-up/email", {
|
|
|
244
246
|
user: createdUser,
|
|
245
247
|
url,
|
|
246
248
|
token
|
|
247
|
-
}, ctx.request));
|
|
249
|
+
}, ctx.request?.clone()));
|
|
248
250
|
}
|
|
249
251
|
if (shouldSkipAutoSignIn) return ctx.json({
|
|
250
252
|
token: null,
|
|
@@ -168,7 +168,7 @@ const changePassword = createAuthEndpoint("/change-password", {
|
|
|
168
168
|
await ctx.context.internalAdapter.updateAccount(account.id, { password: passwordHash });
|
|
169
169
|
let token = null;
|
|
170
170
|
if (revokeOtherSessions) {
|
|
171
|
-
await ctx.context.internalAdapter.
|
|
171
|
+
await ctx.context.internalAdapter.deleteUserSessions(session.user.id);
|
|
172
172
|
const newSession = await ctx.context.internalAdapter.createSession(session.user.id);
|
|
173
173
|
if (!newSession) throw APIError.from("INTERNAL_SERVER_ERROR", BASE_ERROR_CODES.FAILED_TO_GET_SESSION);
|
|
174
174
|
await setSessionCookie(ctx, {
|
|
@@ -309,7 +309,7 @@ const deleteUser = createAuthEndpoint("/delete-user", {
|
|
|
309
309
|
const beforeDelete = ctx.context.options.user.deleteUser?.beforeDelete;
|
|
310
310
|
if (beforeDelete) await beforeDelete(session.user, ctx.request);
|
|
311
311
|
await ctx.context.internalAdapter.deleteUser(session.user.id);
|
|
312
|
-
await ctx.context.internalAdapter.
|
|
312
|
+
await ctx.context.internalAdapter.deleteUserSessions(session.user.id);
|
|
313
313
|
deleteSessionCookie(ctx);
|
|
314
314
|
const afterDelete = ctx.context.options.user.deleteUser?.afterDelete;
|
|
315
315
|
if (afterDelete) await afterDelete(session.user, ctx.request);
|
|
@@ -362,7 +362,7 @@ const deleteUserCallback = createAuthEndpoint("/delete-user/callback", {
|
|
|
362
362
|
const beforeDelete = ctx.context.options.user.deleteUser?.beforeDelete;
|
|
363
363
|
if (beforeDelete) await beforeDelete(session.user, ctx.request);
|
|
364
364
|
await ctx.context.internalAdapter.deleteUser(session.user.id);
|
|
365
|
-
await ctx.context.internalAdapter.
|
|
365
|
+
await ctx.context.internalAdapter.deleteUserSessions(session.user.id);
|
|
366
366
|
await ctx.context.internalAdapter.deleteAccounts(session.user.id);
|
|
367
367
|
await ctx.context.internalAdapter.deleteVerificationByIdentifier(`delete-account-${ctx.query.token}`);
|
|
368
368
|
deleteSessionCookie(ctx);
|
|
@@ -410,7 +410,7 @@ const changeEmail = createAuthEndpoint("/change-email", {
|
|
|
410
410
|
}, async (ctx) => {
|
|
411
411
|
if (!ctx.context.options.user?.changeEmail?.enabled) {
|
|
412
412
|
ctx.context.logger.error("Change email is disabled.");
|
|
413
|
-
throw APIError.
|
|
413
|
+
throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.CHANGE_EMAIL_DISABLED);
|
|
414
414
|
}
|
|
415
415
|
const newEmail = ctx.body.newEmail.toLowerCase();
|
|
416
416
|
if (newEmail === ctx.context.session.user.email) {
|
|
@@ -424,8 +424,8 @@ const changeEmail = createAuthEndpoint("/change-email", {
|
|
|
424
424
|
* email would later throw 400, leaking email existence.
|
|
425
425
|
*/
|
|
426
426
|
const canUpdateWithoutVerification = ctx.context.session.user.emailVerified !== true && ctx.context.options.user.changeEmail.updateEmailWithoutVerification;
|
|
427
|
-
const canSendConfirmation = ctx.context.session.user.emailVerified && ctx.context.options.user.changeEmail.sendChangeEmailConfirmation;
|
|
428
427
|
const canSendVerification = ctx.context.options.emailVerification?.sendVerificationEmail;
|
|
428
|
+
const canSendConfirmation = canSendVerification && ctx.context.session.user.emailVerified && ctx.context.options.user.changeEmail.sendChangeEmailConfirmation;
|
|
429
429
|
if (!canUpdateWithoutVerification && !canSendConfirmation && !canSendVerification) {
|
|
430
430
|
ctx.context.logger.error("Verification email isn't enabled.");
|
|
431
431
|
throw APIError.fromStatus("BAD_REQUEST", { message: "Verification email isn't enabled" });
|
|
@@ -449,7 +449,7 @@ const changeEmail = createAuthEndpoint("/change-email", {
|
|
|
449
449
|
});
|
|
450
450
|
if (canSendVerification) {
|
|
451
451
|
const token = await createEmailVerificationToken(ctx.context.secret, newEmail, void 0, ctx.context.options.emailVerification?.expiresIn);
|
|
452
|
-
const url = `${ctx.context.baseURL}/verify-email?token=${token}&callbackURL=${ctx.body.callbackURL || "/"}`;
|
|
452
|
+
const url = `${ctx.context.baseURL}/verify-email?token=${token}&callbackURL=${encodeURIComponent(ctx.body.callbackURL || "/")}`;
|
|
453
453
|
await ctx.context.runInBackgroundOrAwait(canSendVerification({
|
|
454
454
|
user: {
|
|
455
455
|
...ctx.context.session.user,
|
|
@@ -466,7 +466,7 @@ const changeEmail = createAuthEndpoint("/change-email", {
|
|
|
466
466
|
*/
|
|
467
467
|
if (canSendConfirmation) {
|
|
468
468
|
const token = await createEmailVerificationToken(ctx.context.secret, ctx.context.session.user.email, newEmail, ctx.context.options.emailVerification?.expiresIn, { requestType: "change-email-confirmation" });
|
|
469
|
-
const url = `${ctx.context.baseURL}/verify-email?token=${token}&callbackURL=${ctx.body.callbackURL || "/"}`;
|
|
469
|
+
const url = `${ctx.context.baseURL}/verify-email?token=${token}&callbackURL=${encodeURIComponent(ctx.body.callbackURL || "/")}`;
|
|
470
470
|
await ctx.context.runInBackgroundOrAwait(canSendConfirmation({
|
|
471
471
|
user: ctx.context.session.user,
|
|
472
472
|
newEmail,
|
|
@@ -480,7 +480,7 @@ const changeEmail = createAuthEndpoint("/change-email", {
|
|
|
480
480
|
throw APIError.fromStatus("BAD_REQUEST", { message: "Verification email isn't enabled" });
|
|
481
481
|
}
|
|
482
482
|
const token = await createEmailVerificationToken(ctx.context.secret, ctx.context.session.user.email, newEmail, ctx.context.options.emailVerification?.expiresIn, { requestType: "change-email-verification" });
|
|
483
|
-
const url = `${ctx.context.baseURL}/verify-email?token=${token}&callbackURL=${ctx.body.callbackURL || "/"}`;
|
|
483
|
+
const url = `${ctx.context.baseURL}/verify-email?token=${token}&callbackURL=${encodeURIComponent(ctx.body.callbackURL || "/")}`;
|
|
484
484
|
await ctx.context.runInBackgroundOrAwait(canSendVerification({
|
|
485
485
|
user: {
|
|
486
486
|
...ctx.context.session.user,
|
|
@@ -117,7 +117,13 @@ function toAuthEndpoints(endpoints, ctx) {
|
|
|
117
117
|
* headers override while cookies accumulate.
|
|
118
118
|
*/
|
|
119
119
|
const ctxHeaders = e[kAPIErrorHeaderSymbol];
|
|
120
|
-
|
|
120
|
+
/**
|
|
121
|
+
* `c.redirect()` (and similar APIError throws) reuse
|
|
122
|
+
* `ctx.responseHeaders` as `e.headers`, so when both sources
|
|
123
|
+
* reference the same Headers, iterating both duplicates every
|
|
124
|
+
* `set-cookie`. Skip the `errHeaders` copy in that case.
|
|
125
|
+
*/
|
|
126
|
+
const errHeaders = e.headers && e.headers !== ctxHeaders ? new Headers(e.headers) : null;
|
|
121
127
|
let headers = null;
|
|
122
128
|
if (ctxHeaders || errHeaders) {
|
|
123
129
|
headers = new Headers();
|
package/dist/auth/base.mjs
CHANGED
|
@@ -7,38 +7,41 @@ import { BASE_ERROR_CODES, BetterAuthError } from "@better-auth/core/error";
|
|
|
7
7
|
const createBetterAuth = (options, initFn) => {
|
|
8
8
|
const authContext = initFn(options);
|
|
9
9
|
const { api } = getEndpoints(authContext, options);
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
10
|
+
const errorCodes = options.plugins?.reduce((acc, plugin) => {
|
|
11
|
+
if (plugin.$ERROR_CODES) return {
|
|
12
|
+
...acc,
|
|
13
|
+
...plugin.$ERROR_CODES
|
|
14
|
+
};
|
|
15
|
+
return acc;
|
|
16
|
+
}, {});
|
|
17
|
+
const handler = async (request) => {
|
|
18
|
+
const ctx = await authContext;
|
|
19
|
+
const basePath = ctx.options.basePath || "/api/auth";
|
|
20
|
+
let handlerCtx;
|
|
21
|
+
if (isDynamicBaseURLConfig(options.baseURL)) handlerCtx = await resolveRequestContext(ctx, request, resolveDynamicTrustedProxyHeaders(ctx.options));
|
|
22
|
+
else {
|
|
23
|
+
handlerCtx = ctx;
|
|
24
|
+
if (!ctx.options.baseURL) {
|
|
25
|
+
const baseURL = getBaseURL(void 0, basePath, request, void 0, ctx.options.advanced?.trustedProxyHeaders);
|
|
26
|
+
if (baseURL) {
|
|
27
|
+
ctx.baseURL = baseURL;
|
|
28
|
+
ctx.options.baseURL = getOrigin(ctx.baseURL) || void 0;
|
|
29
|
+
} else throw new BetterAuthError("Could not get base URL from request. Please provide a valid base URL.");
|
|
27
30
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
+
handlerCtx.trustedOrigins = await getTrustedOrigins(ctx.options, request);
|
|
32
|
+
handlerCtx.trustedProviders = await getTrustedProviders(ctx.options, request);
|
|
33
|
+
}
|
|
34
|
+
const { handler } = router(handlerCtx, options);
|
|
35
|
+
return runWithAdapter(handlerCtx.adapter, () => handler(request));
|
|
36
|
+
};
|
|
37
|
+
return {
|
|
38
|
+
handler,
|
|
39
|
+
fetch: handler,
|
|
31
40
|
api,
|
|
32
41
|
options,
|
|
33
42
|
$context: authContext,
|
|
34
43
|
$ERROR_CODES: {
|
|
35
|
-
...
|
|
36
|
-
if (plugin.$ERROR_CODES) return {
|
|
37
|
-
...acc,
|
|
38
|
-
...plugin.$ERROR_CODES
|
|
39
|
-
};
|
|
40
|
-
return acc;
|
|
41
|
-
}, {}),
|
|
44
|
+
...errorCodes,
|
|
42
45
|
...BASE_ERROR_CODES
|
|
43
46
|
}
|
|
44
47
|
};
|
package/dist/client/config.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getBaseURL } from "../utils/url.mjs";
|
|
2
2
|
import { parseJSON } from "./parser.mjs";
|
|
3
3
|
import { redirectPlugin } from "./fetch-plugins.mjs";
|
|
4
|
-
import { getSessionAtom } from "./session-atom.mjs";
|
|
4
|
+
import { getSessionAtom, hydrateSessionAtom } from "./session-atom.mjs";
|
|
5
5
|
import { defu } from "defu";
|
|
6
6
|
import { createFetch } from "@better-fetch/fetch";
|
|
7
7
|
//#region src/client/config.ts
|
|
@@ -52,6 +52,12 @@ const getClientConfig = (options, loadEnv) => {
|
|
|
52
52
|
]
|
|
53
53
|
});
|
|
54
54
|
const { $sessionSignal, session, broadcastSessionUpdate } = getSessionAtom($fetch, options);
|
|
55
|
+
let hasHydrated = false;
|
|
56
|
+
const hydrateSession = (sessionData) => {
|
|
57
|
+
if (hasHydrated || sessionData === null) return;
|
|
58
|
+
hasHydrated = true;
|
|
59
|
+
hydrateSessionAtom(session, sessionData);
|
|
60
|
+
};
|
|
55
61
|
const plugins = options?.plugins || [];
|
|
56
62
|
let pluginsActions = {};
|
|
57
63
|
const pluginsAtoms = {
|
|
@@ -97,6 +103,7 @@ const getClientConfig = (options, loadEnv) => {
|
|
|
97
103
|
pluginsAtoms,
|
|
98
104
|
pluginPathMethods,
|
|
99
105
|
atomListeners,
|
|
106
|
+
hydrateSession,
|
|
100
107
|
$fetch,
|
|
101
108
|
$store
|
|
102
109
|
};
|