@protobase/server 0.9.0 → 0.11.0
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/active-role.js +8 -0
- package/dist/admin-options.d.ts +8 -0
- package/dist/api-cors.d.ts +5 -0
- package/dist/api-cors.js +53 -0
- package/dist/better-auth/admin-only.js +5 -3
- package/dist/better-auth/authenticator.d.ts +1 -1
- package/dist/better-auth/authenticator.js +1 -1
- package/dist/better-auth/create-auth.d.ts +166 -160
- package/dist/better-auth/create-auth.js +40 -10
- package/dist/better-auth/operator-provider.d.ts +2 -1
- package/dist/better-auth/origins.d.ts +4 -0
- package/dist/better-auth/origins.js +43 -0
- package/dist/better-auth/passkey-domain.js +41 -0
- package/dist/better-auth/passkey-plugin.js +151 -0
- package/dist/better-auth/roles/active-role.js +26 -0
- package/dist/better-auth/roles/roles-plugin.js +73 -0
- package/dist/better-auth/roles/session-role.js +28 -0
- package/dist/better-auth/staff-sign-in-endpoints.js +9 -2
- package/dist/better-auth/status-route.js +5 -1
- package/dist/better-auth/tokens.d.ts +2 -1
- package/dist/better-auth/tokens.js +5 -2
- package/dist/check-shell.js +11 -2
- package/dist/check-views.js +28 -5
- package/dist/create-admin.d.ts +5 -3
- package/dist/create-admin.js +24 -3
- package/dist/index.d.ts +4 -2
- package/dist/index.js +2 -1
- package/dist/jobs/failed-jobs.js +10 -10
- package/dist/jobs/functions-sql.js +8 -5
- package/dist/jobs/runtime.js +2 -0
- package/dist/meta.js +9 -2
- package/dist/openapi/components.js +1 -1
- package/dist/openapi/document.js +7 -5
- package/dist/openapi/naming.js +2 -1
- package/dist/resource-source.d.ts +3 -2
- package/dist/resource-source.js +3 -1
- package/dist/routes/docs.js +2 -2
- package/dist/view-access.js +136 -37
- package/dist/webhooks/table/owner-roles.js +15 -9
- package/dist/webhooks/table/plugin.d.ts +1 -1
- package/dist/webhooks/table/plugin.js +1 -1
- package/dist/webhooks/table/validate-hook.js +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/active-role.ts
|
|
2
|
+
/**
|
|
3
|
+
* The one role a session works as, which picks its bottom bar: the first of its roles. A Better Auth token carries the
|
|
4
|
+
* session's active role alone (see `narrowClaims`); with another authenticator, the caller's first role.
|
|
5
|
+
*/
|
|
6
|
+
const activeRole = (session) => session.user.roles[0];
|
|
7
|
+
//#endregion
|
|
8
|
+
export { activeRole };
|
package/dist/admin-options.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AuditQueue, PipelineHook, ScanGuardMode } from "./types.js";
|
|
2
|
+
import { CorsOrigins } from "./api-cors.js";
|
|
2
3
|
import { AssistantOptions } from "./assistant/assistant-settings.js";
|
|
3
4
|
import { RuntimeOptions } from "./runtime/runtime-settings.js";
|
|
4
5
|
import { ResolveOptions } from "@protobase/schema";
|
|
@@ -29,6 +30,13 @@ export type AdminOptions = {
|
|
|
29
30
|
onUnhandledError?: (error: unknown) => void;
|
|
30
31
|
/** The assistant in the admin app's dock: a backend elsewhere or the built-in one (see `AssistantOptions`); `false` turns it off. */
|
|
31
32
|
assistant?: AssistantOptions | false;
|
|
33
|
+
/**
|
|
34
|
+
* The websites whose browser code may call the API (`/api/*` but `/api/auth/*`) besides the app's own origins (see
|
|
35
|
+
* `createAuth`'s `origins`): a list of origins, or `*` for any. Defaults to the one the platform passes in
|
|
36
|
+
* `PROTOBASE_CORS_ORIGINS` (`*` or comma separated), when set. With neither this nor other origins, the API sends no
|
|
37
|
+
* CORS headers.
|
|
38
|
+
*/
|
|
39
|
+
cors?: CorsOrigins;
|
|
32
40
|
/** The runtime updates endpoint behind the top bar's update button (see `RuntimeOptions`); `false` turns it off. */
|
|
33
41
|
runtime?: RuntimeOptions | false;
|
|
34
42
|
};
|
package/dist/api-cors.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { readList } from "./better-auth/origins.js";
|
|
2
|
+
import { cors } from "hono/cors";
|
|
3
|
+
//#region src/api-cors.ts
|
|
4
|
+
const corsOriginsVariable = "PROTOBASE_CORS_ORIGINS";
|
|
5
|
+
/** The origins in `PROTOBASE_CORS_ORIGINS`, `*` or comma separated; `undefined` when it is unset. One that is not a URL stops the server at startup. */
|
|
6
|
+
const readCorsOrigins = (env) => {
|
|
7
|
+
const value = env[corsOriginsVariable]?.trim();
|
|
8
|
+
if (!value) return void 0;
|
|
9
|
+
if (value === "*") return "*";
|
|
10
|
+
return readList(value).map((origin) => {
|
|
11
|
+
if (!URL.canParse(origin)) throw new Error(`${corsOriginsVariable} lists "${origin}", which is not a URL such as https://shop.com`);
|
|
12
|
+
return new URL(origin).origin;
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
const allowHeaders = [
|
|
16
|
+
"authorization",
|
|
17
|
+
"content-type",
|
|
18
|
+
"if-match",
|
|
19
|
+
"if-none-match"
|
|
20
|
+
];
|
|
21
|
+
const exposeHeaders = [
|
|
22
|
+
"location",
|
|
23
|
+
"etag",
|
|
24
|
+
"x-meta-version",
|
|
25
|
+
"x-protobase-warning"
|
|
26
|
+
];
|
|
27
|
+
/**
|
|
28
|
+
* CORS for the API: an allowed origin gets `Access-Control-Allow-Origin` (`*` when any is), preflights are answered
|
|
29
|
+
* before authentication and kept for ten minutes.
|
|
30
|
+
*/
|
|
31
|
+
const apiCors = ({ own, allowed, skip }) => {
|
|
32
|
+
const origin = (requestOrigin) => {
|
|
33
|
+
if (allowed === "*") return "*";
|
|
34
|
+
return own.includes(requestOrigin) || allowed.includes(requestOrigin) ? requestOrigin : null;
|
|
35
|
+
};
|
|
36
|
+
const handler = cors({
|
|
37
|
+
origin,
|
|
38
|
+
allowHeaders,
|
|
39
|
+
exposeHeaders,
|
|
40
|
+
maxAge: 600,
|
|
41
|
+
allowMethods: [
|
|
42
|
+
"GET",
|
|
43
|
+
"HEAD",
|
|
44
|
+
"POST",
|
|
45
|
+
"PUT",
|
|
46
|
+
"PATCH",
|
|
47
|
+
"DELETE"
|
|
48
|
+
]
|
|
49
|
+
});
|
|
50
|
+
return (c, next) => skip(c.req.path) ? next() : handler(c, next);
|
|
51
|
+
};
|
|
52
|
+
//#endregion
|
|
53
|
+
export { apiCors, corsOriginsVariable, readCorsOrigins };
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "./organizations/role-definitions.js";
|
|
2
|
+
import { sessionRoles } from "./roles/session-role.js";
|
|
2
3
|
import { APIError, createAuthMiddleware, sessionMiddleware } from "better-auth/api";
|
|
3
4
|
//#region src/better-auth/admin-only.ts
|
|
4
|
-
/** Lets a request through only with the session of an admin; others get `403 ADMIN_ONLY` with `message`. */
|
|
5
|
+
/** Lets a request through only with the session of someone acting as an admin; others get `403 ADMIN_ONLY` with `message`. */
|
|
5
6
|
const adminOnly = (message) => createAuthMiddleware({ use: [sessionMiddleware] }, async (ctx) => {
|
|
6
|
-
|
|
7
|
+
const { active } = await sessionRoles(ctx.context, ctx.context.session);
|
|
8
|
+
if (active !== "admin") throw new APIError("FORBIDDEN", {
|
|
7
9
|
code: "ADMIN_ONLY",
|
|
8
10
|
message
|
|
9
11
|
});
|
|
@@ -7,7 +7,7 @@ export type BetterAuthAuthenticatorOptions = {
|
|
|
7
7
|
auth?: AdminAuth;
|
|
8
8
|
/** Or its JWKS endpoint, for an API that runs apart from the auth server. Needs `issuer`. */
|
|
9
9
|
jwksUrl?: string | URL;
|
|
10
|
-
/** Defaults to the auth instance's `baseURL`; it is both issuer and audience of its tokens. */
|
|
10
|
+
/** Defaults to the auth instance's `issuer`, its `baseURL`; it is both issuer and audience of its tokens. */
|
|
11
11
|
issuer?: string;
|
|
12
12
|
/** The one tenant everyone works in, for an app without organizations; never read from the token. */
|
|
13
13
|
tenant?: TenantValue | (() => Promise<TenantValue | undefined>);
|
|
@@ -9,7 +9,7 @@ import { cachedKeys } from "./jwks-cache.js";
|
|
|
9
9
|
* role, is left out.
|
|
10
10
|
*/
|
|
11
11
|
const betterAuthAuthenticator = (options) => {
|
|
12
|
-
const issuer = options.issuer ?? options.auth?.
|
|
12
|
+
const issuer = options.issuer ?? options.auth?.issuer;
|
|
13
13
|
if (!issuer) throw new Error("betterAuthAuthenticator needs `issuer` (or an `auth` instance with a baseURL)");
|
|
14
14
|
if (!options.auth && !options.jwksUrl) throw new Error("betterAuthAuthenticator needs `auth` or `jwksUrl`");
|
|
15
15
|
const organizations = options.organizations ?? Boolean(options.auth?.organizations);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { SignInPolicy } from "./sign-in-policy.js";
|
|
2
2
|
import { StaffSignIn } from "./staff-log.js";
|
|
3
|
-
import { RoleDefinitions, RolesInput } from "./organizations/role-definitions.js";
|
|
4
3
|
import { Mailer } from "../mail/smtp-mailer.js";
|
|
5
4
|
import { OperatorProvider } from "./operator-provider.js";
|
|
5
|
+
import { RoleDefinitions, RolesInput } from "./organizations/role-definitions.js";
|
|
6
6
|
import { OrganizationRole } from "./organizations/store.js";
|
|
7
7
|
import { OrganizationsOptions, ResolvedOrganizations } from "./organizations/options.js";
|
|
8
8
|
import { PlatformSignIn } from "./platform-sign-in.js";
|
|
@@ -12,8 +12,21 @@ import { BetterAuthOptions } from "better-auth";
|
|
|
12
12
|
export type CreateAuthOptions = {
|
|
13
13
|
/** A `pg` Pool, or `{ dialect, type: 'postgres', schemaName? }` for a Kysely dialect: the admin store, apart from the application's tables (its own schema or database). */
|
|
14
14
|
database: BetterAuthOptions['database'];
|
|
15
|
-
/** Public origin of the API, for example `https://admin.example.com`. Issuer and audience of the tokens; passkeys
|
|
15
|
+
/** Public origin of the API, for example `https://admin.example.com`. Issuer and audience of the tokens; new passkeys are made for its host unless `passkeyDomain` names another. */
|
|
16
16
|
baseURL: string;
|
|
17
|
+
/**
|
|
18
|
+
* The other origins the app is served on, for example `['https://admin.shop.com']`. A request to one of them is
|
|
19
|
+
* answered for that host: its sign-in callbacks and the links it mails, such as a password reset, stay there, and
|
|
20
|
+
* passkeys work on every origin. Tokens keep `baseURL` as issuer, whatever host issued them. Defaults to the
|
|
21
|
+
* comma-separated list the platform passes in `PROTOBASE_ORIGINS`, when set; none otherwise.
|
|
22
|
+
*/
|
|
23
|
+
origins?: string[];
|
|
24
|
+
/**
|
|
25
|
+
* The host new passkeys are made for (their RP ID): the host of `baseURL` or of one of `origins`. Each passkey keeps
|
|
26
|
+
* the one it was made for, and works on every origin, so changing it breaks none. Defaults to the one the platform
|
|
27
|
+
* passes in `PROTOBASE_PASSKEY_DOMAIN`, when set, and to the host of `baseURL` otherwise.
|
|
28
|
+
*/
|
|
29
|
+
passkeyDomain?: string;
|
|
17
30
|
/** The name authenticator apps and passkey prompts show for this app. Default `Protobase`. */
|
|
18
31
|
appName?: string;
|
|
19
32
|
/** Signs cookies and encrypts the JWT private keys. Generate with `openssl rand -base64 32`. */
|
|
@@ -1075,26 +1088,26 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
|
|
|
1075
1088
|
user: import("better-auth").User & Record<string, any>;
|
|
1076
1089
|
session: import("better-auth").Session & Record<string, any>;
|
|
1077
1090
|
}) => Promise<{
|
|
1078
|
-
email: string;
|
|
1079
1091
|
role: any;
|
|
1092
|
+
email: string;
|
|
1080
1093
|
} | {
|
|
1081
1094
|
org?: undefined;
|
|
1082
1095
|
org_role?: undefined;
|
|
1083
1096
|
app_roles?: undefined;
|
|
1084
|
-
email: string;
|
|
1085
1097
|
role: any;
|
|
1098
|
+
email: string;
|
|
1086
1099
|
} | {
|
|
1087
1100
|
org: string;
|
|
1088
1101
|
org_role: OrganizationRole;
|
|
1089
1102
|
app_roles: string[];
|
|
1090
|
-
email: string;
|
|
1091
1103
|
role: any;
|
|
1104
|
+
email: string;
|
|
1092
1105
|
} | {
|
|
1093
1106
|
org: string;
|
|
1094
1107
|
org_role?: undefined;
|
|
1095
1108
|
app_roles?: undefined;
|
|
1096
|
-
email: string;
|
|
1097
1109
|
role: any;
|
|
1110
|
+
email: string;
|
|
1098
1111
|
}>;
|
|
1099
1112
|
};
|
|
1100
1113
|
disableSettingJwtHeader: true;
|
|
@@ -1990,9 +2003,39 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
|
|
|
1990
2003
|
INVALID_TWO_FACTOR_COOKIE: import("better-auth").RawError<"INVALID_TWO_FACTOR_COOKIE">;
|
|
1991
2004
|
};
|
|
1992
2005
|
}, {
|
|
1993
|
-
id: "passkey";
|
|
1994
|
-
version: string;
|
|
1995
2006
|
endpoints: {
|
|
2007
|
+
generatePasskeyAuthenticationOptions: import("better-auth").StrictEndpoint<"/passkey/generate-authenticate-options", {
|
|
2008
|
+
method: "GET";
|
|
2009
|
+
query: import("zod").ZodOptional<import("zod").ZodObject<{
|
|
2010
|
+
rpId: import("zod").ZodOptional<import("zod").ZodString>;
|
|
2011
|
+
}, import("zod/v4/core").$strip>>;
|
|
2012
|
+
}, import("@simplewebauthn/server").PublicKeyCredentialRequestOptionsJSON>;
|
|
2013
|
+
verifyPasskeyAuthentication: import("better-auth").StrictEndpoint<"/passkey/verify-authentication", {
|
|
2014
|
+
method: "POST";
|
|
2015
|
+
body: import("zod").ZodObject<{
|
|
2016
|
+
response: import("zod").ZodRecord<import("zod").ZodAny, import("zod").ZodAny>;
|
|
2017
|
+
}, import("zod/v4/core").$strip>;
|
|
2018
|
+
}, {
|
|
2019
|
+
session: {
|
|
2020
|
+
id: string;
|
|
2021
|
+
createdAt: Date;
|
|
2022
|
+
updatedAt: Date;
|
|
2023
|
+
userId: string;
|
|
2024
|
+
expiresAt: Date;
|
|
2025
|
+
token: string;
|
|
2026
|
+
ipAddress?: string | null | undefined;
|
|
2027
|
+
userAgent?: string | null | undefined;
|
|
2028
|
+
};
|
|
2029
|
+
user: {
|
|
2030
|
+
id: string;
|
|
2031
|
+
createdAt: Date;
|
|
2032
|
+
updatedAt: Date;
|
|
2033
|
+
email: string;
|
|
2034
|
+
emailVerified: boolean;
|
|
2035
|
+
name: string;
|
|
2036
|
+
image?: string | null | undefined;
|
|
2037
|
+
};
|
|
2038
|
+
}>;
|
|
1996
2039
|
generatePasskeyRegistrationOptions: import("better-auth").StrictEndpoint<"/passkey/generate-register-options", {
|
|
1997
2040
|
method: "GET";
|
|
1998
2041
|
use: import("better-auth").Middleware<import("better-auth").MiddlewareOptions, (inputContext: import("better-auth").MiddlewareInputContext<import("better-auth").MiddlewareOptions>) => Promise<{
|
|
@@ -2133,100 +2176,6 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
|
|
|
2133
2176
|
};
|
|
2134
2177
|
};
|
|
2135
2178
|
}, import("@simplewebauthn/server").PublicKeyCredentialCreationOptionsJSON>;
|
|
2136
|
-
generatePasskeyAuthenticationOptions: import("better-auth").StrictEndpoint<"/passkey/generate-authenticate-options", {
|
|
2137
|
-
method: "GET";
|
|
2138
|
-
metadata: {
|
|
2139
|
-
openapi: {
|
|
2140
|
-
operationId: string;
|
|
2141
|
-
description: string;
|
|
2142
|
-
responses: {
|
|
2143
|
-
200: {
|
|
2144
|
-
description: string;
|
|
2145
|
-
content: {
|
|
2146
|
-
"application/json": {
|
|
2147
|
-
schema: {
|
|
2148
|
-
type: "object";
|
|
2149
|
-
properties: {
|
|
2150
|
-
challenge: {
|
|
2151
|
-
type: string;
|
|
2152
|
-
};
|
|
2153
|
-
rp: {
|
|
2154
|
-
type: string;
|
|
2155
|
-
properties: {
|
|
2156
|
-
name: {
|
|
2157
|
-
type: string;
|
|
2158
|
-
};
|
|
2159
|
-
id: {
|
|
2160
|
-
type: string;
|
|
2161
|
-
};
|
|
2162
|
-
};
|
|
2163
|
-
};
|
|
2164
|
-
user: {
|
|
2165
|
-
type: string;
|
|
2166
|
-
properties: {
|
|
2167
|
-
id: {
|
|
2168
|
-
type: string;
|
|
2169
|
-
};
|
|
2170
|
-
name: {
|
|
2171
|
-
type: string;
|
|
2172
|
-
};
|
|
2173
|
-
displayName: {
|
|
2174
|
-
type: string;
|
|
2175
|
-
};
|
|
2176
|
-
};
|
|
2177
|
-
};
|
|
2178
|
-
timeout: {
|
|
2179
|
-
type: string;
|
|
2180
|
-
};
|
|
2181
|
-
allowCredentials: {
|
|
2182
|
-
type: string;
|
|
2183
|
-
items: {
|
|
2184
|
-
type: string;
|
|
2185
|
-
properties: {
|
|
2186
|
-
id: {
|
|
2187
|
-
type: string;
|
|
2188
|
-
};
|
|
2189
|
-
type: {
|
|
2190
|
-
type: string;
|
|
2191
|
-
};
|
|
2192
|
-
transports: {
|
|
2193
|
-
type: string;
|
|
2194
|
-
items: {
|
|
2195
|
-
type: string;
|
|
2196
|
-
};
|
|
2197
|
-
};
|
|
2198
|
-
};
|
|
2199
|
-
};
|
|
2200
|
-
};
|
|
2201
|
-
userVerification: {
|
|
2202
|
-
type: string;
|
|
2203
|
-
};
|
|
2204
|
-
authenticatorSelection: {
|
|
2205
|
-
type: string;
|
|
2206
|
-
properties: {
|
|
2207
|
-
authenticatorAttachment: {
|
|
2208
|
-
type: string;
|
|
2209
|
-
};
|
|
2210
|
-
requireResidentKey: {
|
|
2211
|
-
type: string;
|
|
2212
|
-
};
|
|
2213
|
-
userVerification: {
|
|
2214
|
-
type: string;
|
|
2215
|
-
};
|
|
2216
|
-
};
|
|
2217
|
-
};
|
|
2218
|
-
extensions: {
|
|
2219
|
-
type: string;
|
|
2220
|
-
};
|
|
2221
|
-
};
|
|
2222
|
-
};
|
|
2223
|
-
};
|
|
2224
|
-
};
|
|
2225
|
-
};
|
|
2226
|
-
};
|
|
2227
|
-
};
|
|
2228
|
-
};
|
|
2229
|
-
}, import("@simplewebauthn/server").PublicKeyCredentialRequestOptionsJSON>;
|
|
2230
2179
|
verifyPasskeyRegistration: import("better-auth").StrictEndpoint<"/passkey/verify-registration", {
|
|
2231
2180
|
method: "POST";
|
|
2232
2181
|
body: import("zod").ZodObject<{
|
|
@@ -2292,63 +2241,6 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
|
|
|
2292
2241
|
};
|
|
2293
2242
|
};
|
|
2294
2243
|
}, import("@better-auth/passkey").Passkey>;
|
|
2295
|
-
verifyPasskeyAuthentication: import("better-auth").StrictEndpoint<"/passkey/verify-authentication", {
|
|
2296
|
-
method: "POST";
|
|
2297
|
-
body: import("zod").ZodObject<{
|
|
2298
|
-
response: import("zod").ZodRecord<import("zod").ZodAny, import("zod").ZodAny>;
|
|
2299
|
-
}, import("zod/v4/core").$strip>;
|
|
2300
|
-
metadata: {
|
|
2301
|
-
openapi: {
|
|
2302
|
-
operationId: string;
|
|
2303
|
-
description: string;
|
|
2304
|
-
responses: {
|
|
2305
|
-
200: {
|
|
2306
|
-
description: string;
|
|
2307
|
-
content: {
|
|
2308
|
-
"application/json": {
|
|
2309
|
-
schema: {
|
|
2310
|
-
type: "object";
|
|
2311
|
-
properties: {
|
|
2312
|
-
session: {
|
|
2313
|
-
$ref: string;
|
|
2314
|
-
};
|
|
2315
|
-
user: {
|
|
2316
|
-
$ref: string;
|
|
2317
|
-
};
|
|
2318
|
-
};
|
|
2319
|
-
};
|
|
2320
|
-
};
|
|
2321
|
-
};
|
|
2322
|
-
};
|
|
2323
|
-
};
|
|
2324
|
-
};
|
|
2325
|
-
$Infer: {
|
|
2326
|
-
body: {
|
|
2327
|
-
response: import("@simplewebauthn/server").AuthenticationResponseJSON;
|
|
2328
|
-
};
|
|
2329
|
-
};
|
|
2330
|
-
};
|
|
2331
|
-
}, {
|
|
2332
|
-
session: {
|
|
2333
|
-
id: string;
|
|
2334
|
-
createdAt: Date;
|
|
2335
|
-
updatedAt: Date;
|
|
2336
|
-
userId: string;
|
|
2337
|
-
expiresAt: Date;
|
|
2338
|
-
token: string;
|
|
2339
|
-
ipAddress?: string | null | undefined;
|
|
2340
|
-
userAgent?: string | null | undefined;
|
|
2341
|
-
};
|
|
2342
|
-
user: {
|
|
2343
|
-
id: string;
|
|
2344
|
-
createdAt: Date;
|
|
2345
|
-
updatedAt: Date;
|
|
2346
|
-
email: string;
|
|
2347
|
-
emailVerified: boolean;
|
|
2348
|
-
name: string;
|
|
2349
|
-
image?: string | null | undefined;
|
|
2350
|
-
};
|
|
2351
|
-
}>;
|
|
2352
2244
|
listPasskeys: import("better-auth").StrictEndpoint<"/passkey/list-user-passkeys", {
|
|
2353
2245
|
method: "GET";
|
|
2354
2246
|
use: import("better-auth").Middleware<import("better-auth").MiddlewareOptions, (inputContext: import("better-auth").MiddlewareInputContext<import("better-auth").MiddlewareOptions>) => Promise<{
|
|
@@ -2515,6 +2407,13 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
|
|
|
2515
2407
|
schema: {
|
|
2516
2408
|
passkey: {
|
|
2517
2409
|
fields: {
|
|
2410
|
+
rpID: {
|
|
2411
|
+
type: "string";
|
|
2412
|
+
required: false;
|
|
2413
|
+
fieldName: string;
|
|
2414
|
+
input: false;
|
|
2415
|
+
defaultValue: () => string;
|
|
2416
|
+
};
|
|
2518
2417
|
name: {
|
|
2519
2418
|
type: "string";
|
|
2520
2419
|
required: false;
|
|
@@ -2564,6 +2463,8 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
|
|
|
2564
2463
|
};
|
|
2565
2464
|
};
|
|
2566
2465
|
};
|
|
2466
|
+
id: "passkey";
|
|
2467
|
+
version: string;
|
|
2567
2468
|
$ERROR_CODES: {
|
|
2568
2469
|
CHALLENGE_NOT_FOUND: import("better-auth").RawError<"CHALLENGE_NOT_FOUND">;
|
|
2569
2470
|
YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEY: import("better-auth").RawError<"YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEY">;
|
|
@@ -3663,6 +3564,101 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
|
|
|
3663
3564
|
handler: import("better-auth").Middleware<import("better-auth").MiddlewareOptions, (inputContext: import("better-auth").MiddlewareInputContext<import("better-auth").MiddlewareOptions>) => Promise<void>>;
|
|
3664
3565
|
}[];
|
|
3665
3566
|
};
|
|
3567
|
+
} | {
|
|
3568
|
+
id: "protobase-roles";
|
|
3569
|
+
schema: {
|
|
3570
|
+
session: {
|
|
3571
|
+
fields: {
|
|
3572
|
+
activeRole: {
|
|
3573
|
+
type: "string";
|
|
3574
|
+
required: false;
|
|
3575
|
+
input: false;
|
|
3576
|
+
fieldName: string;
|
|
3577
|
+
};
|
|
3578
|
+
};
|
|
3579
|
+
};
|
|
3580
|
+
user: {
|
|
3581
|
+
fields: {
|
|
3582
|
+
lastRole: {
|
|
3583
|
+
type: "string";
|
|
3584
|
+
required: false;
|
|
3585
|
+
input: false;
|
|
3586
|
+
fieldName: string;
|
|
3587
|
+
};
|
|
3588
|
+
};
|
|
3589
|
+
};
|
|
3590
|
+
};
|
|
3591
|
+
endpoints: {
|
|
3592
|
+
currentRole: import("better-auth").StrictEndpoint<"/role/current", {
|
|
3593
|
+
method: "GET";
|
|
3594
|
+
use: import("better-auth").Middleware<import("better-auth").MiddlewareOptions, (inputContext: import("better-auth").MiddlewareInputContext<import("better-auth").MiddlewareOptions>) => Promise<{
|
|
3595
|
+
session: {
|
|
3596
|
+
session: Record<string, any> & {
|
|
3597
|
+
id: string;
|
|
3598
|
+
createdAt: Date;
|
|
3599
|
+
updatedAt: Date;
|
|
3600
|
+
userId: string;
|
|
3601
|
+
expiresAt: Date;
|
|
3602
|
+
token: string;
|
|
3603
|
+
ipAddress?: string | null | undefined;
|
|
3604
|
+
userAgent?: string | null | undefined;
|
|
3605
|
+
};
|
|
3606
|
+
user: Record<string, any> & {
|
|
3607
|
+
id: string;
|
|
3608
|
+
createdAt: Date;
|
|
3609
|
+
updatedAt: Date;
|
|
3610
|
+
email: string;
|
|
3611
|
+
emailVerified: boolean;
|
|
3612
|
+
name: string;
|
|
3613
|
+
image?: string | null | undefined;
|
|
3614
|
+
};
|
|
3615
|
+
};
|
|
3616
|
+
}>>[];
|
|
3617
|
+
}, {
|
|
3618
|
+
active: string | null;
|
|
3619
|
+
roles: {
|
|
3620
|
+
name: string;
|
|
3621
|
+
label: string;
|
|
3622
|
+
}[];
|
|
3623
|
+
}>;
|
|
3624
|
+
switchRole: import("better-auth").StrictEndpoint<"/role/switch", {
|
|
3625
|
+
method: "POST";
|
|
3626
|
+
use: import("better-auth").Middleware<import("better-auth").MiddlewareOptions, (inputContext: import("better-auth").MiddlewareInputContext<import("better-auth").MiddlewareOptions>) => Promise<{
|
|
3627
|
+
session: {
|
|
3628
|
+
session: Record<string, any> & {
|
|
3629
|
+
id: string;
|
|
3630
|
+
createdAt: Date;
|
|
3631
|
+
updatedAt: Date;
|
|
3632
|
+
userId: string;
|
|
3633
|
+
expiresAt: Date;
|
|
3634
|
+
token: string;
|
|
3635
|
+
ipAddress?: string | null | undefined;
|
|
3636
|
+
userAgent?: string | null | undefined;
|
|
3637
|
+
};
|
|
3638
|
+
user: Record<string, any> & {
|
|
3639
|
+
id: string;
|
|
3640
|
+
createdAt: Date;
|
|
3641
|
+
updatedAt: Date;
|
|
3642
|
+
email: string;
|
|
3643
|
+
emailVerified: boolean;
|
|
3644
|
+
name: string;
|
|
3645
|
+
image?: string | null | undefined;
|
|
3646
|
+
};
|
|
3647
|
+
};
|
|
3648
|
+
}>>[];
|
|
3649
|
+
body: import("zod").ZodObject<{
|
|
3650
|
+
role: import("zod").ZodString;
|
|
3651
|
+
}, import("zod/v4/core").$strip>;
|
|
3652
|
+
}, {
|
|
3653
|
+
role: string;
|
|
3654
|
+
}>;
|
|
3655
|
+
};
|
|
3656
|
+
hooks: {
|
|
3657
|
+
before: {
|
|
3658
|
+
matcher: (ctx: import("better-auth").HookEndpointContext) => boolean;
|
|
3659
|
+
handler: import("better-auth").Middleware<import("better-auth").MiddlewareOptions, (inputContext: import("better-auth").MiddlewareInputContext<import("better-auth").MiddlewareOptions>) => Promise<void>>;
|
|
3660
|
+
}[];
|
|
3661
|
+
};
|
|
3666
3662
|
} | import("better-auth/plugins").DefaultOrganizationPlugin<{
|
|
3667
3663
|
organizationHooks: {
|
|
3668
3664
|
beforeCreateOrganization?: (data: {
|
|
@@ -4264,7 +4260,11 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
|
|
|
4264
4260
|
socialProviders?: import("better-auth").SocialProviders | undefined;
|
|
4265
4261
|
appName: string;
|
|
4266
4262
|
database: any;
|
|
4267
|
-
baseURL: string
|
|
4263
|
+
baseURL: string | {
|
|
4264
|
+
allowedHosts: string[];
|
|
4265
|
+
fallback: string;
|
|
4266
|
+
protocol: "https" | "http";
|
|
4267
|
+
};
|
|
4268
4268
|
basePath: string;
|
|
4269
4269
|
secret: string;
|
|
4270
4270
|
trustedOrigins: string[];
|
|
@@ -4281,6 +4281,12 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
|
|
|
4281
4281
|
minPasswordLength: number;
|
|
4282
4282
|
};
|
|
4283
4283
|
}> & {
|
|
4284
|
+
/** Issuer and audience of the tokens: `baseURL`, on every origin. */
|
|
4285
|
+
issuer: string;
|
|
4286
|
+
/** Every origin the app is served on, `baseURL`'s first. */
|
|
4287
|
+
origins: string[];
|
|
4288
|
+
/** The RP ID of new passkeys. */
|
|
4289
|
+
passkeyDomain: string;
|
|
4284
4290
|
roles: string[];
|
|
4285
4291
|
roleDefinitions: RoleDefinitions;
|
|
4286
4292
|
organizations: ResolvedOrganizations | undefined;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { multiHostBaseURL, readOrigins, resolveOrigins } from "./origins.js";
|
|
1
2
|
import { readMailSettings } from "../mail/mail-settings.js";
|
|
2
3
|
import { smtpMailer } from "../mail/smtp-mailer.js";
|
|
3
4
|
import { readOperatorSettings, resolveOperator } from "./operator-provider.js";
|
|
@@ -6,14 +7,17 @@ import { lastOrganizationField, organizationClaims, sessionOrganizationHooks } f
|
|
|
6
7
|
import { organizationPlugin } from "./organizations/organization-plugin.js";
|
|
7
8
|
import { protobaseOrganizationPlugin } from "./organizations/protobase-plugin.js";
|
|
8
9
|
import { resolveOrganizations } from "./organizations/options.js";
|
|
10
|
+
import { passkeyHosts, readPasskeyDomain, resolvePasskeyDomain } from "./passkey-domain.js";
|
|
11
|
+
import { coreNames, pluginNames } from "./snake-case-names.js";
|
|
12
|
+
import { passkeyPlugin } from "./passkey-plugin.js";
|
|
9
13
|
import { passwordResetOptions } from "./password-reset.js";
|
|
14
|
+
import { narrowClaims } from "./roles/active-role.js";
|
|
15
|
+
import { rolesPlugin } from "./roles/roles-plugin.js";
|
|
10
16
|
import { platformSignInFor, platformSignInProvider, readPlatformSignIn, resolvePlatformSignIn } from "./platform-sign-in.js";
|
|
11
17
|
import { signInPolicyPlugin } from "./policy-plugin.js";
|
|
12
18
|
import { emailCodeOptions, twoFactorCodeOptions, unusedEmailCodePaths } from "./sign-in-mail.js";
|
|
13
|
-
import { coreNames, pluginNames } from "./snake-case-names.js";
|
|
14
19
|
import { staffSignInPlugin } from "./staff-plugin.js";
|
|
15
20
|
import { twoFactorAfterPasswordOrCode } from "./two-factor-challenge.js";
|
|
16
|
-
import { passkey } from "@better-auth/passkey";
|
|
17
21
|
import { APIError } from "better-auth/api";
|
|
18
22
|
import { betterAuth } from "better-auth";
|
|
19
23
|
import { admin, emailOTP, genericOAuth, jwt } from "better-auth/plugins";
|
|
@@ -21,6 +25,8 @@ import { adminAc, userAc } from "better-auth/plugins/admin/access";
|
|
|
21
25
|
//#region src/better-auth/create-auth.ts
|
|
22
26
|
const platformOperator = () => readOperatorSettings(globalThis.process?.env ?? {});
|
|
23
27
|
const platformSignInSettings = () => readPlatformSignIn(globalThis.process?.env ?? {});
|
|
28
|
+
const platformOrigins = () => readOrigins(globalThis.process?.env ?? {});
|
|
29
|
+
const platformPasskeyDomain = () => readPasskeyDomain(globalThis.process?.env ?? {});
|
|
24
30
|
const platformMailer = () => {
|
|
25
31
|
const settings = readMailSettings(globalThis.process?.env ?? {});
|
|
26
32
|
return settings && smtpMailer(settings);
|
|
@@ -42,17 +48,19 @@ const organizationPaths = ["/organization/set-active", "/organization/accept-inv
|
|
|
42
48
|
* The options `createAuth` gives Better Auth, with the roles, default role, mailer, operator provider and platform
|
|
43
49
|
* sign-in provider already resolved.
|
|
44
50
|
*/
|
|
45
|
-
const betterAuthOptions = (options, { roles, defaultRole, mailer, operator, platformSignIn, organizations, context = noContext }) => {
|
|
51
|
+
const betterAuthOptions = (options, { origins = [], passkeyDomain, roles, definitions, defaultRole, mailer, operator, platformSignIn, organizations, context = noContext }) => {
|
|
46
52
|
const secure = options.baseURL.startsWith("https://");
|
|
47
53
|
const signIn = platformSignInFor(platformSignIn, Object.keys(options.socialProviders ?? {}));
|
|
54
|
+
const hosts = passkeyHosts([options.baseURL, ...origins]);
|
|
48
55
|
return {
|
|
49
56
|
appName: options.appName ?? "Protobase",
|
|
50
57
|
database: options.database,
|
|
51
|
-
baseURL: options.baseURL,
|
|
58
|
+
baseURL: multiHostBaseURL(options.baseURL, origins),
|
|
52
59
|
basePath: authBasePath,
|
|
53
60
|
secret: options.secret,
|
|
54
61
|
trustedOrigins: [
|
|
55
62
|
options.baseURL,
|
|
63
|
+
...origins,
|
|
56
64
|
"https://*.trycloudflare.com",
|
|
57
65
|
...options.trustedOrigins ?? []
|
|
58
66
|
],
|
|
@@ -86,11 +94,17 @@ const betterAuthOptions = (options, { roles, defaultRole, mailer, operator, plat
|
|
|
86
94
|
expirationTime: tokenLifetime,
|
|
87
95
|
issuer: options.baseURL,
|
|
88
96
|
audience: options.baseURL,
|
|
89
|
-
definePayload: async ({ user, session }) =>
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
97
|
+
definePayload: async ({ user, session }) => {
|
|
98
|
+
const { activeRole, activeOrganizationId } = session;
|
|
99
|
+
const claims = {
|
|
100
|
+
role: user.role,
|
|
101
|
+
...organizations && await organizationClaims((await context()).adapter, user, activeOrganizationId)
|
|
102
|
+
};
|
|
103
|
+
return {
|
|
104
|
+
email: user.email,
|
|
105
|
+
...narrowClaims(claims, [activeRole, user.lastRole], Boolean(organizations))
|
|
106
|
+
};
|
|
107
|
+
}
|
|
94
108
|
},
|
|
95
109
|
disableSettingJwtHeader: true
|
|
96
110
|
}),
|
|
@@ -99,7 +113,11 @@ const betterAuthOptions = (options, { roles, defaultRole, mailer, operator, plat
|
|
|
99
113
|
allowPasswordless: true,
|
|
100
114
|
...mailer && { otpOptions: twoFactorCodeOptions(mailer) }
|
|
101
115
|
}),
|
|
102
|
-
|
|
116
|
+
passkeyPlugin({
|
|
117
|
+
domain: passkeyDomain ?? hosts[0],
|
|
118
|
+
hosts,
|
|
119
|
+
formerDomain: hosts[0]
|
|
120
|
+
}),
|
|
103
121
|
...mailer ? [emailOTP(emailCodeOptions(mailer))] : [],
|
|
104
122
|
...signIn ? [genericOAuth({ config: [platformSignInProvider(signIn)] })] : [],
|
|
105
123
|
signInPolicyPlugin({
|
|
@@ -115,6 +133,7 @@ const betterAuthOptions = (options, { roles, defaultRole, mailer, operator, plat
|
|
|
115
133
|
...operator && { operator },
|
|
116
134
|
...mailer && { mailer }
|
|
117
135
|
}),
|
|
136
|
+
rolesPlugin({ definitions }),
|
|
118
137
|
...organizations ? [organizationPlugin({
|
|
119
138
|
resolved: organizations,
|
|
120
139
|
secret: options.secret,
|
|
@@ -186,11 +205,16 @@ const createAuth = (options) => {
|
|
|
186
205
|
const signInSettings = options.signInProvider === void 0 ? platformSignInSettings() : options.signInProvider || void 0;
|
|
187
206
|
const socialProviders = Object.keys(options.socialProviders ?? {});
|
|
188
207
|
const platformSignIn = platformSignInFor(signInSettings && resolvePlatformSignIn(signInSettings), socialProviders);
|
|
208
|
+
const origins = resolveOrigins(options.baseURL, options.origins ?? platformOrigins());
|
|
209
|
+
const passkeyDomain = resolvePasskeyDomain(options.passkeyDomain ?? platformPasskeyDomain(), [options.baseURL, ...origins]);
|
|
189
210
|
const organizations = options.organizations && resolveOrganizations(options.organizations, definitions, options.baseURL);
|
|
190
211
|
let instance;
|
|
191
212
|
const context = () => instance?.$context ?? Promise.reject(/* @__PURE__ */ new Error("The auth instance is not made yet"));
|
|
192
213
|
const auth = betterAuth(betterAuthOptions(options, {
|
|
214
|
+
origins,
|
|
215
|
+
passkeyDomain,
|
|
193
216
|
roles,
|
|
217
|
+
definitions,
|
|
194
218
|
defaultRole,
|
|
195
219
|
mailer,
|
|
196
220
|
operator,
|
|
@@ -202,6 +226,12 @@ const createAuth = (options) => {
|
|
|
202
226
|
}));
|
|
203
227
|
instance = auth;
|
|
204
228
|
return Object.assign(auth, {
|
|
229
|
+
/** Issuer and audience of the tokens: `baseURL`, on every origin. */
|
|
230
|
+
issuer: options.baseURL,
|
|
231
|
+
/** Every origin the app is served on, `baseURL`'s first. */
|
|
232
|
+
origins: [new URL(options.baseURL).origin, ...origins],
|
|
233
|
+
/** The RP ID of new passkeys. */
|
|
234
|
+
passkeyDomain,
|
|
205
235
|
roles,
|
|
206
236
|
roleDefinitions: definitions,
|
|
207
237
|
organizations,
|