@bitbaum/accountkit 0.0.0-stage → 0.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/LICENSE +21 -0
- package/README.md +203 -2
- package/dist/AccountMenu.d.ts +76 -0
- package/dist/AccountMenu.d.ts.map +1 -0
- package/dist/AccountMenu.js +156 -0
- package/dist/AccountMenu.js.map +1 -0
- package/dist/SignInError.d.ts +50 -0
- package/dist/SignInError.d.ts.map +1 -0
- package/dist/SignInError.js +34 -0
- package/dist/SignInError.js.map +1 -0
- package/dist/auth/client.d.ts +19 -0
- package/dist/auth/client.d.ts.map +1 -0
- package/dist/auth/client.js +17 -0
- package/dist/auth/client.js.map +1 -0
- package/dist/auth/factor.d.ts +9 -0
- package/dist/auth/factor.d.ts.map +1 -0
- package/dist/auth/factor.js +107 -0
- package/dist/auth/factor.js.map +1 -0
- package/dist/auth/index.d.ts +6 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +6 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/labels.d.ts +114 -0
- package/dist/auth/labels.d.ts.map +1 -0
- package/dist/auth/labels.js +132 -0
- package/dist/auth/labels.js.map +1 -0
- package/dist/auth/limits.d.ts +28 -0
- package/dist/auth/limits.d.ts.map +1 -0
- package/dist/auth/limits.js +90 -0
- package/dist/auth/limits.js.map +1 -0
- package/dist/auth/mail.d.ts +10 -0
- package/dist/auth/mail.d.ts.map +1 -0
- package/dist/auth/mail.js +45 -0
- package/dist/auth/mail.js.map +1 -0
- package/dist/auth/methods.d.ts +71 -0
- package/dist/auth/methods.d.ts.map +1 -0
- package/dist/auth/methods.js +92 -0
- package/dist/auth/methods.js.map +1 -0
- package/dist/auth/next.d.ts +73 -0
- package/dist/auth/next.d.ts.map +1 -0
- package/dist/auth/next.js +131 -0
- package/dist/auth/next.js.map +1 -0
- package/dist/auth/react.d.ts +174 -0
- package/dist/auth/react.d.ts.map +1 -0
- package/dist/auth/react.js +396 -0
- package/dist/auth/react.js.map +1 -0
- package/dist/auth/recovery.d.ts +17 -0
- package/dist/auth/recovery.d.ts.map +1 -0
- package/dist/auth/recovery.js +85 -0
- package/dist/auth/recovery.js.map +1 -0
- package/dist/auth/roles.d.ts +19 -0
- package/dist/auth/roles.d.ts.map +1 -0
- package/dist/auth/roles.js +29 -0
- package/dist/auth/roles.js.map +1 -0
- package/dist/auth/schema.d.ts +1923 -0
- package/dist/auth/schema.d.ts.map +1 -0
- package/dist/auth/schema.js +120 -0
- package/dist/auth/schema.js.map +1 -0
- package/dist/auth/server.d.ts +56 -0
- package/dist/auth/server.d.ts.map +1 -0
- package/dist/auth/server.js +229 -0
- package/dist/auth/server.js.map +1 -0
- package/dist/auth/translations.d.ts +9 -0
- package/dist/auth/translations.d.ts.map +1 -0
- package/dist/auth/translations.js +513 -0
- package/dist/auth/translations.js.map +1 -0
- package/dist/identity.d.ts +50 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +76 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/orangecat.d.ts +333 -0
- package/dist/orangecat.d.ts.map +1 -0
- package/dist/orangecat.js +508 -0
- package/dist/orangecat.js.map +1 -0
- package/dist/paths.d.ts +3 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +11 -0
- package/dist/paths.js.map +1 -0
- package/package.json +145 -4
- package/styles.css +383 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which sign-in methods this deployment offers — a pure function of its env,
|
|
3
|
+
* so "is this button shown" is a unit test, not a guess (fleet STACK.md,
|
|
4
|
+
* "Identity", 2026-10-11).
|
|
5
|
+
*
|
|
6
|
+
* - Email + password, passkeys and two-factor need nothing external.
|
|
7
|
+
* - A magic link needs mail (@bitbaum/mail-kit). Without it the option is
|
|
8
|
+
* HIDDEN in production rather than offered and silently undeliverable; in
|
|
9
|
+
* development the link is printed to the server console instead.
|
|
10
|
+
* - "bitbaum sign-in" is the shared sign-in service that holds the Google,
|
|
11
|
+
* GitHub, X, Meta and Apple credentials once and speaks OIDC to every app,
|
|
12
|
+
* issuing a per-app (pairwise) subject. Shown only when SIGNIN_* is set.
|
|
13
|
+
* - "Sign in with OrangeCat" is OrangeCat's OIDC provider: one click for
|
|
14
|
+
* people who already have OrangeCat, never a requirement. OrangeCat's token
|
|
15
|
+
* endpoint accepts ONLY client_secret_post and requires PKCE.
|
|
16
|
+
*
|
|
17
|
+
* A method whose env is missing is hidden, never broken.
|
|
18
|
+
*/
|
|
19
|
+
type Env = Record<string, string | undefined>;
|
|
20
|
+
export declare const SIGNIN_PROVIDER_ID = "bitbaum-signin";
|
|
21
|
+
export declare const ORANGECAT_PROVIDER_ID = "orangecat";
|
|
22
|
+
export declare const ORANGECAT_DEFAULT_ISSUER = "https://orangecat.ch";
|
|
23
|
+
export type OidcProviderId = typeof SIGNIN_PROVIDER_ID | typeof ORANGECAT_PROVIDER_ID;
|
|
24
|
+
export interface OidcClient {
|
|
25
|
+
providerId: OidcProviderId;
|
|
26
|
+
issuer: string;
|
|
27
|
+
discoveryUrl: string;
|
|
28
|
+
clientId: string;
|
|
29
|
+
clientSecret: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* An issuer we are willing to send people to: https, or http on localhost for
|
|
33
|
+
* development. Anything else is treated as not configured — a typo must hide
|
|
34
|
+
* the button, not send someone's sign-in over plain HTTP.
|
|
35
|
+
*/
|
|
36
|
+
export declare function usableIssuer(value: string): string | null;
|
|
37
|
+
/** The shared bitbaum sign-in service (SIGNIN_ISSUER/CLIENT_ID/CLIENT_SECRET). */
|
|
38
|
+
export declare function signinBroker(env: Env): OidcClient | null;
|
|
39
|
+
/** OrangeCat, under the env names every fleet app already uses. */
|
|
40
|
+
export declare function orangecatOidc(env: Env): OidcClient | null;
|
|
41
|
+
export declare function oidcClients(env: Env): OidcClient[];
|
|
42
|
+
export interface SignInMethods {
|
|
43
|
+
/** Recovery needs a real sender; absent on older capability objects. */
|
|
44
|
+
passwordReset?: boolean;
|
|
45
|
+
password: boolean;
|
|
46
|
+
passkey: boolean;
|
|
47
|
+
twoFactor: boolean;
|
|
48
|
+
magicLink: boolean;
|
|
49
|
+
/** Whether an email must be confirmed before a password account signs in. */
|
|
50
|
+
verifyEmail: boolean;
|
|
51
|
+
signin: boolean;
|
|
52
|
+
orangecat: boolean;
|
|
53
|
+
}
|
|
54
|
+
/** What the sign-in and sign-up pages offer. Safe to send to the browser: booleans only. */
|
|
55
|
+
export declare function signInMethods(env: Env, mailConfigured: boolean): SignInMethods;
|
|
56
|
+
/**
|
|
57
|
+
* The address given to a person who signed in with a method that brought no
|
|
58
|
+
* email, or whose email we do not trust as an identity.
|
|
59
|
+
*
|
|
60
|
+
* An address from a provider is CONTACT data, never an identity: linking by it
|
|
61
|
+
* lets whoever controls an unverified address at the provider take over the
|
|
62
|
+
* local account (fleet accountkit, `orangecatProfile`). So OIDC accounts never
|
|
63
|
+
* carry the provider's address. `.invalid` is reserved (RFC 2606): it cannot
|
|
64
|
+
* receive mail and cannot collide with a real address. Hashed so the
|
|
65
|
+
* provider's subject is not readable from it.
|
|
66
|
+
*/
|
|
67
|
+
export declare function placeholderEmail(providerId: string, subject: string): string;
|
|
68
|
+
/** Whether mail can ever reach this address. */
|
|
69
|
+
export declare function isDeliverable(email: string | null | undefined): boolean;
|
|
70
|
+
export {};
|
|
71
|
+
//# sourceMappingURL=methods.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"methods.d.ts","sourceRoot":"","sources":["../../src/auth/methods.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AACH,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAE9C,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AACnD,eAAO,MAAM,qBAAqB,cAAc,CAAC;AACjD,eAAO,MAAM,wBAAwB,yBAAyB,CAAC;AAE/D,MAAM,MAAM,cAAc,GACxB,OAAO,kBAAkB,GAAG,OAAO,qBAAqB,CAAC;AAE3D,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,cAAc,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAID;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAczD;AAoBD,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,UAAU,GAAG,IAAI,CAOxD;AAED,mEAAmE;AACnE,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG,GAAG,UAAU,GAAG,IAAI,CAOzD;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,UAAU,EAAE,CAIlD;AAED,MAAM,WAAW,aAAa;IAC5B,wEAAwE;IACxE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,6EAA6E;IAC7E,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,4FAA4F;AAC5F,wBAAgB,aAAa,CAC3B,GAAG,EAAE,GAAG,EACR,cAAc,EAAE,OAAO,GACtB,aAAa,CAYf;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAM5E;AAED,gDAAgD;AAChD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAIvE"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
export const SIGNIN_PROVIDER_ID = "bitbaum-signin";
|
|
3
|
+
export const ORANGECAT_PROVIDER_ID = "orangecat";
|
|
4
|
+
export const ORANGECAT_DEFAULT_ISSUER = "https://orangecat.ch";
|
|
5
|
+
const text = (value) => value?.trim() || "";
|
|
6
|
+
/**
|
|
7
|
+
* An issuer we are willing to send people to: https, or http on localhost for
|
|
8
|
+
* development. Anything else is treated as not configured — a typo must hide
|
|
9
|
+
* the button, not send someone's sign-in over plain HTTP.
|
|
10
|
+
*/
|
|
11
|
+
export function usableIssuer(value) {
|
|
12
|
+
let url;
|
|
13
|
+
try {
|
|
14
|
+
url = new URL(value);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const local = url.hostname === "localhost" || url.hostname === "127.0.0.1";
|
|
20
|
+
if (url.protocol !== "https:" && !(url.protocol === "http:" && local))
|
|
21
|
+
return null;
|
|
22
|
+
if (url.search || url.hash || url.username || url.password)
|
|
23
|
+
return null;
|
|
24
|
+
// OIDC compares `iss` byte for byte; normalise only the trailing slash used
|
|
25
|
+
// to build the discovery URL, never the issuer itself.
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
function oidcClient(providerId, issuerValue, clientId, clientSecret) {
|
|
29
|
+
if (!issuerValue || !clientId || !clientSecret)
|
|
30
|
+
return null;
|
|
31
|
+
const issuer = usableIssuer(issuerValue);
|
|
32
|
+
if (!issuer)
|
|
33
|
+
return null;
|
|
34
|
+
return {
|
|
35
|
+
providerId,
|
|
36
|
+
issuer,
|
|
37
|
+
discoveryUrl: `${issuer.replace(/\/+$/, "")}/.well-known/openid-configuration`,
|
|
38
|
+
clientId,
|
|
39
|
+
clientSecret,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/** The shared bitbaum sign-in service (SIGNIN_ISSUER/CLIENT_ID/CLIENT_SECRET). */
|
|
43
|
+
export function signinBroker(env) {
|
|
44
|
+
return oidcClient(SIGNIN_PROVIDER_ID, text(env.SIGNIN_ISSUER), text(env.SIGNIN_CLIENT_ID), text(env.SIGNIN_CLIENT_SECRET));
|
|
45
|
+
}
|
|
46
|
+
/** OrangeCat, under the env names every fleet app already uses. */
|
|
47
|
+
export function orangecatOidc(env) {
|
|
48
|
+
return oidcClient(ORANGECAT_PROVIDER_ID, text(env.ORANGECAT_OAUTH_ISSUER) || ORANGECAT_DEFAULT_ISSUER, text(env.ORANGECAT_OAUTH_CLIENT_ID), text(env.ORANGECAT_OAUTH_CLIENT_SECRET));
|
|
49
|
+
}
|
|
50
|
+
export function oidcClients(env) {
|
|
51
|
+
return [signinBroker(env), orangecatOidc(env)].filter((c) => c !== null);
|
|
52
|
+
}
|
|
53
|
+
/** What the sign-in and sign-up pages offer. Safe to send to the browser: booleans only. */
|
|
54
|
+
export function signInMethods(env, mailConfigured) {
|
|
55
|
+
const development = env.NODE_ENV === "development";
|
|
56
|
+
return {
|
|
57
|
+
passwordReset: mailConfigured,
|
|
58
|
+
password: true,
|
|
59
|
+
passkey: true,
|
|
60
|
+
twoFactor: true,
|
|
61
|
+
magicLink: mailConfigured || development,
|
|
62
|
+
verifyEmail: mailConfigured,
|
|
63
|
+
signin: signinBroker(env) !== null,
|
|
64
|
+
orangecat: orangecatOidc(env) !== null,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The address given to a person who signed in with a method that brought no
|
|
69
|
+
* email, or whose email we do not trust as an identity.
|
|
70
|
+
*
|
|
71
|
+
* An address from a provider is CONTACT data, never an identity: linking by it
|
|
72
|
+
* lets whoever controls an unverified address at the provider take over the
|
|
73
|
+
* local account (fleet accountkit, `orangecatProfile`). So OIDC accounts never
|
|
74
|
+
* carry the provider's address. `.invalid` is reserved (RFC 2606): it cannot
|
|
75
|
+
* receive mail and cannot collide with a real address. Hashed so the
|
|
76
|
+
* provider's subject is not readable from it.
|
|
77
|
+
*/
|
|
78
|
+
export function placeholderEmail(providerId, subject) {
|
|
79
|
+
const digest = createHash("sha256")
|
|
80
|
+
.update(`${providerId}:${subject}`)
|
|
81
|
+
.digest("hex")
|
|
82
|
+
.slice(0, 32);
|
|
83
|
+
return `${digest}@${providerId}.invalid`;
|
|
84
|
+
}
|
|
85
|
+
/** Whether mail can ever reach this address. */
|
|
86
|
+
export function isDeliverable(email) {
|
|
87
|
+
if (!email)
|
|
88
|
+
return false;
|
|
89
|
+
const domain = email.split("@")[1]?.toLowerCase() ?? "";
|
|
90
|
+
return domain.length > 0 && !domain.endsWith(".invalid");
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=methods.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"methods.js","sourceRoot":"","sources":["../../src/auth/methods.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { type Auth, type CreateAuthOptions, type AuthSite, type AuthMailer, type AuthStatus } from "./server.js";
|
|
2
|
+
export interface AuthRuntimeOptions {
|
|
3
|
+
site: AuthSite;
|
|
4
|
+
mail: AuthMailer;
|
|
5
|
+
/** Whether the product has a database to keep accounts in. */
|
|
6
|
+
isDatabaseConfigured: (env: NodeJS.ProcessEnv) => boolean;
|
|
7
|
+
/** The Drizzle database. Called on first use, never at import. */
|
|
8
|
+
getDatabase: () => unknown;
|
|
9
|
+
/** Only if the product keeps the account tables under its own definitions. */
|
|
10
|
+
schema?: Record<string, unknown>;
|
|
11
|
+
/**
|
|
12
|
+
* For a product whose rows were keyed on an OIDC subject before it had
|
|
13
|
+
* accounts (an OrangeCat actor id). A person who FIRST came in through that
|
|
14
|
+
* provider keeps the subject as their `actorId`, so every existing row stays
|
|
15
|
+
* theirs with no data migration. Everyone else's `actorId` is their user id.
|
|
16
|
+
* Linking the provider later never changes an id that already has data.
|
|
17
|
+
*/
|
|
18
|
+
legacyIdentityProvider?: string;
|
|
19
|
+
/** See CreateAuthOptions.onAccountCreated. */
|
|
20
|
+
onAccountCreated?: CreateAuthOptions["onAccountCreated"];
|
|
21
|
+
}
|
|
22
|
+
type SessionUser = {
|
|
23
|
+
id: string;
|
|
24
|
+
actorId: string;
|
|
25
|
+
role?: unknown;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Everything a Next.js product needs from accounts, from one call:
|
|
29
|
+
*
|
|
30
|
+
* export const { GET, POST, getSession, requireUser, authStatus } =
|
|
31
|
+
* createAuthRuntime({ site, mail, isDatabaseConfigured, getDatabase });
|
|
32
|
+
*
|
|
33
|
+
* Built on first request, never at import: `next build` evaluates route
|
|
34
|
+
* modules, and an instance built there would make the build need a database
|
|
35
|
+
* and a secret. A running server without them answers "accounts unavailable"
|
|
36
|
+
* on every auth surface instead of crashing.
|
|
37
|
+
*/
|
|
38
|
+
export declare function createAuthRuntime(options: AuthRuntimeOptions): {
|
|
39
|
+
getAuth: () => Auth;
|
|
40
|
+
authStatus: (env?: NodeJS.ProcessEnv) => AuthStatus;
|
|
41
|
+
getSession: () => Promise<AuthSession | null>;
|
|
42
|
+
sessionFor: (requestHeaders: Headers) => Promise<AuthSession | null>;
|
|
43
|
+
requireUser: (request: Request) => Promise<{
|
|
44
|
+
user: SessionUser;
|
|
45
|
+
response?: never;
|
|
46
|
+
} | {
|
|
47
|
+
user?: never;
|
|
48
|
+
response: Response;
|
|
49
|
+
}>;
|
|
50
|
+
GET: (request: Request) => Promise<Response>;
|
|
51
|
+
POST: (request: Request) => Promise<Response>;
|
|
52
|
+
};
|
|
53
|
+
/** The signed-in person, as the products read them. */
|
|
54
|
+
export interface AuthSession {
|
|
55
|
+
user: {
|
|
56
|
+
id: string;
|
|
57
|
+
/** The id the product's rows use: the user id, or a legacy subject (see legacyIdentityProvider). */
|
|
58
|
+
actorId: string;
|
|
59
|
+
createdAt?: Date | string;
|
|
60
|
+
name: string;
|
|
61
|
+
email: string;
|
|
62
|
+
emailVerified: boolean;
|
|
63
|
+
image?: string | null;
|
|
64
|
+
role?: string;
|
|
65
|
+
twoFactorEnabled?: boolean;
|
|
66
|
+
};
|
|
67
|
+
session: {
|
|
68
|
+
id: string;
|
|
69
|
+
expiresAt: Date;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export {};
|
|
73
|
+
//# sourceMappingURL=next.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"next.d.ts","sourceRoot":"","sources":["../../src/auth/next.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,IAAI,EACT,KAAK,iBAAiB,EACtB,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,UAAU,EAChB,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,UAAU,CAAC;IACjB,8DAA8D;IAC9D,oBAAoB,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,KAAK,OAAO,CAAC;IAC1D,kEAAkE;IAClE,WAAW,EAAE,MAAM,OAAO,CAAC;IAC3B,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC;;;;;;OAMG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,8CAA8C;IAC9C,gBAAgB,CAAC,EAAE,iBAAiB,CAAC,kBAAkB,CAAC,CAAC;CAC1D;AAED,KAAK,WAAW,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEnE;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB;mBAEvC,IAAI;uBAUC,MAAM,CAAC,UAAU,KAAiB,UAAU;sBA2DxC,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;iCAdtC,OAAO,KACtB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;2BA6BnB,OAAO,KACf,OAAO,CACN;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,QAAQ,CAAC,EAAE,KAAK,CAAA;KAAE,GACvC;QAAE,IAAI,CAAC,EAAE,KAAK,CAAC;QAAC,QAAQ,EAAE,QAAQ,CAAA;KAAE,CACvC;mBAsCsB,OAAO;oBAEN,OAAO;EAGhC;AAED,uDAAuD;AACvD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE;QACJ,EAAE,EAAE,MAAM,CAAC;QACX,oGAAoG;QACpG,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;QAC1B,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,aAAa,EAAE,OAAO,CAAC;QACvB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,gBAAgB,CAAC,EAAE,OAAO,CAAC;KAC5B,CAAC;IACF,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,IAAI,CAAA;KAAE,CAAC;CAC1C"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { headers } from "next/headers.js";
|
|
2
|
+
import { toNextJsHandler } from "better-auth/next-js";
|
|
3
|
+
import { asc, eq } from "drizzle-orm";
|
|
4
|
+
import { rateLimitAuthRequest } from "./limits.js";
|
|
5
|
+
import { authSchema } from "./schema.js";
|
|
6
|
+
import { authStatusFor, createAuthInstance, } from "./server.js";
|
|
7
|
+
/**
|
|
8
|
+
* Everything a Next.js product needs from accounts, from one call:
|
|
9
|
+
*
|
|
10
|
+
* export const { GET, POST, getSession, requireUser, authStatus } =
|
|
11
|
+
* createAuthRuntime({ site, mail, isDatabaseConfigured, getDatabase });
|
|
12
|
+
*
|
|
13
|
+
* Built on first request, never at import: `next build` evaluates route
|
|
14
|
+
* modules, and an instance built there would make the build need a database
|
|
15
|
+
* and a secret. A running server without them answers "accounts unavailable"
|
|
16
|
+
* on every auth surface instead of crashing.
|
|
17
|
+
*/
|
|
18
|
+
export function createAuthRuntime(options) {
|
|
19
|
+
let instance = null;
|
|
20
|
+
const getAuth = () => {
|
|
21
|
+
instance ??= createAuthInstance({
|
|
22
|
+
site: options.site,
|
|
23
|
+
mail: options.mail,
|
|
24
|
+
schema: options.schema,
|
|
25
|
+
onAccountCreated: options.onAccountCreated,
|
|
26
|
+
database: options.getDatabase(),
|
|
27
|
+
});
|
|
28
|
+
return instance;
|
|
29
|
+
};
|
|
30
|
+
const authStatus = (env = process.env) => authStatusFor(options.isDatabaseConfigured(env), env);
|
|
31
|
+
const noStore = { "Cache-Control": "no-store" };
|
|
32
|
+
const actorIds = new Map();
|
|
33
|
+
/** The id the product's own rows use for this person. */
|
|
34
|
+
async function actorIdOf(user) {
|
|
35
|
+
const provider = options.legacyIdentityProvider;
|
|
36
|
+
if (!provider)
|
|
37
|
+
return user.id;
|
|
38
|
+
const known = actorIds.get(user.id);
|
|
39
|
+
if (known)
|
|
40
|
+
return known;
|
|
41
|
+
const table = (options.schema?.account ??
|
|
42
|
+
authSchema.account);
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
44
|
+
const db = options.getDatabase();
|
|
45
|
+
// The person's FIRST sign-in method decides: if it was the provider, their
|
|
46
|
+
// rows were written under its subject before this account existed.
|
|
47
|
+
const rows = await db
|
|
48
|
+
.select({ accountId: table.accountId, providerId: table.providerId })
|
|
49
|
+
.from(table)
|
|
50
|
+
.where(eq(table.userId, user.id))
|
|
51
|
+
.orderBy(asc(table.createdAt))
|
|
52
|
+
.limit(1);
|
|
53
|
+
const id = rows[0]?.providerId === provider ? rows[0].accountId : user.id;
|
|
54
|
+
actorIds.set(user.id, id);
|
|
55
|
+
return id;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The session behind these request headers, with the `actorId` the
|
|
59
|
+
* product's rows use — or null. The one reader both `getSession` and
|
|
60
|
+
* `requireUser` go through, so the two cannot disagree about who somebody
|
|
61
|
+
* is.
|
|
62
|
+
*
|
|
63
|
+
* `actorId` is computed HERE and not left to the caller: `getSession` used
|
|
64
|
+
* to return better-auth's raw session, whose user has no `actorId`, while
|
|
65
|
+
* `requireUser` attached one. A product reading `session.user.actorId` in
|
|
66
|
+
* a server component got `undefined` for every signed-in person and drew
|
|
67
|
+
* the signed-out page, while its API routes, going through `requireUser`,
|
|
68
|
+
* worked — which is how the fault stayed invisible.
|
|
69
|
+
*/
|
|
70
|
+
async function sessionFor(requestHeaders) {
|
|
71
|
+
if (!authStatus().ready)
|
|
72
|
+
return null;
|
|
73
|
+
const session = (await getAuth().api.getSession({
|
|
74
|
+
headers: requestHeaders,
|
|
75
|
+
}));
|
|
76
|
+
if (!session)
|
|
77
|
+
return null;
|
|
78
|
+
return {
|
|
79
|
+
...session,
|
|
80
|
+
user: { ...session.user, actorId: await actorIdOf(session.user) },
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/** Who is signed in, for a server component. Null also when accounts are unavailable. */
|
|
84
|
+
async function getSession() {
|
|
85
|
+
// Always cross the request boundary, even when a build has no database or
|
|
86
|
+
// secret. Otherwise Next can pre-render an anonymous redirect permanently.
|
|
87
|
+
// Keep this outside the catch: framework dynamic-render signals must escape.
|
|
88
|
+
const requestHeaders = await headers();
|
|
89
|
+
if (!authStatus().ready)
|
|
90
|
+
return null;
|
|
91
|
+
try {
|
|
92
|
+
return await sessionFor(requestHeaders);
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
console.error(`[auth] session read failed: ${error.name}`);
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/** The signed-in person behind an API request, or the Response to send instead. */
|
|
100
|
+
async function requireUser(request) {
|
|
101
|
+
if (!authStatus().ready) {
|
|
102
|
+
return {
|
|
103
|
+
response: Response.json({ error: "accounts_unavailable" }, { status: 503, headers: noStore }),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const session = await sessionFor(request.headers).catch(() => null);
|
|
107
|
+
if (!session) {
|
|
108
|
+
return {
|
|
109
|
+
response: Response.json({ error: "sign_in_required" }, { status: 401, headers: noStore }),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return { user: session.user };
|
|
113
|
+
}
|
|
114
|
+
async function guard(request) {
|
|
115
|
+
const status = authStatus();
|
|
116
|
+
if (!status.ready) {
|
|
117
|
+
return Response.json({ error: "accounts_unavailable", reason: status.reason }, { status: 503, headers: noStore });
|
|
118
|
+
}
|
|
119
|
+
return rateLimitAuthRequest(request);
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
getAuth,
|
|
123
|
+
authStatus,
|
|
124
|
+
getSession,
|
|
125
|
+
sessionFor,
|
|
126
|
+
requireUser,
|
|
127
|
+
GET: async (request) => (await guard(request)) ?? toNextJsHandler(getAuth()).GET(request),
|
|
128
|
+
POST: async (request) => (await guard(request)) ?? toNextJsHandler(getAuth()).POST(request),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=next.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"next.js","sourceRoot":"","sources":["../../src/auth/next.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { SignInMethods } from "./methods.js";
|
|
3
|
+
import { DEFAULT_AUTH_LABELS, authErrorText, fill, type AuthError, type AuthLabels } from "./labels.js";
|
|
4
|
+
/**
|
|
5
|
+
* The account screens every product shows: sign in, create an account, and
|
|
6
|
+
* the account page. Logic and words here, look in the product: pass `classes`
|
|
7
|
+
* with your own class names and `labels` in your own language. The client is
|
|
8
|
+
* the product's own (`createAuthClient({ plugins: authClientPlugins() })`).
|
|
9
|
+
*/
|
|
10
|
+
type Result<T = unknown> = Promise<{
|
|
11
|
+
data?: T | null;
|
|
12
|
+
error?: AuthError;
|
|
13
|
+
}>;
|
|
14
|
+
/** What these screens call on the product's better-auth client. */
|
|
15
|
+
export interface AuthClientLike {
|
|
16
|
+
requestPasswordReset?(input: {
|
|
17
|
+
email: string;
|
|
18
|
+
redirectTo: string;
|
|
19
|
+
}): Result;
|
|
20
|
+
resetPassword?(input: {
|
|
21
|
+
newPassword: string;
|
|
22
|
+
token: string;
|
|
23
|
+
}): Result;
|
|
24
|
+
signIn: {
|
|
25
|
+
email(input: {
|
|
26
|
+
email: string;
|
|
27
|
+
password: string;
|
|
28
|
+
callbackURL?: string;
|
|
29
|
+
}): Result;
|
|
30
|
+
social(input: {
|
|
31
|
+
provider: string;
|
|
32
|
+
callbackURL?: string;
|
|
33
|
+
errorCallbackURL?: string;
|
|
34
|
+
}): Result;
|
|
35
|
+
magicLink(input: {
|
|
36
|
+
email: string;
|
|
37
|
+
name?: string;
|
|
38
|
+
callbackURL?: string;
|
|
39
|
+
errorCallbackURL?: string;
|
|
40
|
+
}): Result;
|
|
41
|
+
passkey(): Promise<{
|
|
42
|
+
error?: AuthError;
|
|
43
|
+
} | undefined | null>;
|
|
44
|
+
};
|
|
45
|
+
signUp: {
|
|
46
|
+
email(input: {
|
|
47
|
+
name: string;
|
|
48
|
+
email: string;
|
|
49
|
+
password: string;
|
|
50
|
+
callbackURL?: string;
|
|
51
|
+
}): Result;
|
|
52
|
+
};
|
|
53
|
+
signOut(): Result;
|
|
54
|
+
sendVerificationEmail(input: {
|
|
55
|
+
email: string;
|
|
56
|
+
callbackURL?: string;
|
|
57
|
+
}): Result;
|
|
58
|
+
updateUser(input: {
|
|
59
|
+
name: string;
|
|
60
|
+
}): Result;
|
|
61
|
+
deleteUser(input: {
|
|
62
|
+
password?: string;
|
|
63
|
+
}): Result;
|
|
64
|
+
linkSocial(input: {
|
|
65
|
+
provider: string;
|
|
66
|
+
callbackURL?: string;
|
|
67
|
+
}): Result;
|
|
68
|
+
twoFactor: {
|
|
69
|
+
verifyTotp(input: {
|
|
70
|
+
code: string;
|
|
71
|
+
trustDevice?: boolean;
|
|
72
|
+
}): Result;
|
|
73
|
+
verifyBackupCode(input: {
|
|
74
|
+
code: string;
|
|
75
|
+
trustDevice?: boolean;
|
|
76
|
+
}): Result;
|
|
77
|
+
enable(input: {
|
|
78
|
+
password?: string;
|
|
79
|
+
}): Result<object>;
|
|
80
|
+
disable(input: {
|
|
81
|
+
password?: string;
|
|
82
|
+
}): Result;
|
|
83
|
+
};
|
|
84
|
+
passkey: {
|
|
85
|
+
addPasskey(input: {
|
|
86
|
+
name?: string;
|
|
87
|
+
}): Promise<{
|
|
88
|
+
error?: AuthError;
|
|
89
|
+
} | undefined | null>;
|
|
90
|
+
listUserPasskeys(): Result<Passkey[]>;
|
|
91
|
+
deletePasskey(input: {
|
|
92
|
+
id: string;
|
|
93
|
+
}): Result;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
type Passkey = {
|
|
97
|
+
id: string;
|
|
98
|
+
name?: string | null;
|
|
99
|
+
};
|
|
100
|
+
export interface AuthClasses {
|
|
101
|
+
button: string;
|
|
102
|
+
buttonQuiet: string;
|
|
103
|
+
input: string;
|
|
104
|
+
label: string;
|
|
105
|
+
hint: string;
|
|
106
|
+
notice: string;
|
|
107
|
+
error: string;
|
|
108
|
+
section: string;
|
|
109
|
+
sectionTitle: string;
|
|
110
|
+
divider: string;
|
|
111
|
+
link: string;
|
|
112
|
+
stack: string;
|
|
113
|
+
field: string;
|
|
114
|
+
check: string;
|
|
115
|
+
}
|
|
116
|
+
/** Class names styled by @bitbaum/accountkit/styles.css on --acct-* variables. */
|
|
117
|
+
export declare const DEFAULT_AUTH_CLASSES: AuthClasses;
|
|
118
|
+
interface Common {
|
|
119
|
+
client: AuthClientLike;
|
|
120
|
+
methods: SignInMethods;
|
|
121
|
+
labels?: AuthLabels;
|
|
122
|
+
classes?: Partial<AuthClasses>;
|
|
123
|
+
}
|
|
124
|
+
/** "Continue with …" for each OIDC method this deployment has switched on. */
|
|
125
|
+
export declare function OidcButtons({ client, methods, labels, classes, callbackURL, errorCallbackURL, onError, }: Common & {
|
|
126
|
+
callbackURL: string;
|
|
127
|
+
errorCallbackURL: string;
|
|
128
|
+
onError: (error: AuthError) => void;
|
|
129
|
+
}): import("react").JSX.Element | null;
|
|
130
|
+
/**
|
|
131
|
+
* Every way in, on one screen: password, passkey, a link by email, and the
|
|
132
|
+
* OIDC buttons this deployment has switched on. A second factor, when the
|
|
133
|
+
* account has one, is asked for on the same card.
|
|
134
|
+
*/
|
|
135
|
+
export declare function SignInForm({ client, methods, labels, classes, next, signInPath, signUpLink, initialError, }: Common & {
|
|
136
|
+
/** Where to land, already localised (`/de/account`). */
|
|
137
|
+
next: string;
|
|
138
|
+
/** This page, localised: where a failed OIDC round trip comes back to. */
|
|
139
|
+
signInPath: string;
|
|
140
|
+
/** The link to the sign-up page, rendered by the product's router. */
|
|
141
|
+
signUpLink: ReactNode;
|
|
142
|
+
initialError?: boolean;
|
|
143
|
+
}): import("react").JSX.Element;
|
|
144
|
+
export { PasswordRecoveryForm } from "./recovery.js";
|
|
145
|
+
/**
|
|
146
|
+
* A new account in one step. No real name is asked for — a display name is
|
|
147
|
+
* optional and may be anything. A passkey is added from the account page once
|
|
148
|
+
* the account exists.
|
|
149
|
+
*/
|
|
150
|
+
export declare function SignUpForm({ client, methods, labels, classes, next, signUpPath, signInPath, signInLink, }: Common & {
|
|
151
|
+
next: string;
|
|
152
|
+
signUpPath: string;
|
|
153
|
+
/** Where an existing account completes a second factor after passwordless signup. */
|
|
154
|
+
signInPath?: string;
|
|
155
|
+
/** The link to the sign-in page, rendered by the product's router. */
|
|
156
|
+
signInLink: ReactNode;
|
|
157
|
+
}): import("react").JSX.Element;
|
|
158
|
+
/** Everything about one's own account, and the way out of it. */
|
|
159
|
+
export declare function AccountPanel({ client, methods, labels, classes, user, linked, accountPath, homePath, }: Common & {
|
|
160
|
+
user: {
|
|
161
|
+
name: string;
|
|
162
|
+
/** Null when the account has no address that can receive mail. */
|
|
163
|
+
email: string | null;
|
|
164
|
+
emailVerified: boolean;
|
|
165
|
+
role: string;
|
|
166
|
+
twoFactorEnabled: boolean;
|
|
167
|
+
};
|
|
168
|
+
/** Provider ids of the sign-in methods this account has ("credential", "orangecat", …). */
|
|
169
|
+
linked: string[];
|
|
170
|
+
accountPath: string;
|
|
171
|
+
homePath: string;
|
|
172
|
+
}): import("react").JSX.Element;
|
|
173
|
+
export { DEFAULT_AUTH_LABELS, authErrorText, fill, type AuthError, type AuthLabels, };
|
|
174
|
+
//# sourceMappingURL=react.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/auth/react.tsx"],"names":[],"mappings":"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"}
|