better-auth 1.6.1 → 1.6.3
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/dist/api/index.d.mts +0 -2
- package/dist/api/routes/account.mjs +1 -1
- package/dist/api/routes/callback.mjs +2 -2
- package/dist/api/routes/email-verification.mjs +1 -1
- package/dist/api/routes/password.mjs +1 -1
- package/dist/api/routes/session.d.mts +0 -1
- package/dist/api/routes/session.mjs +3 -4
- package/dist/api/routes/sign-in.mjs +1 -1
- package/dist/api/to-auth-endpoints.mjs +27 -3
- package/dist/auth/base.mjs +5 -24
- package/dist/client/plugins/index.d.mts +2 -2
- package/dist/client/query.mjs +4 -4
- package/dist/context/create-context.mjs +2 -2
- package/dist/context/helpers.mjs +61 -3
- package/dist/cookies/index.mjs +3 -3
- package/dist/crypto/index.mjs +2 -2
- package/dist/db/index.mjs +1 -1
- package/dist/db/internal-adapter.mjs +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/integrations/next-js.mjs +21 -12
- package/dist/oauth2/state.d.mts +1 -0
- package/dist/package.mjs +1 -1
- package/dist/plugins/admin/admin.d.mts +1 -3
- package/dist/plugins/admin/routes.mjs +2 -8
- package/dist/plugins/device-authorization/routes.mjs +1 -1
- package/dist/plugins/email-otp/routes.mjs +1 -1
- package/dist/plugins/index.d.mts +2 -2
- package/dist/plugins/jwt/utils.mjs +1 -1
- package/dist/plugins/mcp/index.mjs +20 -8
- package/dist/plugins/oauth-proxy/index.mjs +5 -1
- package/dist/plugins/oidc-provider/index.mjs +2 -2
- package/dist/plugins/organization/organization.d.mts +1 -3
- package/dist/plugins/organization/organization.mjs +1 -7
- package/dist/plugins/organization/routes/crud-invites.mjs +1 -1
- package/dist/plugins/organization/routes/crud-org.mjs +1 -1
- package/dist/plugins/organization/routes/crud-team.mjs +1 -1
- package/dist/plugins/phone-number/routes.mjs +1 -1
- package/dist/plugins/two-factor/backup-codes/index.d.mts +2 -1
- package/dist/plugins/two-factor/backup-codes/index.mjs +12 -17
- package/dist/plugins/two-factor/client.d.mts +12 -2
- package/dist/plugins/two-factor/client.mjs +1 -1
- package/dist/plugins/two-factor/index.d.mts +9 -2
- package/dist/plugins/two-factor/index.mjs +35 -3
- package/dist/plugins/two-factor/otp/index.mjs +1 -1
- package/dist/plugins/two-factor/schema.d.mts +6 -0
- package/dist/plugins/two-factor/schema.mjs +6 -0
- package/dist/plugins/two-factor/totp/index.mjs +19 -10
- package/dist/plugins/two-factor/types.d.mts +1 -1
- package/dist/state.d.mts +6 -0
- package/dist/state.mjs +18 -2
- package/dist/test-utils/test-instance.d.mts +0 -6
- package/dist/test-utils/test-instance.mjs +7 -1
- package/dist/utils/index.d.mts +1 -1
- package/dist/utils/url.d.mts +22 -15
- package/dist/utils/url.mjs +54 -28
- package/package.json +9 -9
package/dist/api/index.d.mts
CHANGED
|
@@ -249,7 +249,6 @@ declare function getEndpoints<Option extends BetterAuthOptions>(ctx: Awaitable<A
|
|
|
249
249
|
"application/json": {
|
|
250
250
|
schema: {
|
|
251
251
|
type: "object";
|
|
252
|
-
nullable: boolean;
|
|
253
252
|
properties: {
|
|
254
253
|
session: {
|
|
255
254
|
$ref: string;
|
|
@@ -2239,7 +2238,6 @@ declare const router: <Option extends BetterAuthOptions>(ctx: AuthContext, optio
|
|
|
2239
2238
|
"application/json": {
|
|
2240
2239
|
schema: {
|
|
2241
2240
|
type: "object";
|
|
2242
|
-
nullable: boolean;
|
|
2243
2241
|
properties: {
|
|
2244
2242
|
session: {
|
|
2245
2243
|
$ref: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { parseAccountOutput } from "../../db/schema.mjs";
|
|
2
|
-
import { getAwaitableValue } from "../../context/helpers.mjs";
|
|
3
2
|
import { getAccountCookie, setAccountCookie } from "../../cookies/session-store.mjs";
|
|
3
|
+
import { getAwaitableValue } from "../../context/helpers.mjs";
|
|
4
4
|
import { generateState } from "../../oauth2/state.mjs";
|
|
5
5
|
import { decryptOAuthToken, setTokenUtil } from "../../oauth2/utils.mjs";
|
|
6
6
|
import { freshSessionMiddleware, getSessionFromCtx, sessionMiddleware } from "./session.mjs";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { getAwaitableValue } from "../../context/helpers.mjs";
|
|
2
1
|
import { setSessionCookie } from "../../cookies/index.mjs";
|
|
2
|
+
import { getAwaitableValue } from "../../context/helpers.mjs";
|
|
3
3
|
import { parseState } from "../../oauth2/state.mjs";
|
|
4
4
|
import { setTokenUtil } from "../../oauth2/utils.mjs";
|
|
5
5
|
import { handleOAuthUserInfo } from "../../oauth2/link-account.mjs";
|
|
@@ -104,7 +104,7 @@ const callbackOAuth = createAuthEndpoint("/callback/:id", {
|
|
|
104
104
|
return redirectOnError("unable_to_link_account");
|
|
105
105
|
}
|
|
106
106
|
if (userInfo.email?.toLowerCase() !== link.email.toLowerCase() && c.context.options.account?.accountLinking?.allowDifferentEmails !== true) return redirectOnError("email_doesn't_match");
|
|
107
|
-
const existingAccount = await c.context.internalAdapter.
|
|
107
|
+
const existingAccount = await c.context.internalAdapter.findAccountByProviderId(String(userInfo.id), provider.id);
|
|
108
108
|
if (existingAccount) {
|
|
109
109
|
if (existingAccount.userId.toString() !== link.userId.toString()) return redirectOnError("account_already_linked_to_different_user");
|
|
110
110
|
const updateData = Object.fromEntries(Object.entries({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { originCheck } from "../middlewares/origin-check.mjs";
|
|
2
|
-
import { parseUserOutput } from "../../db/schema.mjs";
|
|
3
2
|
import { signJWT } from "../../crypto/jwt.mjs";
|
|
3
|
+
import { parseUserOutput } from "../../db/schema.mjs";
|
|
4
4
|
import { setSessionCookie } from "../../cookies/index.mjs";
|
|
5
5
|
import { getSessionFromCtx } from "./session.mjs";
|
|
6
6
|
import { APIError, BASE_ERROR_CODES } from "@better-auth/core/error";
|
|
@@ -82,7 +82,7 @@ const requestPasswordReset = createAuthEndpoint("/request-password-reset", {
|
|
|
82
82
|
});
|
|
83
83
|
const requestPasswordResetCallback = createAuthEndpoint("/reset-password/:token", {
|
|
84
84
|
method: "GET",
|
|
85
|
-
operationId: "
|
|
85
|
+
operationId: "resetPasswordCallback",
|
|
86
86
|
query: z.object({ callbackURL: z.string().meta({ description: "The URL to redirect the user to reset their password" }) }),
|
|
87
87
|
use: [originCheck((ctx) => ctx.query.callbackURL)],
|
|
88
88
|
metadata: { openapi: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isAPIError } from "../../utils/is-api-error.mjs";
|
|
2
|
-
import { getDate } from "../../utils/date.mjs";
|
|
3
|
-
import { parseSessionOutput, parseUserOutput } from "../../db/schema.mjs";
|
|
4
2
|
import { symmetricDecodeJWT, verifyJWT } from "../../crypto/jwt.mjs";
|
|
3
|
+
import { parseSessionOutput, parseUserOutput } from "../../db/schema.mjs";
|
|
4
|
+
import { getDate } from "../../utils/date.mjs";
|
|
5
5
|
import { getChunkedCookie, getSessionQuerySchema } from "../../cookies/session-store.mjs";
|
|
6
6
|
import { deleteSessionCookie, expireCookie, setCookieCache, setSessionCookie } from "../../cookies/index.mjs";
|
|
7
7
|
import { getShouldSkipSessionRefresh } from "../state/should-session-refresh.mjs";
|
|
@@ -24,8 +24,7 @@ const getSession = () => createAuthEndpoint("/get-session", {
|
|
|
24
24
|
responses: { "200": {
|
|
25
25
|
description: "Success",
|
|
26
26
|
content: { "application/json": { schema: {
|
|
27
|
-
type: "object",
|
|
28
|
-
nullable: true,
|
|
27
|
+
type: ["object", "null"],
|
|
29
28
|
properties: {
|
|
30
29
|
session: { $ref: "#/components/schemas/Session" },
|
|
31
30
|
user: { $ref: "#/components/schemas/User" }
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { formCsrfMiddleware } from "../middlewares/origin-check.mjs";
|
|
2
2
|
import { parseUserOutput } from "../../db/schema.mjs";
|
|
3
|
-
import { getAwaitableValue } from "../../context/helpers.mjs";
|
|
4
3
|
import { setSessionCookie } from "../../cookies/index.mjs";
|
|
4
|
+
import { getAwaitableValue } from "../../context/helpers.mjs";
|
|
5
5
|
import { generateState } from "../../oauth2/state.mjs";
|
|
6
6
|
import { handleOAuthUserInfo } from "../../oauth2/link-account.mjs";
|
|
7
7
|
import { createEmailVerificationToken } from "./email-verification.mjs";
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { isAPIError } from "../utils/is-api-error.mjs";
|
|
2
|
+
import { isDynamicBaseURLConfig, isRequestLike } from "../utils/url.mjs";
|
|
3
|
+
import { pickSource, resolveDynamicTrustedProxyHeaders, resolveRequestContext } from "../context/helpers.mjs";
|
|
2
4
|
import { hasRequestState, runWithEndpointContext, runWithRequestState } from "@better-auth/core/context";
|
|
3
5
|
import { shouldPublishLog } from "@better-auth/core/env";
|
|
4
|
-
import { APIError } from "@better-auth/core/error";
|
|
6
|
+
import { APIError, BetterAuthError } from "@better-auth/core/error";
|
|
5
7
|
import { createDefu } from "defu";
|
|
6
8
|
import { ATTR_CONTEXT, ATTR_HOOK_TYPE, ATTR_HTTP_ROUTE, ATTR_OPERATION_ID, withSpan } from "@better-auth/core/instrumentation";
|
|
7
9
|
import { kAPIErrorHeaderSymbol, toResponse } from "better-call";
|
|
@@ -18,6 +20,27 @@ function getOperationId(endpoint, key) {
|
|
|
18
20
|
const opts = endpoint.options;
|
|
19
21
|
return opts.operationId ?? opts.metadata?.openapi?.operationId ?? key;
|
|
20
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Resolves the per-call `AuthContext` for endpoints with a dynamic `baseURL`.
|
|
25
|
+
*
|
|
26
|
+
* - `rawCtx.baseURL` already set: HTTP handler rehydrated upstream; return as-is.
|
|
27
|
+
* - Direct `auth.api` call with a source or a configured `fallback`: resolve here.
|
|
28
|
+
* - Neither: throw `APIError` with a helpful message. Leaving `baseURL = ""`
|
|
29
|
+
* would let plugins build `new URL("")` and crash cryptically downstream.
|
|
30
|
+
*/
|
|
31
|
+
async function resolveDynamicContext(rawCtx, input) {
|
|
32
|
+
if (rawCtx.baseURL) return rawCtx;
|
|
33
|
+
const source = pickSource(input);
|
|
34
|
+
const config = rawCtx.options.baseURL;
|
|
35
|
+
const hasFallback = isDynamicBaseURLConfig(config) && Boolean(config.fallback);
|
|
36
|
+
if (source === void 0 && !hasFallback) throw new APIError("INTERNAL_SERVER_ERROR", { message: "Dynamic baseURL could not be resolved for this direct auth.api call. Pass `headers: request.headers` (or `request`) to the call, or add `fallback` to your baseURL config." });
|
|
37
|
+
try {
|
|
38
|
+
return await resolveRequestContext(rawCtx, source, resolveDynamicTrustedProxyHeaders(rawCtx.options));
|
|
39
|
+
} catch (err) {
|
|
40
|
+
if (err instanceof BetterAuthError) throw new APIError("INTERNAL_SERVER_ERROR", { message: err.message });
|
|
41
|
+
throw err;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
21
44
|
function toAuthEndpoints(endpoints, ctx) {
|
|
22
45
|
const api = {};
|
|
23
46
|
for (const [key, endpoint] of Object.entries(endpoints)) {
|
|
@@ -26,9 +49,10 @@ function toAuthEndpoints(endpoints, ctx) {
|
|
|
26
49
|
const endpointMethod = endpoint?.options?.method;
|
|
27
50
|
const defaultMethod = Array.isArray(endpointMethod) ? endpointMethod[0] : endpointMethod;
|
|
28
51
|
const run = async () => {
|
|
29
|
-
const
|
|
52
|
+
const rawContext = await ctx;
|
|
30
53
|
const methodName = context?.method ?? context?.request?.method ?? defaultMethod ?? "?";
|
|
31
54
|
const route = endpoint.path ?? "/:virtual";
|
|
55
|
+
const authContext = isDynamicBaseURLConfig(rawContext.options.baseURL) ? await resolveDynamicContext(rawContext, context) : rawContext;
|
|
32
56
|
let internalContext = {
|
|
33
57
|
...context,
|
|
34
58
|
context: {
|
|
@@ -40,7 +64,7 @@ function toAuthEndpoints(endpoints, ctx) {
|
|
|
40
64
|
path: endpoint.path,
|
|
41
65
|
headers: context?.headers ? new Headers(context?.headers) : void 0
|
|
42
66
|
};
|
|
43
|
-
const hasRequest = context?.request
|
|
67
|
+
const hasRequest = isRequestLike(context?.request);
|
|
44
68
|
const shouldReturnResponse = context?.asResponse ?? hasRequest;
|
|
45
69
|
return withSpan(`${methodName} ${route}`, {
|
|
46
70
|
[ATTR_HTTP_ROUTE]: route,
|
package/dist/auth/base.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { getBaseURL, getOrigin, isDynamicBaseURLConfig
|
|
2
|
-
import { getTrustedOrigins, getTrustedProviders } from "../context/helpers.mjs";
|
|
3
|
-
import { createCookieGetter, getCookies } from "../cookies/index.mjs";
|
|
1
|
+
import { getBaseURL, getOrigin, isDynamicBaseURLConfig } from "../utils/url.mjs";
|
|
2
|
+
import { getTrustedOrigins, getTrustedProviders, resolveDynamicTrustedProxyHeaders, resolveRequestContext } from "../context/helpers.mjs";
|
|
4
3
|
import { getEndpoints, router } from "../api/index.mjs";
|
|
5
4
|
import { runWithAdapter } from "@better-auth/core/context";
|
|
6
5
|
import { BASE_ERROR_CODES, BetterAuthError } from "@better-auth/core/error";
|
|
@@ -13,26 +12,8 @@ const createBetterAuth = (options, initFn) => {
|
|
|
13
12
|
const ctx = await authContext;
|
|
14
13
|
const basePath = ctx.options.basePath || "/api/auth";
|
|
15
14
|
let handlerCtx;
|
|
16
|
-
if (isDynamicBaseURLConfig(options.baseURL))
|
|
17
|
-
|
|
18
|
-
const baseURL = resolveBaseURL(options.baseURL, basePath, request);
|
|
19
|
-
if (baseURL) {
|
|
20
|
-
handlerCtx.baseURL = baseURL;
|
|
21
|
-
handlerCtx.options = {
|
|
22
|
-
...ctx.options,
|
|
23
|
-
baseURL: getOrigin(baseURL) || void 0
|
|
24
|
-
};
|
|
25
|
-
} else throw new BetterAuthError("Could not resolve base URL from request. Check your allowedHosts config.");
|
|
26
|
-
const trustedOriginOptions = {
|
|
27
|
-
...handlerCtx.options,
|
|
28
|
-
baseURL: options.baseURL
|
|
29
|
-
};
|
|
30
|
-
handlerCtx.trustedOrigins = await getTrustedOrigins(trustedOriginOptions, request);
|
|
31
|
-
if (options.advanced?.crossSubDomainCookies?.enabled) {
|
|
32
|
-
handlerCtx.authCookies = getCookies(handlerCtx.options);
|
|
33
|
-
handlerCtx.createAuthCookie = createCookieGetter(handlerCtx.options);
|
|
34
|
-
}
|
|
35
|
-
} else {
|
|
15
|
+
if (isDynamicBaseURLConfig(options.baseURL)) handlerCtx = await resolveRequestContext(ctx, request, resolveDynamicTrustedProxyHeaders(ctx.options));
|
|
16
|
+
else {
|
|
36
17
|
handlerCtx = ctx;
|
|
37
18
|
if (!ctx.options.baseURL) {
|
|
38
19
|
const baseURL = getBaseURL(void 0, basePath, request, void 0, ctx.options.advanced?.trustedProxyHeaders);
|
|
@@ -42,8 +23,8 @@ const createBetterAuth = (options, initFn) => {
|
|
|
42
23
|
} else throw new BetterAuthError("Could not get base URL from request. Please provide a valid base URL.");
|
|
43
24
|
}
|
|
44
25
|
handlerCtx.trustedOrigins = await getTrustedOrigins(ctx.options, request);
|
|
26
|
+
handlerCtx.trustedProviders = await getTrustedProviders(ctx.options, request);
|
|
45
27
|
}
|
|
46
|
-
handlerCtx.trustedProviders = await getTrustedProviders(handlerCtx.options, request);
|
|
47
28
|
const { handler } = router(handlerCtx, options);
|
|
48
29
|
return runWithAdapter(handlerCtx.adapter, () => handler(request));
|
|
49
30
|
},
|
|
@@ -20,7 +20,7 @@ import { MULTI_SESSION_ERROR_CODES } from "../../plugins/multi-session/error-cod
|
|
|
20
20
|
import { MultiSessionConfig } from "../../plugins/multi-session/index.mjs";
|
|
21
21
|
import { OneTimeTokenOptions } from "../../plugins/one-time-token/index.mjs";
|
|
22
22
|
import { PhoneNumberOptions, UserWithPhoneNumber } from "../../plugins/phone-number/types.mjs";
|
|
23
|
-
import { BackupCodeOptions, backupCode2fa, generateBackupCodes, getBackupCodes, verifyBackupCode } from "../../plugins/two-factor/backup-codes/index.mjs";
|
|
23
|
+
import { BackupCodeOptions, backupCode2fa, encodeBackupCodes, generateBackupCodes, getBackupCodes, verifyBackupCode } from "../../plugins/two-factor/backup-codes/index.mjs";
|
|
24
24
|
import { OTPOptions, otp2fa } from "../../plugins/two-factor/otp/index.mjs";
|
|
25
25
|
import { TOTPOptions, totp2fa } from "../../plugins/two-factor/totp/index.mjs";
|
|
26
26
|
import { TwoFactorOptions, TwoFactorProvider, TwoFactorTable, UserWithTwoFactor } from "../../plugins/two-factor/types.mjs";
|
|
@@ -52,4 +52,4 @@ import { phoneNumberClient } from "../../plugins/phone-number/client.mjs";
|
|
|
52
52
|
import { siweClient } from "../../plugins/siwe/client.mjs";
|
|
53
53
|
import { usernameClient } from "../../plugins/username/client.mjs";
|
|
54
54
|
import { InferServerPlugin } from "./infer-plugin.mjs";
|
|
55
|
-
export { ADMIN_ERROR_CODES, ANONYMOUS_ERROR_CODES, AdminOptions, AnonymousOptions, AnonymousSession, Auth0Options, AuthorizationQuery, BackupCodeOptions, BaseOAuthProviderOptions, Client, CodeVerificationValue, EMAIL_OTP_ERROR_CODES, ExtractPluginField, GENERIC_OAUTH_ERROR_CODES, GenericOAuthConfig, GenericOAuthOptions, GoogleOneTapActionOptions, GoogleOneTapOptions, GsiButtonConfiguration, GumroadOptions, HasRequiredKeys, HubSpotOptions, InferAdminRolesFromOption, InferInvitation, InferMember, InferOrganization, InferOrganizationRolesFromOption, InferOrganizationZodRolesFromOption, InferPluginFieldFromTuple, InferServerPlugin, InferTeam, Invitation, InvitationInput, InvitationStatus, IsAny, JWKOptions, JWSAlgorithms, Jwk, JwtOptions, KeycloakOptions, LastLoginMethodClientConfig, LineOptions, MULTI_SESSION_ERROR_CODES, Member, MemberInput, MicrosoftEntraIdOptions, MultiSessionConfig, OAuthAccessToken, OIDCMetadata, OIDCOptions, ORGANIZATION_ERROR_CODES, OTPOptions, OidcClientPlugin, OktaOptions, OneTimeTokenOptions, Organization, OrganizationInput, OrganizationRole, OrganizationSchema, OverrideMerge, PHONE_NUMBER_ERROR_CODES, PatreonOptions, PhoneNumberOptions, Prettify, PrettifyDeep, RequiredKeysOf, SessionWithImpersonatedBy, SlackOptions, StripEmptyObjects, TOTPOptions, TWO_FACTOR_ERROR_CODES, Team, TeamInput, TeamMember, TeamMemberInput, TokenBody, TwoFactorOptions, TwoFactorProvider, TwoFactorTable, USERNAME_ERROR_CODES, UnionToIntersection, UserWithAnonymous, UserWithPhoneNumber, UserWithRole, UserWithTwoFactor, adminClient, anonymousClient, auth0, backupCode2fa, clientSideHasPermission, customSessionClient, defaultRolesSchema, deviceAuthorizationClient, emailOTPClient, generateBackupCodes, genericOAuthClient, getBackupCodes, gumroad, hubspot, inferAdditionalFields, inferOrgAdditionalFields, invitationSchema, invitationStatus, jwtClient, keycloak, lastLoginMethodClient, line, magicLinkClient, memberSchema, microsoftEntraId, multiSessionClient, oidcClient, okta, oneTapClient, oneTimeTokenClient, organizationClient, organizationRoleSchema, organizationSchema, otp2fa, patreon, phoneNumberClient, roleSchema, schema, siweClient, slack, teamMemberSchema, teamSchema, totp2fa, twoFactorClient, usernameClient, verifyBackupCode };
|
|
55
|
+
export { ADMIN_ERROR_CODES, ANONYMOUS_ERROR_CODES, AdminOptions, AnonymousOptions, AnonymousSession, Auth0Options, AuthorizationQuery, BackupCodeOptions, BaseOAuthProviderOptions, Client, CodeVerificationValue, EMAIL_OTP_ERROR_CODES, ExtractPluginField, GENERIC_OAUTH_ERROR_CODES, GenericOAuthConfig, GenericOAuthOptions, GoogleOneTapActionOptions, GoogleOneTapOptions, GsiButtonConfiguration, GumroadOptions, HasRequiredKeys, HubSpotOptions, InferAdminRolesFromOption, InferInvitation, InferMember, InferOrganization, InferOrganizationRolesFromOption, InferOrganizationZodRolesFromOption, InferPluginFieldFromTuple, InferServerPlugin, InferTeam, Invitation, InvitationInput, InvitationStatus, IsAny, JWKOptions, JWSAlgorithms, Jwk, JwtOptions, KeycloakOptions, LastLoginMethodClientConfig, LineOptions, MULTI_SESSION_ERROR_CODES, Member, MemberInput, MicrosoftEntraIdOptions, MultiSessionConfig, OAuthAccessToken, OIDCMetadata, OIDCOptions, ORGANIZATION_ERROR_CODES, OTPOptions, OidcClientPlugin, OktaOptions, OneTimeTokenOptions, Organization, OrganizationInput, OrganizationRole, OrganizationSchema, OverrideMerge, PHONE_NUMBER_ERROR_CODES, PatreonOptions, PhoneNumberOptions, Prettify, PrettifyDeep, RequiredKeysOf, SessionWithImpersonatedBy, SlackOptions, StripEmptyObjects, TOTPOptions, TWO_FACTOR_ERROR_CODES, Team, TeamInput, TeamMember, TeamMemberInput, TokenBody, TwoFactorOptions, TwoFactorProvider, TwoFactorTable, USERNAME_ERROR_CODES, UnionToIntersection, UserWithAnonymous, UserWithPhoneNumber, UserWithRole, UserWithTwoFactor, adminClient, anonymousClient, auth0, backupCode2fa, clientSideHasPermission, customSessionClient, defaultRolesSchema, deviceAuthorizationClient, emailOTPClient, encodeBackupCodes, generateBackupCodes, genericOAuthClient, getBackupCodes, gumroad, hubspot, inferAdditionalFields, inferOrgAdditionalFields, invitationSchema, invitationStatus, jwtClient, keycloak, lastLoginMethodClient, line, magicLinkClient, memberSchema, microsoftEntraId, multiSessionClient, oidcClient, okta, oneTapClient, oneTimeTokenClient, organizationClient, organizationRoleSchema, organizationSchema, otp2fa, patreon, phoneNumberClient, roleSchema, schema, siweClient, slack, teamMemberSchema, teamSchema, totp2fa, twoFactorClient, usernameClient, verifyBackupCode };
|
package/dist/client/query.mjs
CHANGED
|
@@ -72,15 +72,15 @@ const useAuthQuery = (initializedAtom, path, $fetch, options) => {
|
|
|
72
72
|
});
|
|
73
73
|
};
|
|
74
74
|
initializedAtom = Array.isArray(initializedAtom) ? initializedAtom : [initializedAtom];
|
|
75
|
-
let
|
|
75
|
+
let isInitialized = false;
|
|
76
76
|
for (const initAtom of initializedAtom) initAtom.subscribe(async () => {
|
|
77
77
|
if (isServer()) return;
|
|
78
|
-
if (
|
|
78
|
+
if (isInitialized) await fn();
|
|
79
79
|
else onMount(value, () => {
|
|
80
80
|
const timeoutId = setTimeout(async () => {
|
|
81
|
-
if (!
|
|
81
|
+
if (!isInitialized) {
|
|
82
|
+
isInitialized = true;
|
|
82
83
|
await fn();
|
|
83
|
-
isMounted = true;
|
|
84
84
|
}
|
|
85
85
|
}, 0);
|
|
86
86
|
return () => {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { getBaseURL, isDynamicBaseURLConfig } from "../utils/url.mjs";
|
|
2
2
|
import { matchesOriginPattern } from "../auth/trusted-origins.mjs";
|
|
3
|
-
import { createInternalAdapter } from "../db/internal-adapter.mjs";
|
|
4
3
|
import { isPromise } from "../utils/is-promise.mjs";
|
|
5
|
-
import { getInternalPlugins, getTrustedOrigins, getTrustedProviders, runPluginInit } from "./helpers.mjs";
|
|
6
4
|
import { hashPassword, verifyPassword } from "../crypto/password.mjs";
|
|
7
5
|
import { createCookieGetter, getCookies } from "../cookies/index.mjs";
|
|
6
|
+
import { createInternalAdapter } from "../db/internal-adapter.mjs";
|
|
7
|
+
import { getInternalPlugins, getTrustedOrigins, getTrustedProviders, runPluginInit } from "./helpers.mjs";
|
|
8
8
|
import { checkPassword } from "../utils/password.mjs";
|
|
9
9
|
import { checkEndpointConflicts } from "../api/index.mjs";
|
|
10
10
|
import { DEFAULT_SECRET } from "../utils/constants.mjs";
|
package/dist/context/helpers.mjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { getBaseURL, isDynamicBaseURLConfig } from "../utils/url.mjs";
|
|
2
|
-
import { createInternalAdapter } from "../db/internal-adapter.mjs";
|
|
1
|
+
import { getBaseURL, getOrigin, isDynamicBaseURLConfig, isRequestLike, resolveBaseURL } from "../utils/url.mjs";
|
|
3
2
|
import { isPromise } from "../utils/is-promise.mjs";
|
|
3
|
+
import { createCookieGetter, getCookies } from "../cookies/index.mjs";
|
|
4
|
+
import { createInternalAdapter } from "../db/internal-adapter.mjs";
|
|
4
5
|
import { env } from "@better-auth/core/env";
|
|
6
|
+
import { BetterAuthError } from "@better-auth/core/error";
|
|
5
7
|
import { defu } from "defu";
|
|
6
8
|
//#region src/context/helpers.ts
|
|
7
9
|
async function runPluginInit(context) {
|
|
@@ -80,6 +82,62 @@ async function getTrustedOrigins(options, request) {
|
|
|
80
82
|
if (envTrustedOrigins) trustedOrigins.push(...envTrustedOrigins.split(","));
|
|
81
83
|
return trustedOrigins.filter((v) => Boolean(v));
|
|
82
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Picks a `Request`-like or `Headers` value from a direct `auth.api` call.
|
|
87
|
+
* Headers are only accepted when they carry a host: without one, host
|
|
88
|
+
* resolution would fall back to `null` and the caller should use `fallback`
|
|
89
|
+
* or pass a `Request` instead.
|
|
90
|
+
*/
|
|
91
|
+
function pickSource(input) {
|
|
92
|
+
if (isRequestLike(input?.request)) return input.request;
|
|
93
|
+
if (!input?.headers) return void 0;
|
|
94
|
+
const headers = input.headers instanceof Headers ? input.headers : new Headers(input.headers);
|
|
95
|
+
if (!headers.has("host") && !headers.has("x-forwarded-host")) return;
|
|
96
|
+
return headers;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Returns the effective `trustedProxyHeaders` value for dynamic `baseURL`
|
|
100
|
+
* resolution. When the user hasn't set `advanced.trustedProxyHeaders`,
|
|
101
|
+
* proxy headers (`x-forwarded-host` / `x-forwarded-proto`) are trusted by
|
|
102
|
+
* default so deployments behind a reverse proxy work without extra config.
|
|
103
|
+
*/
|
|
104
|
+
function resolveDynamicTrustedProxyHeaders(options) {
|
|
105
|
+
return options.advanced?.trustedProxyHeaders ?? true;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Per-request clone with `baseURL`, `trustedOrigins`, `trustedProviders`
|
|
109
|
+
* and cookies rehydrated for the resolved host. Throws `BetterAuthError`
|
|
110
|
+
* when the URL cannot be resolved; callers on the direct-API path convert
|
|
111
|
+
* this to `APIError`.
|
|
112
|
+
*/
|
|
113
|
+
async function resolveRequestContext(ctx, source, trustedProxyHeaders) {
|
|
114
|
+
const dynamicBaseURLConfig = ctx.options.baseURL;
|
|
115
|
+
const baseURL = resolveBaseURL(dynamicBaseURLConfig, ctx.options.basePath || "/api/auth", source, void 0, trustedProxyHeaders);
|
|
116
|
+
if (!baseURL) throw new BetterAuthError("Could not resolve base URL from request. Check your allowedHosts config.");
|
|
117
|
+
const resolved = Object.create(Object.getPrototypeOf(ctx), Object.getOwnPropertyDescriptors(ctx));
|
|
118
|
+
resolved.baseURL = baseURL;
|
|
119
|
+
resolved.options = {
|
|
120
|
+
...ctx.options,
|
|
121
|
+
baseURL: getOrigin(baseURL) || void 0
|
|
122
|
+
};
|
|
123
|
+
const trustedOriginOptions = {
|
|
124
|
+
...resolved.options,
|
|
125
|
+
baseURL: dynamicBaseURLConfig
|
|
126
|
+
};
|
|
127
|
+
const needsRequest = typeof ctx.options.trustedOrigins === "function" || typeof ctx.options.account?.accountLinking?.trustedProviders === "function";
|
|
128
|
+
let callbackRequest;
|
|
129
|
+
if (needsRequest) if (isRequestLike(source)) callbackRequest = source;
|
|
130
|
+
else if (source) callbackRequest = new Request(baseURL, { headers: source });
|
|
131
|
+
else callbackRequest = void 0;
|
|
132
|
+
else callbackRequest = void 0;
|
|
133
|
+
resolved.trustedOrigins = await getTrustedOrigins(trustedOriginOptions, callbackRequest);
|
|
134
|
+
resolved.trustedProviders = await getTrustedProviders(resolved.options, callbackRequest);
|
|
135
|
+
if (ctx.options.advanced?.crossSubDomainCookies?.enabled) {
|
|
136
|
+
resolved.authCookies = getCookies(resolved.options);
|
|
137
|
+
resolved.createAuthCookie = createCookieGetter(resolved.options);
|
|
138
|
+
}
|
|
139
|
+
return resolved;
|
|
140
|
+
}
|
|
83
141
|
async function getAwaitableValue(arr, item) {
|
|
84
142
|
if (!arr) return void 0;
|
|
85
143
|
for (const val of arr) {
|
|
@@ -94,4 +152,4 @@ async function getTrustedProviders(options, request) {
|
|
|
94
152
|
return (await trustedProviders(request) ?? []).filter((v) => Boolean(v));
|
|
95
153
|
}
|
|
96
154
|
//#endregion
|
|
97
|
-
export { getAwaitableValue, getInternalPlugins, getTrustedOrigins, getTrustedProviders, runPluginInit };
|
|
155
|
+
export { getAwaitableValue, getInternalPlugins, getTrustedOrigins, getTrustedProviders, pickSource, resolveDynamicTrustedProxyHeaders, resolveRequestContext, runPluginInit };
|
package/dist/cookies/index.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { isDynamicBaseURLConfig } from "../utils/url.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { signJWT, symmetricDecodeJWT, symmetricEncodeJWT, verifyJWT } from "../crypto/jwt.mjs";
|
|
3
3
|
import { parseUserOutput } from "../db/schema.mjs";
|
|
4
|
+
import { getDate } from "../utils/date.mjs";
|
|
4
5
|
import { isPromise } from "../utils/is-promise.mjs";
|
|
5
|
-
import { signJWT, symmetricDecodeJWT, symmetricEncodeJWT, verifyJWT } from "../crypto/jwt.mjs";
|
|
6
|
-
import { createAccountStore, createSessionStore, getAccountCookie, getChunkedCookie, setAccountCookie } from "./session-store.mjs";
|
|
7
6
|
import { sec } from "../utils/time.mjs";
|
|
8
7
|
import { HOST_COOKIE_PREFIX, SECURE_COOKIE_PREFIX, parseSetCookieHeader, setCookieToHeader, splitSetCookieHeader, stripSecureCookiePrefix } from "./cookie-utils.mjs";
|
|
8
|
+
import { createAccountStore, createSessionStore, getAccountCookie, getChunkedCookie, setAccountCookie } from "./session-store.mjs";
|
|
9
9
|
import { env, isProduction } from "@better-auth/core/env";
|
|
10
10
|
import { BetterAuthError } from "@better-auth/core/error";
|
|
11
11
|
import { safeJSONParse } from "@better-auth/core/utils/json";
|
package/dist/crypto/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { constantTimeEqual } from "./buffer.mjs";
|
|
2
1
|
import { signJWT, symmetricDecodeJWT, symmetricEncodeJWT, verifyJWT } from "./jwt.mjs";
|
|
2
|
+
import { constantTimeEqual } from "./buffer.mjs";
|
|
3
3
|
import { hashPassword, verifyPassword } from "./password.mjs";
|
|
4
4
|
import { generateRandomString } from "./random.mjs";
|
|
5
|
-
import { createHash } from "@better-auth/utils/hash";
|
|
6
5
|
import { getWebcryptoSubtle } from "@better-auth/utils";
|
|
6
|
+
import { createHash } from "@better-auth/utils/hash";
|
|
7
7
|
import { xchacha20poly1305 } from "@noble/ciphers/chacha.js";
|
|
8
8
|
import { bytesToHex, hexToBytes, managedNonce, utf8ToBytes } from "@noble/ciphers/utils.js";
|
|
9
9
|
//#region src/crypto/index.ts
|
package/dist/db/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { __exportAll, __reExport } from "../_virtual/_rolldown/runtime.mjs";
|
|
2
2
|
import { getSchema } from "./get-schema.mjs";
|
|
3
|
-
import { convertFromDB, convertToDB } from "./field-converter.mjs";
|
|
4
3
|
import { getSessionDefaultFields, mergeSchema, parseAccountInput, parseAccountOutput, parseAdditionalUserInput, parseInputData, parseSessionInput, parseSessionOutput, parseUserInput, parseUserOutput } from "./schema.mjs";
|
|
4
|
+
import { convertFromDB, convertToDB } from "./field-converter.mjs";
|
|
5
5
|
import { getWithHooks } from "./with-hooks.mjs";
|
|
6
6
|
import { createInternalAdapter } from "./internal-adapter.mjs";
|
|
7
7
|
import { toZodSchema } from "./to-zod.mjs";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getIp } from "../utils/get-request-ip.mjs";
|
|
2
|
-
import { getDate } from "../utils/date.mjs";
|
|
3
2
|
import { getSessionDefaultFields, parseSessionOutput, parseUserOutput } from "./schema.mjs";
|
|
3
|
+
import { getDate } from "../utils/date.mjs";
|
|
4
4
|
import { getStorageOption, processIdentifier } from "./verification-token-storage.mjs";
|
|
5
5
|
import { getWithHooks } from "./with-hooks.mjs";
|
|
6
6
|
import { getCurrentAdapter, getCurrentAuthContext, runWithTransaction } from "@better-auth/core/context";
|
package/dist/index.d.mts
CHANGED
|
@@ -10,7 +10,7 @@ import { betterAuth } from "./auth/full.mjs";
|
|
|
10
10
|
import { generateState, parseState } from "./oauth2/state.mjs";
|
|
11
11
|
import { StateData, generateGenericState, parseGenericState } from "./state.mjs";
|
|
12
12
|
import { HIDE_METADATA } from "./utils/hide-metadata.mjs";
|
|
13
|
-
import { getBaseURL, getHost,
|
|
13
|
+
import { getBaseURL, getHost, getHostFromSource, getOrigin, getProtocol, getProtocolFromSource, isDynamicBaseURLConfig, isRequestLike, matchesHostPattern, resolveBaseURL, resolveDynamicBaseURL } from "./utils/url.mjs";
|
|
14
14
|
import { APIError } from "./api/index.mjs";
|
|
15
15
|
import { StandardSchemaV1 } from "@better-auth/core";
|
|
16
16
|
import { getCurrentAdapter } from "@better-auth/core/context";
|
|
@@ -27,4 +27,4 @@ export * from "@better-auth/core/utils/json";
|
|
|
27
27
|
export * from "@better-auth/core/social-providers";
|
|
28
28
|
export * from "better-call";
|
|
29
29
|
export * from "zod";
|
|
30
|
-
export { APIError, Account, AdditionalSessionFieldsInput, AdditionalUserFieldsInput, Auth, BetterAuthAdvancedOptions, BetterAuthClientOptions, BetterAuthClientPlugin, BetterAuthCookies, BetterAuthOptions, BetterAuthPlugin, BetterAuthRateLimitOptions, ClientAtomListener, ClientStore, DBAdapter, DBAdapterInstance, DBAdapterSchemaCreation, DBTransactionAdapter, ExtractPluginField, FilteredAPI, HIDE_METADATA, HasRequiredKeys, InferAPI, InferActions, InferAdditionalFromClient, InferClientAPI, InferErrorCodes, InferOptionSchema, InferPluginContext, InferPluginErrorCodes, InferPluginFieldFromTuple, InferPluginIDs, InferPluginTypes, InferSessionAPI, InferSessionFromClient, InferUserFromClient, IsAny, IsSignal, type JSONWebKeySet, type JWTPayload, JoinConfig, JoinOption, OverrideMerge, Prettify, PrettifyDeep, RateLimit, RequiredKeysOf, Session, SessionQueryParams, type StandardSchemaV1, StateData, StoreIdentifierOption, StripEmptyObjects, type TelemetryEvent, UnionToIntersection, User, Verification, Where, betterAuth, createTelemetry, generateGenericState, generateState, getBaseURL, getCurrentAdapter, getHost,
|
|
30
|
+
export { APIError, Account, AdditionalSessionFieldsInput, AdditionalUserFieldsInput, Auth, BetterAuthAdvancedOptions, BetterAuthClientOptions, BetterAuthClientPlugin, BetterAuthCookies, BetterAuthOptions, BetterAuthPlugin, BetterAuthRateLimitOptions, ClientAtomListener, ClientStore, DBAdapter, DBAdapterInstance, DBAdapterSchemaCreation, DBTransactionAdapter, ExtractPluginField, FilteredAPI, HIDE_METADATA, HasRequiredKeys, InferAPI, InferActions, InferAdditionalFromClient, InferClientAPI, InferErrorCodes, InferOptionSchema, InferPluginContext, InferPluginErrorCodes, InferPluginFieldFromTuple, InferPluginIDs, InferPluginTypes, InferSessionAPI, InferSessionFromClient, InferUserFromClient, IsAny, IsSignal, type JSONWebKeySet, type JWTPayload, JoinConfig, JoinOption, OverrideMerge, Prettify, PrettifyDeep, RateLimit, RequiredKeysOf, Session, SessionQueryParams, type StandardSchemaV1, StateData, StoreIdentifierOption, StripEmptyObjects, type TelemetryEvent, UnionToIntersection, User, Verification, Where, betterAuth, createTelemetry, generateGenericState, generateState, getBaseURL, getCurrentAdapter, getHost, getHostFromSource, getOrigin, getProtocol, getProtocolFromSource, getTelemetryAuthConfig, isDynamicBaseURLConfig, isRequestLike, matchesHostPattern, parseGenericState, parseState, resolveBaseURL, resolveDynamicBaseURL };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getBaseURL, getHost,
|
|
1
|
+
import { getBaseURL, getHost, getHostFromSource, getOrigin, getProtocol, getProtocolFromSource, isDynamicBaseURLConfig, isRequestLike, matchesHostPattern, resolveBaseURL, resolveDynamicBaseURL } from "./utils/url.mjs";
|
|
2
2
|
import { generateGenericState, parseGenericState } from "./state.mjs";
|
|
3
3
|
import { generateState, parseState } from "./oauth2/state.mjs";
|
|
4
4
|
import { HIDE_METADATA } from "./utils/hide-metadata.mjs";
|
|
@@ -14,4 +14,4 @@ export * from "@better-auth/core/oauth2";
|
|
|
14
14
|
export * from "@better-auth/core/utils/error-codes";
|
|
15
15
|
export * from "@better-auth/core/utils/id";
|
|
16
16
|
export * from "@better-auth/core/utils/json";
|
|
17
|
-
export { APIError, HIDE_METADATA, betterAuth, createTelemetry, generateGenericState, generateState, getBaseURL, getCurrentAdapter, getHost,
|
|
17
|
+
export { APIError, HIDE_METADATA, betterAuth, createTelemetry, generateGenericState, generateState, getBaseURL, getCurrentAdapter, getHost, getHostFromSource, getOrigin, getProtocol, getProtocolFromSource, getTelemetryAuthConfig, isDynamicBaseURLConfig, isRequestLike, matchesHostPattern, parseGenericState, parseState, resolveBaseURL, resolveDynamicBaseURL };
|
|
@@ -24,20 +24,29 @@ const nextCookies = () => {
|
|
|
24
24
|
matcher(ctx) {
|
|
25
25
|
return ctx.path === "/get-session";
|
|
26
26
|
},
|
|
27
|
-
handler: createAuthMiddleware(async () => {
|
|
28
|
-
|
|
27
|
+
handler: createAuthMiddleware(async (ctx) => {
|
|
28
|
+
if ("_flag" in ctx && ctx._flag === "router") return;
|
|
29
|
+
let headersStore;
|
|
29
30
|
try {
|
|
30
|
-
const {
|
|
31
|
-
|
|
31
|
+
const { headers } = await import("next/headers.js");
|
|
32
|
+
headersStore = await headers();
|
|
32
33
|
} catch {
|
|
33
34
|
return;
|
|
34
35
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Detect RSC via headers, NOT by probing cookies().set().
|
|
38
|
+
* In Next.js, cookies().set() unconditionally triggers router
|
|
39
|
+
* cache invalidation -- even if the value is unchanged.
|
|
40
|
+
*
|
|
41
|
+
* RSC sends `RSC: 1` without `next-action`. Only in that
|
|
42
|
+
* context cookies cannot be written -- skip session refresh
|
|
43
|
+
* to avoid DB/cookie mismatch.
|
|
44
|
+
*
|
|
45
|
+
* @see https://github.com/vercel/next.js/blob/8c5af211d580/packages/next/src/server/web/spec-extension/adapters/request-cookies.ts#L112-L157
|
|
46
|
+
*/
|
|
47
|
+
const isRSC = headersStore.get("RSC") === "1";
|
|
48
|
+
const isServerAction = !!headersStore.get("next-action");
|
|
49
|
+
if (isRSC && !isServerAction) await setShouldSkipSessionRefresh(true);
|
|
41
50
|
})
|
|
42
51
|
}],
|
|
43
52
|
after: [{
|
|
@@ -51,12 +60,12 @@ const nextCookies = () => {
|
|
|
51
60
|
const setCookies = returned?.get("set-cookie");
|
|
52
61
|
if (!setCookies) return;
|
|
53
62
|
const parsed = parseSetCookieHeader(setCookies);
|
|
54
|
-
const { cookies } = await import("next/headers.js");
|
|
55
63
|
let cookieHelper;
|
|
56
64
|
try {
|
|
65
|
+
const { cookies } = await import("next/headers.js");
|
|
57
66
|
cookieHelper = await cookies();
|
|
58
67
|
} catch (error) {
|
|
59
|
-
if (error instanceof Error && error.message.startsWith("`cookies` was called outside a request scope.")) return;
|
|
68
|
+
if (error instanceof Error && (error.message.startsWith("`cookies` was called outside a request scope.") || error.message.includes("Cannot find module"))) return;
|
|
60
69
|
throw error;
|
|
61
70
|
}
|
|
62
71
|
parsed.forEach((value, key) => {
|
package/dist/oauth2/state.d.mts
CHANGED
package/dist/package.mjs
CHANGED
|
@@ -775,11 +775,9 @@ declare const admin: <O extends AdminOptions>(options?: O | undefined) => {
|
|
|
775
775
|
body: zod.ZodIntersection<zod.ZodObject<{
|
|
776
776
|
userId: zod.ZodOptional<zod.ZodCoercedString<unknown>>;
|
|
777
777
|
role: zod.ZodOptional<zod.ZodString>;
|
|
778
|
-
}, zod_v4_core0.$strip>, zod.
|
|
778
|
+
}, zod_v4_core0.$strip>, zod.ZodXor<readonly [zod.ZodObject<{
|
|
779
779
|
permission: zod.ZodRecord<zod.ZodString, zod.ZodArray<zod.ZodString>>;
|
|
780
|
-
permissions: zod.ZodUndefined;
|
|
781
780
|
}, zod_v4_core0.$strip>, zod.ZodObject<{
|
|
782
|
-
permission: zod.ZodUndefined;
|
|
783
781
|
permissions: zod.ZodRecord<zod.ZodString, zod.ZodArray<zod.ZodString>>;
|
|
784
782
|
}, zod_v4_core0.$strip>]>>;
|
|
785
783
|
metadata: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { getDate } from "../../utils/date.mjs";
|
|
2
1
|
import { parseSessionOutput, parseUserOutput } from "../../db/schema.mjs";
|
|
2
|
+
import { getDate } from "../../utils/date.mjs";
|
|
3
3
|
import { deleteSessionCookie, expireCookie, setSessionCookie } from "../../cookies/index.mjs";
|
|
4
4
|
import { getSessionFromCtx } from "../../api/routes/session.mjs";
|
|
5
5
|
import { ADMIN_ERROR_CODES } from "./error-codes.mjs";
|
|
@@ -766,13 +766,7 @@ const setUserPassword = (opts) => createAuthEndpoint("/admin/set-user-password",
|
|
|
766
766
|
const userHasPermissionBodySchema = z.object({
|
|
767
767
|
userId: z.coerce.string().optional().meta({ description: `The user id. Eg: "user-id"` }),
|
|
768
768
|
role: z.string().optional().meta({ description: `The role to check permission for. Eg: "admin"` })
|
|
769
|
-
}).and(z.
|
|
770
|
-
permission: z.record(z.string(), z.array(z.string())),
|
|
771
|
-
permissions: z.undefined()
|
|
772
|
-
}), z.object({
|
|
773
|
-
permission: z.undefined(),
|
|
774
|
-
permissions: z.record(z.string(), z.array(z.string()))
|
|
775
|
-
})]));
|
|
769
|
+
}).and(z.xor([z.object({ permission: z.record(z.string(), z.array(z.string())) }), z.object({ permissions: z.record(z.string(), z.array(z.string())) })]));
|
|
776
770
|
/**
|
|
777
771
|
* ### Endpoint
|
|
778
772
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { generateRandomString } from "../../crypto/random.mjs";
|
|
2
1
|
import { ms } from "../../utils/time.mjs";
|
|
2
|
+
import { generateRandomString } from "../../crypto/random.mjs";
|
|
3
3
|
import { getSessionFromCtx } from "../../api/routes/session.mjs";
|
|
4
4
|
import { DEVICE_AUTHORIZATION_ERROR_CODES } from "./error-codes.mjs";
|
|
5
5
|
import { APIError } from "@better-auth/core/error";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { getDate } from "../../utils/date.mjs";
|
|
2
1
|
import { parseUserInput, parseUserOutput } from "../../db/schema.mjs";
|
|
2
|
+
import { getDate } from "../../utils/date.mjs";
|
|
3
3
|
import { generateRandomString } from "../../crypto/random.mjs";
|
|
4
4
|
import { symmetricDecrypt } from "../../crypto/index.mjs";
|
|
5
5
|
import { setCookieCache, setSessionCookie } from "../../cookies/index.mjs";
|
package/dist/plugins/index.d.mts
CHANGED
|
@@ -51,7 +51,7 @@ import { phoneNumber } from "./phone-number/index.mjs";
|
|
|
51
51
|
import { SIWEPluginOptions, siwe } from "./siwe/index.mjs";
|
|
52
52
|
import { LoginResult, TestCookie, TestHelpers, TestUtilsOptions } from "./test-utils/types.mjs";
|
|
53
53
|
import { testUtils } from "./test-utils/index.mjs";
|
|
54
|
-
import { BackupCodeOptions, backupCode2fa, generateBackupCodes, getBackupCodes, verifyBackupCode } from "./two-factor/backup-codes/index.mjs";
|
|
54
|
+
import { BackupCodeOptions, backupCode2fa, encodeBackupCodes, generateBackupCodes, getBackupCodes, verifyBackupCode } from "./two-factor/backup-codes/index.mjs";
|
|
55
55
|
import { OTPOptions, otp2fa } from "./two-factor/otp/index.mjs";
|
|
56
56
|
import { TOTPOptions, totp2fa } from "./two-factor/totp/index.mjs";
|
|
57
57
|
import { TwoFactorOptions, TwoFactorProvider, TwoFactorTable, UserWithTwoFactor } from "./two-factor/types.mjs";
|
|
@@ -62,4 +62,4 @@ import { USERNAME_ERROR_CODES } from "./username/error-codes.mjs";
|
|
|
62
62
|
import { UsernameOptions, username } from "./username/index.mjs";
|
|
63
63
|
import { hasPermission } from "./organization/has-permission.mjs";
|
|
64
64
|
import { DefaultOrganizationPlugin, DynamicAccessControlEndpoints, OrganizationCreator, OrganizationEndpoints, OrganizationPlugin, TeamEndpoints, organization, parseRoles } from "./organization/organization.mjs";
|
|
65
|
-
export { AccessControl, AdminOptions, AnonymousOptions, AnonymousSession, ArrayElement, Auth0Options, AuthorizationQuery, AuthorizeResponse, BackupCodeOptions, BaseCaptchaOptions, BaseOAuthProviderOptions, BearerOptions, CaptchaFoxOptions, CaptchaOptions, Client, CloudflareTurnstileOptions, CodeVerificationValue, CustomSessionPluginOptions, DefaultOrganizationPlugin, DeviceAuthorizationOptions, DynamicAccessControlEndpoints, MULTI_SESSION_ERROR_CODES as ERROR_CODES, EmailOTPOptions, FieldSchema, GenericOAuthConfig, GenericOAuthOptions, GoogleRecaptchaOptions, GumroadOptions, HCaptchaOptions, HIDE_METADATA, HaveIBeenPwnedOptions, HubSpotOptions, InferAdminRolesFromOption, InferInvitation, InferMember, InferOptionSchema, InferOrganization, InferOrganizationRolesFromOption, InferOrganizationZodRolesFromOption, InferPluginContext, InferPluginErrorCodes, InferPluginIDs, InferTeam, Invitation, InvitationInput, InvitationStatus, JWKOptions, JWSAlgorithms, Jwk, JwtOptions, KeycloakOptions, LastLoginMethodOptions, LineOptions, LoginResult, MagicLinkOptions, Member, MemberInput, MicrosoftEntraIdOptions, MultiSessionConfig, OAuthAccessToken, OAuthProxyOptions, OIDCMetadata, OIDCOptions, OTPOptions, OktaOptions, OneTapOptions, OneTimeTokenOptions, OpenAPIModelSchema, OpenAPIOptions, Organization, OrganizationCreator, OrganizationEndpoints, OrganizationInput, OrganizationOptions, OrganizationPlugin, OrganizationRole, OrganizationSchema, Path, PatreonOptions, PhoneNumberOptions, Provider, Role, SIWEPluginOptions, SessionWithImpersonatedBy, SlackOptions, Statements, SubArray, Subset, TOTPOptions, TWO_FACTOR_ERROR_CODES, Team, TeamEndpoints, TeamInput, TeamMember, TeamMemberInput, TestCookie, TestHelpers, TestUtilsOptions, TimeString, TokenBody, TwoFactorOptions, TwoFactorProvider, TwoFactorTable, USERNAME_ERROR_CODES, UserWithAnonymous, UserWithPhoneNumber, UserWithRole, UserWithTwoFactor, UsernameOptions, admin, anonymous, auth0, backupCode2fa, bearer, captcha, createAccessControl, createJwk, customSession, defaultRolesSchema, deviceAuthorization, deviceAuthorizationOptionsSchema, emailOTP, generateBackupCodes, generateExportedKeyPair, generator, genericOAuth, getBackupCodes, getClient, getJwtToken, getMCPProtectedResourceMetadata, getMCPProviderMetadata, getMetadata, getOrgAdapter, gumroad, hasPermission, haveIBeenPwned, hubspot, invitationSchema, invitationStatus, jwt, keycloak, lastLoginMethod, line, magicLink, mcp, memberSchema, microsoftEntraId, ms, multiSession, oAuthDiscoveryMetadata, oAuthProtectedResourceMetadata, oAuthProxy, oidcProvider, okta, oneTap, oneTimeToken, openAPI, organization, organizationRoleSchema, organizationSchema, otp2fa, parseRoles, patreon, phoneNumber, role, roleSchema, sec, signJWT, siwe, slack, teamMemberSchema, teamSchema, testUtils, toExpJWT, totp2fa, twoFactor, twoFactorClient, username, verifyBackupCode, verifyJWT, withMcpAuth };
|
|
65
|
+
export { AccessControl, AdminOptions, AnonymousOptions, AnonymousSession, ArrayElement, Auth0Options, AuthorizationQuery, AuthorizeResponse, BackupCodeOptions, BaseCaptchaOptions, BaseOAuthProviderOptions, BearerOptions, CaptchaFoxOptions, CaptchaOptions, Client, CloudflareTurnstileOptions, CodeVerificationValue, CustomSessionPluginOptions, DefaultOrganizationPlugin, DeviceAuthorizationOptions, DynamicAccessControlEndpoints, MULTI_SESSION_ERROR_CODES as ERROR_CODES, EmailOTPOptions, FieldSchema, GenericOAuthConfig, GenericOAuthOptions, GoogleRecaptchaOptions, GumroadOptions, HCaptchaOptions, HIDE_METADATA, HaveIBeenPwnedOptions, HubSpotOptions, InferAdminRolesFromOption, InferInvitation, InferMember, InferOptionSchema, InferOrganization, InferOrganizationRolesFromOption, InferOrganizationZodRolesFromOption, InferPluginContext, InferPluginErrorCodes, InferPluginIDs, InferTeam, Invitation, InvitationInput, InvitationStatus, JWKOptions, JWSAlgorithms, Jwk, JwtOptions, KeycloakOptions, LastLoginMethodOptions, LineOptions, LoginResult, MagicLinkOptions, Member, MemberInput, MicrosoftEntraIdOptions, MultiSessionConfig, OAuthAccessToken, OAuthProxyOptions, OIDCMetadata, OIDCOptions, OTPOptions, OktaOptions, OneTapOptions, OneTimeTokenOptions, OpenAPIModelSchema, OpenAPIOptions, Organization, OrganizationCreator, OrganizationEndpoints, OrganizationInput, OrganizationOptions, OrganizationPlugin, OrganizationRole, OrganizationSchema, Path, PatreonOptions, PhoneNumberOptions, Provider, Role, SIWEPluginOptions, SessionWithImpersonatedBy, SlackOptions, Statements, SubArray, Subset, TOTPOptions, TWO_FACTOR_ERROR_CODES, Team, TeamEndpoints, TeamInput, TeamMember, TeamMemberInput, TestCookie, TestHelpers, TestUtilsOptions, TimeString, TokenBody, TwoFactorOptions, TwoFactorProvider, TwoFactorTable, USERNAME_ERROR_CODES, UserWithAnonymous, UserWithPhoneNumber, UserWithRole, UserWithTwoFactor, UsernameOptions, admin, anonymous, auth0, backupCode2fa, bearer, captcha, createAccessControl, createJwk, customSession, defaultRolesSchema, deviceAuthorization, deviceAuthorizationOptionsSchema, emailOTP, encodeBackupCodes, generateBackupCodes, generateExportedKeyPair, generator, genericOAuth, getBackupCodes, getClient, getJwtToken, getMCPProtectedResourceMetadata, getMCPProviderMetadata, getMetadata, getOrgAdapter, gumroad, hasPermission, haveIBeenPwned, hubspot, invitationSchema, invitationStatus, jwt, keycloak, lastLoginMethod, line, magicLink, mcp, memberSchema, microsoftEntraId, ms, multiSession, oAuthDiscoveryMetadata, oAuthProtectedResourceMetadata, oAuthProxy, oidcProvider, okta, oneTap, oneTimeToken, openAPI, organization, organizationRoleSchema, organizationSchema, otp2fa, parseRoles, patreon, phoneNumber, role, roleSchema, sec, signJWT, siwe, slack, teamMemberSchema, teamSchema, testUtils, toExpJWT, totp2fa, twoFactor, twoFactorClient, username, verifyBackupCode, verifyJWT, withMcpAuth };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { symmetricEncrypt } from "../../crypto/index.mjs";
|
|
2
1
|
import { sec } from "../../utils/time.mjs";
|
|
2
|
+
import { symmetricEncrypt } from "../../crypto/index.mjs";
|
|
3
3
|
import { getJwksAdapter } from "./adapter.mjs";
|
|
4
4
|
import { exportJWK, generateKeyPair } from "jose";
|
|
5
5
|
//#region src/plugins/jwt/utils.ts
|