@protobase/server 0.48.0 → 0.49.1
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/admin-options.d.ts +2 -2
- package/dist/app-identity.d.ts +2 -2
- package/dist/app-name.d.ts +2 -0
- package/dist/better-auth/auth-settings.d.ts +8773 -0
- package/dist/better-auth/auth-settings.js +43 -0
- package/dist/better-auth/authenticate-settings.d.ts +15 -0
- package/dist/better-auth/authenticate-settings.js +12 -0
- package/dist/better-auth/create-auth.d.ts +51 -11
- package/dist/better-auth/create-auth.js +33 -11
- package/dist/better-auth/mcp/mcp-auth-plugins.d.ts +2719 -0
- package/dist/better-auth/mcp/mcp-auth-plugins.js +68 -0
- package/dist/better-auth/mcp/mcp-plugins.d.ts +7 -2
- package/dist/better-auth/mcp/mcp-plugins.js +3 -68
- package/dist/better-auth/mcp/mcp-token-claims.js +1 -1
- package/dist/better-auth/organizations/store.d.ts +1 -0
- package/dist/better-auth/saml-plugin.d.ts +993 -0
- package/dist/better-auth/saml-plugin.js +36 -0
- package/dist/better-auth/saml-sign-in.d.ts +27 -1
- package/dist/better-auth/saml-sign-in.js +1 -33
- package/dist/better-auth/secret-versions.d.ts +7 -0
- package/dist/better-auth/secret-versions.js +21 -0
- package/dist/better-auth/signing-keys.js +86 -0
- package/dist/better-auth/tokens.js +1 -0
- package/dist/better-auth/user-table.js +1 -1
- package/dist/better-auth/users.d.ts +1 -1
- package/dist/create-admin.d.ts +5 -3
- package/dist/create-admin.js +3 -1
- package/dist/encryption/keyring.js +1 -1
- package/dist/files/options.d.ts +5 -8
- package/dist/files/provider-settings.d.ts +16 -0
- package/dist/files/provider-settings.js +17 -0
- package/dist/files/runtime.js +4 -4
- package/dist/forms/runtime.js +3 -3
- package/dist/gotrue/sessions-plugin.js +3 -9
- package/dist/index.d.ts +16 -15
- package/dist/index.js +8 -10
- package/dist/internal.d.ts +13 -0
- package/dist/internal.js +13 -0
- package/dist/jobs/declared-job.d.ts +24 -0
- package/dist/jobs/declared-job.js +26 -0
- package/dist/jobs/job-types.d.ts +1 -1
- package/dist/mcp/mcp-authenticator.js +3 -3
- package/dist/notifications/device-store-of.d.ts +1 -1
- package/dist/notifications/device-store-of.js +1 -1
- package/dist/notifications/device-store.d.ts +1 -1
- package/dist/notifications/device-store.js +1 -1
- package/dist/notifications/history-store-of.d.ts +1 -1
- package/dist/notifications/history-store-of.js +1 -1
- package/dist/notifications/history-store.d.ts +1 -1
- package/dist/notifications/history-store.js +1 -1
- package/dist/notifications/options.d.ts +3 -1
- package/dist/notifications/options.js +1 -1
- package/dist/notifications/schema.d.ts +2 -2
- package/dist/notifications/schema.js +7 -7
- package/dist/notifications/send-notification.js +1 -1
- package/dist/notifications/sender.d.ts +1 -1
- package/dist/notifications/sender.js +2 -2
- package/dist/notifications/senders-of.d.ts +1 -1
- package/dist/notifications/senders-of.js +1 -1
- package/dist/package.js +1 -1
- package/dist/webhooks/subscription.d.ts +1 -0
- package/dist/webhooks/table/options.d.ts +1 -1
- package/dist/webhooks/table/schema.d.ts +2 -2
- package/dist/webhooks/table/schema.js +2 -2
- package/dist/webhooks/table/webhook-table.js +2 -2
- package/dist/webhooks/table/webhooks-module.d.ts +108 -0
- package/dist/webhooks/table/webhooks-module.js +11 -0
- package/package.json +6 -5
- package/dist/notifications/plugin.d.ts +0 -13
- package/dist/notifications/plugin.js +0 -16
- package/dist/project-config.d.ts +0 -54
- package/dist/project-config.js +0 -182
- package/dist/webhooks/table/plugin.d.ts +0 -10
- package/dist/webhooks/table/plugin.js +0 -18
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { buildAuth } from "./create-auth.js";
|
|
2
|
+
import { PostgresDialect } from "kysely";
|
|
3
|
+
//#region src/better-auth/auth-settings.ts
|
|
4
|
+
const organizationOptions = (organizations, hooks, app) => {
|
|
5
|
+
if (!organizations) return void 0;
|
|
6
|
+
const own = hooks.organizationHooks ?? {};
|
|
7
|
+
const betterAuthHooks = Object.fromEntries(Object.entries(own).map(([name, hook]) => [name, (input) => hook(input, app)]));
|
|
8
|
+
return {
|
|
9
|
+
...organizations === true ? {} : organizations,
|
|
10
|
+
...hooks.generateOrganizationId && { generateId: () => hooks.generateOrganizationId(app) },
|
|
11
|
+
...hooks.onOrganizationCreated && { onCreated: (input) => hooks.onOrganizationCreated(input, app) },
|
|
12
|
+
...hooks.beforeOrganizationDeleted && { beforeDelete: (organization) => hooks.beforeOrganizationDeleted(organization, app) },
|
|
13
|
+
...Object.keys(betterAuthHooks).length > 0 && { hooks: betterAuthHooks }
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
/** createAuth's options for the `auth` settings, the store in the app's own database. */
|
|
17
|
+
const appAuthOptions = (settings, { pool, db, hooks = {}, mailer }) => {
|
|
18
|
+
const { schema = "auth", secret, generateUserId, mailer: mail, organizations, mcp, ...rest } = settings;
|
|
19
|
+
if (!secret) throw new Error("the auth secret is not set: give it the app's secret, PROTOBASE_SECRET, made with `openssl rand -base64 32`");
|
|
20
|
+
const app = { db };
|
|
21
|
+
const organizationsOptions = organizationOptions(organizations, hooks, app);
|
|
22
|
+
const userId = hooks.generateUserId ? () => hooks.generateUserId(app) : generateUserId;
|
|
23
|
+
const onUserCreated = hooks.onUserCreated && ((user, context) => hooks.onUserCreated(user, context, app));
|
|
24
|
+
return {
|
|
25
|
+
...rest,
|
|
26
|
+
database: {
|
|
27
|
+
dialect: new PostgresDialect({ pool }),
|
|
28
|
+
type: "postgres",
|
|
29
|
+
schemaName: schema,
|
|
30
|
+
transaction: true
|
|
31
|
+
},
|
|
32
|
+
secret,
|
|
33
|
+
...userId && { generateUserId: userId },
|
|
34
|
+
...onUserCreated && { onUserCreated },
|
|
35
|
+
...mail === false ? { mailer: false } : mailer && { mailer },
|
|
36
|
+
...organizationsOptions && { organizations: organizationsOptions },
|
|
37
|
+
...mcp && { mcp }
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
/** The app's Better Auth from its `auth` settings, built at serve time with only the plugins they turn on. */
|
|
41
|
+
const buildAppAuth = (settings, input) => buildAuth(appAuthOptions(settings, input));
|
|
42
|
+
//#endregion
|
|
43
|
+
export { appAuthOptions, buildAppAuth };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { TenantValue } from "../types.js";
|
|
2
|
+
import { BetterAuthAuthenticator, BetterAuthAuthenticatorOptions } from "./authenticator.js";
|
|
3
|
+
import { AdminAuth } from "./create-auth.js";
|
|
4
|
+
//#region src/better-auth/authenticate-settings.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* `authenticate` in `protobase.config.ts`: how the API verifies the app's tokens, as data. Without it, the tokens of
|
|
7
|
+
* the app's own `auth`; `jwksUrl` and `issuer` verify those of an auth server elsewhere instead.
|
|
8
|
+
*/
|
|
9
|
+
export type AuthenticateSettings = Omit<BetterAuthAuthenticatorOptions, 'auth' | 'tenant'> & {
|
|
10
|
+
/** The one tenant everyone works in, for an app without organizations; never read from the token. */
|
|
11
|
+
tenant?: TenantValue;
|
|
12
|
+
};
|
|
13
|
+
/** The authenticator of the `authenticate` settings, over the app's Better Auth when it has one. */
|
|
14
|
+
export declare const buildAuthenticator: (settings?: AuthenticateSettings, auth?: AdminAuth) => BetterAuthAuthenticator;
|
|
15
|
+
//#endregion
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { betterAuthAuthenticator } from "./authenticator.js";
|
|
2
|
+
//#region src/better-auth/authenticate-settings.ts
|
|
3
|
+
/** The authenticator of the `authenticate` settings, over the app's Better Auth when it has one. */
|
|
4
|
+
const buildAuthenticator = (settings = {}, auth) => {
|
|
5
|
+
if (!auth && !settings.jwksUrl) throw new Error("No authenticator: give the config `auth`, or `authenticate.jwksUrl` and `issuer` for an auth server elsewhere; see https://docs.protobase.net/reference/auth/");
|
|
6
|
+
return betterAuthAuthenticator({
|
|
7
|
+
...settings,
|
|
8
|
+
...auth && { auth }
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
//#endregion
|
|
12
|
+
export { buildAuthenticator };
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import { UserColumn, UserTableOptions } from "./user-table.js";
|
|
2
2
|
import { Mailer } from "../mail/smtp-mailer.js";
|
|
3
3
|
import { SignInPolicy } from "./sign-in-policy.js";
|
|
4
|
-
import { OperatorProvider } from "./operator-provider.js";
|
|
5
|
-
import { PlatformSignIn } from "./platform-sign-in.js";
|
|
6
|
-
import { RoleDefinitions, RolesInput } from "./organizations/role-definitions.js";
|
|
7
|
-
import { OrganizationRole } from "./organizations/store.js";
|
|
8
|
-
import { OrganizationsOptions, ResolvedOrganizations } from "./organizations/options.js";
|
|
9
4
|
import { StaffSignIn } from "./staff-log.js";
|
|
10
|
-
import "
|
|
5
|
+
import { RoleDefinitions, RolesInput } from "./organizations/role-definitions.js";
|
|
11
6
|
import { ConnectedApp } from "./mcp/connected-apps.js";
|
|
12
7
|
import { ReplacingContext } from "./end-replaced-session.js";
|
|
8
|
+
import { VersionedSecret } from "./secret-versions.js";
|
|
13
9
|
import { UserDeletionListener } from "./user-deletion.js";
|
|
14
|
-
import "./
|
|
10
|
+
import { OrganizationRole } from "./organizations/store.js";
|
|
11
|
+
import { OrganizationsOptions, ResolvedOrganizations } from "./organizations/options.js";
|
|
15
12
|
import { McpAuthOptions } from "./mcp/mcp-plugins.js";
|
|
13
|
+
import { OperatorProvider } from "./operator-provider.js";
|
|
14
|
+
import { PlatformSignIn } from "./platform-sign-in.js";
|
|
15
|
+
import "../index.js";
|
|
16
|
+
import "./auth-base-path.js";
|
|
17
|
+
import { mcpAuthPlugins } from "./mcp/mcp-auth-plugins.js";
|
|
16
18
|
import { SsoOptions } from "./saml-sign-in.js";
|
|
19
|
+
import { samlPlugin } from "./saml-plugin.js";
|
|
17
20
|
import { signUpPaths } from "./sign-up/sign-up-plugin.js";
|
|
18
21
|
import { PasswordHash } from "./password-hashes.js";
|
|
19
22
|
import { BetterAuthOptions } from "better-auth";
|
|
@@ -46,6 +49,15 @@ export type CreateAuthOptions = {
|
|
|
46
49
|
appName?: string;
|
|
47
50
|
/** Signs cookies and encrypts the JWT private keys. Generate with `openssl rand -base64 32`. */
|
|
48
51
|
secret: string;
|
|
52
|
+
/**
|
|
53
|
+
* The secrets the app had before `secret`, newest first, such as `PROTOBASE_PREVIOUS_SECRETS`: what they encrypted
|
|
54
|
+
* still decrypts, so the signing keys keep signing after the secret changes. Default none.
|
|
55
|
+
*/
|
|
56
|
+
previousSecrets?: string[];
|
|
57
|
+
/** Days a token signing key signs before a new one takes over; default 30. */
|
|
58
|
+
signingKeyDays?: number;
|
|
59
|
+
/** Days a replaced signing key still verifies the tokens it signed; default 7, at least 1. */
|
|
60
|
+
signingKeyGraceDays?: number;
|
|
49
61
|
/** Extra origins that may call the auth endpoints, such as the exact host of a dev tunnel. `baseURL` and `origins` are always trusted. */
|
|
50
62
|
trustedOrigins?: string[];
|
|
51
63
|
/**
|
|
@@ -169,7 +181,17 @@ export type UserCreatedHook = NonNullable<UserCreateHooks['after']>;
|
|
|
169
181
|
*/
|
|
170
182
|
/** The configured roles with `admin` first; `admin` is added when missing. */
|
|
171
183
|
export declare const normalizeRoles: (roles?: RolesInput) => string[];
|
|
172
|
-
|
|
184
|
+
/**
|
|
185
|
+
* The plugins only some apps use, which `loadAuthPlugins` imports when the options turn them on: the SSO plugin of
|
|
186
|
+
* `sso.saml` and the OAuth provider of `mcp`.
|
|
187
|
+
*/
|
|
188
|
+
export type AuthPlugins = {
|
|
189
|
+
samlPlugin?: typeof samlPlugin;
|
|
190
|
+
mcpAuthPlugins?: typeof mcpAuthPlugins;
|
|
191
|
+
};
|
|
192
|
+
/** The optional plugins `options` turns on, imported: an app without SAML or MCP loads neither. */
|
|
193
|
+
export declare const loadAuthPlugins: (options: Pick<CreateAuthOptions, "sso" | "mcp">) => Promise<AuthPlugins>;
|
|
194
|
+
export declare const createAuth: (options: CreateAuthOptions, plugins?: AuthPlugins) => import("better-auth").Auth<{
|
|
173
195
|
user: {
|
|
174
196
|
modelName: string;
|
|
175
197
|
fields: {
|
|
@@ -473,9 +495,7 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
|
|
|
473
495
|
expiresAt: Date;
|
|
474
496
|
token: string;
|
|
475
497
|
ipAddress?: string | null | undefined;
|
|
476
|
-
userAgent
|
|
477
|
-
/** Sign-in attempts allowed per minute and client, default 5; also the sign-up requests allowed. */
|
|
478
|
-
/** Sign-in attempts allowed per minute and client, default 5; also the sign-up requests allowed. */ : string | null | undefined;
|
|
498
|
+
userAgent?: string | null | undefined;
|
|
479
499
|
};
|
|
480
500
|
};
|
|
481
501
|
}>>[];
|
|
@@ -1190,6 +1210,8 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
|
|
|
1190
1210
|
};
|
|
1191
1211
|
};
|
|
1192
1212
|
jwks: {
|
|
1213
|
+
rotationInterval: number;
|
|
1214
|
+
gracePeriod: number;
|
|
1193
1215
|
keyPairConfigs: {
|
|
1194
1216
|
readonly alg: "ES256";
|
|
1195
1217
|
}[];
|
|
@@ -1452,6 +1474,21 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
|
|
|
1452
1474
|
};
|
|
1453
1475
|
};
|
|
1454
1476
|
};
|
|
1477
|
+
} | {
|
|
1478
|
+
id: "protobase-signing-keys";
|
|
1479
|
+
endpoints: {
|
|
1480
|
+
ensureSigningKey: import("better-call").StrictEndpoint<string, {
|
|
1481
|
+
method: "POST";
|
|
1482
|
+
}, {
|
|
1483
|
+
ok: boolean;
|
|
1484
|
+
}>;
|
|
1485
|
+
};
|
|
1486
|
+
hooks: {
|
|
1487
|
+
before: {
|
|
1488
|
+
matcher: (ctx: import("better-auth").HookEndpointContext) => boolean;
|
|
1489
|
+
handler: import("better-call").Middleware<import("better-call").MiddlewareOptions, (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<void>>;
|
|
1490
|
+
}[];
|
|
1491
|
+
};
|
|
1455
1492
|
} | {
|
|
1456
1493
|
hooks: {
|
|
1457
1494
|
after: {
|
|
@@ -8777,6 +8814,7 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
|
|
|
8777
8814
|
};
|
|
8778
8815
|
basePath: string;
|
|
8779
8816
|
secret: string;
|
|
8817
|
+
secrets: VersionedSecret[];
|
|
8780
8818
|
trustedOrigins: string[] | ((request?: Request) => string[]);
|
|
8781
8819
|
emailAndPassword: {
|
|
8782
8820
|
onPasswordReset?: ((data: {
|
|
@@ -8868,4 +8906,6 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
|
|
|
8868
8906
|
} | undefined;
|
|
8869
8907
|
};
|
|
8870
8908
|
export type AdminAuth = ReturnType<typeof createAuth>;
|
|
8909
|
+
/** `createAuth` with the optional plugins its options turn on loaded first (see `loadAuthPlugins`). */
|
|
8910
|
+
export declare const buildAuth: (options: CreateAuthOptions) => Promise<AdminAuth>;
|
|
8871
8911
|
//#endregion
|
|
@@ -20,27 +20,29 @@ import { signUpPaths, signUpPlugin } from "./sign-up/sign-up-plugin.js";
|
|
|
20
20
|
import { leakedPasswordsPlugin } from "./leaked-passwords.js";
|
|
21
21
|
import { userDeletion } from "./user-deletion.js";
|
|
22
22
|
import { revokeMcpGrants } from "./mcp/revoke-grants.js";
|
|
23
|
-
import {
|
|
23
|
+
import { mcpUnusedPaths, resolveMcp } from "./mcp/mcp-plugins.js";
|
|
24
24
|
import { lastOrganizationField, sessionOrganizationHooks } from "./organizations/session-organization.js";
|
|
25
|
-
import { tokenClaims } from "./token-claims.js";
|
|
26
|
-
import { mcpAuthPlugins, mcpUnusedPaths, resolveMcp } from "./mcp/mcp-plugins.js";
|
|
27
25
|
import { organizationPlugin } from "./organizations/organization-plugin.js";
|
|
28
26
|
import { protobaseOrganizationPlugin } from "./organizations/protobase-plugin.js";
|
|
29
27
|
import { resolveOrganizations } from "./organizations/options.js";
|
|
30
28
|
import { passkeyHosts, readPasskeyDomain, resolvePasskeyDomain } from "./passkey-domain.js";
|
|
29
|
+
import { coreNames, pluginNames } from "./snake-case-names.js";
|
|
31
30
|
import { passkeyPlugin } from "./passkey-plugin.js";
|
|
32
31
|
import { passwordResetOptions } from "./password-reset.js";
|
|
33
32
|
import { rolesPlugin } from "./roles/roles-plugin.js";
|
|
33
|
+
import { versionedSecrets } from "./secret-versions.js";
|
|
34
|
+
import { signingKeyRotation, signingKeys } from "./signing-keys.js";
|
|
34
35
|
import { platformSignInFor, platformSignInProvider, readPlatformSignIn, resolvePlatformSignIn } from "./platform-sign-in.js";
|
|
35
36
|
import { appSignInPolicy } from "./app-sign-in-policy.js";
|
|
36
37
|
import { assertNoEndpointKeyClashes } from "./endpoint-key-clashes.js";
|
|
37
|
-
import { emailInDomains, resolveSamlProviders, samlDisabledPaths, samlGuardPlugin
|
|
38
|
+
import { emailInDomains, resolveSamlProviders, samlDisabledPaths, samlGuardPlugin } from "./saml-sign-in.js";
|
|
38
39
|
import { noAccountMailPlugin } from "./no-account-mail.js";
|
|
39
40
|
import { emailCodeOptions, twoFactorCodeOptions, unusedEmailCodePaths } from "./sign-in-mail.js";
|
|
40
41
|
import { confirmedOnCreate, confirmedOnUpdate, emailConfirmedField } from "./email-confirmed.js";
|
|
41
42
|
import { rehashPasswordsPlugin, verifyAcceptedHash } from "./password-hashes.js";
|
|
42
43
|
import { staffSignInPlugin } from "./staff-plugin.js";
|
|
43
44
|
import { strongSignInsPlugin } from "./strong-sign-ins.js";
|
|
45
|
+
import { tokenClaims } from "./token-claims.js";
|
|
44
46
|
import { twoFactorAfterPasswordOrCode } from "./two-factor-challenge.js";
|
|
45
47
|
import { metadataField, userFieldsNamed, userModel, userTable, withUserColumns } from "./user-table.js";
|
|
46
48
|
import { usersPlugin } from "./users/users-plugin.js";
|
|
@@ -70,6 +72,15 @@ const tokenLifetime = "15m";
|
|
|
70
72
|
/** The configured roles with `admin` first; `admin` is added when missing. */
|
|
71
73
|
const normalizeRoles = (roles) => roleDefinitions(roles).names;
|
|
72
74
|
const adminImpersonationPaths = ["/admin/impersonate-user", "/admin/stop-impersonating"];
|
|
75
|
+
/** The optional plugins `options` turns on, imported: an app without SAML or MCP loads neither. */
|
|
76
|
+
const loadAuthPlugins = async (options) => ({
|
|
77
|
+
...(options.sso?.saml.length ?? 0) > 0 && { samlPlugin: (await import("./saml-plugin.js")).samlPlugin },
|
|
78
|
+
...options.mcp && { mcpAuthPlugins: (await import("./mcp/mcp-auth-plugins.js")).mcpAuthPlugins }
|
|
79
|
+
});
|
|
80
|
+
const loaded = (plugin, option) => {
|
|
81
|
+
if (!plugin) throw new Error(`${option} needs its plugin loaded: build auth with buildAuth, which loads it`);
|
|
82
|
+
return plugin;
|
|
83
|
+
};
|
|
73
84
|
const newUserId = (generate) => generate === "uuid" ? crypto.randomUUID() : generate();
|
|
74
85
|
const noContext = () => Promise.reject(/* @__PURE__ */ new Error("The auth context is read only once createAuth has made the instance"));
|
|
75
86
|
const organizationPaths = ["/organization/set-active", "/organization/accept-invitation"];
|
|
@@ -77,7 +88,7 @@ const organizationPaths = ["/organization/set-active", "/organization/accept-inv
|
|
|
77
88
|
* The options `createAuth` gives Better Auth, with the roles, default role, mailer, operator provider and platform
|
|
78
89
|
* sign-in provider already resolved.
|
|
79
90
|
*/
|
|
80
|
-
const betterAuthOptions = (options, { origins = [], passkeyDomain, roles, definitions, defaultRole, appName = defaultAppName, mailer, signUpRole, operator, platformSignIn, saml = [], organizations, mcp, context = noContext, signInPolicy = defaultSignInPolicy, mobile, deletion }) => {
|
|
91
|
+
const betterAuthOptions = (options, { origins = [], passkeyDomain, roles, definitions, defaultRole, appName = defaultAppName, mailer, signUpRole, operator, platformSignIn, saml = [], organizations, mcp, context = noContext, signInPolicy = defaultSignInPolicy, mobile, deletion, ...plugins }) => {
|
|
81
92
|
const secure = options.baseURL.startsWith("https://");
|
|
82
93
|
const signIn = platformSignInFor(platformSignIn, Object.keys(options.socialProviders ?? {}));
|
|
83
94
|
const hosts = passkeyHosts([options.baseURL, ...origins]);
|
|
@@ -101,7 +112,10 @@ const betterAuthOptions = (options, { origins = [], passkeyDomain, roles, defini
|
|
|
101
112
|
};
|
|
102
113
|
const jwtOptions = {
|
|
103
114
|
schema: pluginNames.jwt,
|
|
104
|
-
jwks: {
|
|
115
|
+
jwks: {
|
|
116
|
+
keyPairConfigs: [goTrueKeyPair],
|
|
117
|
+
...signingKeyRotation(options)
|
|
118
|
+
},
|
|
105
119
|
jwt: {
|
|
106
120
|
expirationTime: tokenLifetime,
|
|
107
121
|
issuer: options.baseURL,
|
|
@@ -121,6 +135,8 @@ const betterAuthOptions = (options, { origins = [], passkeyDomain, roles, defini
|
|
|
121
135
|
},
|
|
122
136
|
disableSettingJwtHeader: true
|
|
123
137
|
};
|
|
138
|
+
const keys = signingKeys(jwtOptions);
|
|
139
|
+
const { secrets, legacySecret } = versionedSecrets(options.secret, options.previousSecrets);
|
|
124
140
|
const trusted = [
|
|
125
141
|
options.baseURL,
|
|
126
142
|
...origins,
|
|
@@ -137,7 +153,8 @@ const betterAuthOptions = (options, { origins = [], passkeyDomain, roles, defini
|
|
|
137
153
|
logger: authLogger,
|
|
138
154
|
baseURL: multiHostBaseURL(options.baseURL, origins),
|
|
139
155
|
basePath: authBasePath,
|
|
140
|
-
secret:
|
|
156
|
+
secret: legacySecret,
|
|
157
|
+
secrets,
|
|
141
158
|
trustedOrigins: mobile ? (request) => [...trusted, ...mobile.trusted(request)] : trusted,
|
|
142
159
|
emailAndPassword: {
|
|
143
160
|
enabled: true,
|
|
@@ -166,6 +183,7 @@ const betterAuthOptions = (options, { origins = [], passkeyDomain, roles, defini
|
|
|
166
183
|
roles: Object.fromEntries(roles.map((role) => [role, role === "admin" ? adminAc : userAc]))
|
|
167
184
|
}),
|
|
168
185
|
jwt(jwtOptions),
|
|
186
|
+
keys.plugin,
|
|
169
187
|
twoFactorAfterPasswordOrCode({
|
|
170
188
|
schema: pluginNames.twoFactor,
|
|
171
189
|
allowPasswordless: true,
|
|
@@ -185,13 +203,14 @@ const betterAuthOptions = (options, { origins = [], passkeyDomain, roles, defini
|
|
|
185
203
|
defaultPolicy: signInPolicy
|
|
186
204
|
})] : [],
|
|
187
205
|
...signIn ? [genericOAuth({ config: [platformSignInProvider(signIn)] })] : [],
|
|
188
|
-
...saml.length > 0 ? [samlPlugin(saml, options.baseURL), samlGuardPlugin(samlIds)] : [],
|
|
206
|
+
...saml.length > 0 ? [loaded(plugins.samlPlugin, "sso.saml")(saml, options.baseURL), samlGuardPlugin(samlIds)] : [],
|
|
189
207
|
signInPolicyPlugin(policy),
|
|
190
208
|
setPasswordPlugin(),
|
|
191
209
|
...options.leakedPasswords ? [leakedPasswordsPlugin()] : [],
|
|
192
210
|
goTrueSessionsPlugin({
|
|
193
211
|
issuer: goTrueIssuer(options.baseURL),
|
|
194
212
|
jwt: jwtOptions,
|
|
213
|
+
signingKey: keys.ensure,
|
|
195
214
|
policy
|
|
196
215
|
}),
|
|
197
216
|
staffSignInPlugin({
|
|
@@ -220,7 +239,7 @@ const betterAuthOptions = (options, { origins = [], passkeyDomain, roles, defini
|
|
|
220
239
|
...organizations && { organizations }
|
|
221
240
|
}),
|
|
222
241
|
...passwordHashes.length > 0 ? [rehashPasswordsPlugin(passwordHashes)] : [],
|
|
223
|
-
...mcp ? mcpAuthPlugins({
|
|
242
|
+
...mcp ? loaded(plugins.mcpAuthPlugins, "mcp")({
|
|
224
243
|
mcp,
|
|
225
244
|
organizations: Boolean(organizations),
|
|
226
245
|
mail: Boolean(mailer),
|
|
@@ -318,7 +337,7 @@ const checkSignUpRole = (role, roles) => {
|
|
|
318
337
|
if (!roles.includes(role)) throw new Error(`signUp.role "${role}" is not one of the roles: ${roles.join(", ")}`);
|
|
319
338
|
return role;
|
|
320
339
|
};
|
|
321
|
-
const createAuth = (options) => {
|
|
340
|
+
const createAuth = (options, plugins = {}) => {
|
|
322
341
|
if (options.signUp && options.organizations) throw new Error("signUp is not available with organizations: their people join by invitation");
|
|
323
342
|
const definitions = roleDefinitions(options.roles, { organizations: options.organizations !== void 0 });
|
|
324
343
|
const roles = definitions.names;
|
|
@@ -344,6 +363,7 @@ const createAuth = (options) => {
|
|
|
344
363
|
const mobile = mobileRequests();
|
|
345
364
|
const deletion = userDeletion();
|
|
346
365
|
const authOptions = betterAuthOptions(options, {
|
|
366
|
+
...plugins,
|
|
347
367
|
mobile,
|
|
348
368
|
deletion,
|
|
349
369
|
origins,
|
|
@@ -428,5 +448,7 @@ const createAuth = (options) => {
|
|
|
428
448
|
}
|
|
429
449
|
});
|
|
430
450
|
};
|
|
451
|
+
/** `createAuth` with the optional plugins its options turn on loaded first (see `loadAuthPlugins`). */
|
|
452
|
+
const buildAuth = async (options) => createAuth(options, await loadAuthPlugins(options));
|
|
431
453
|
//#endregion
|
|
432
|
-
export { authBasePath, betterAuthOptions, createAuth, normalizeRoles };
|
|
454
|
+
export { authBasePath, betterAuthOptions, buildAuth, createAuth, loadAuthPlugins, normalizeRoles };
|