368 lines
25 KiB
Plaintext
368 lines
25 KiB
Plaintext
page wrnexusauth {
|
|
seo {
|
|
title = "@wrnexus/auth"
|
|
description = "Authentication routes, sessions, forms, guards, and account flows."
|
|
}
|
|
|
|
view {
|
|
<div class="docs-shell">
|
|
<SkipLink label="Skip to content" href="#main" class="docs-skip-link" />
|
|
<header class="topbar">
|
|
<a class="brand" href="/"><span>W</span> WRNexusJS</a>
|
|
<nav aria-label="Primary"><a href="/getting-started">Get started</a><a href="/packages">Packages</a><a href="https://component.wrnexusjs.dev/">Components</a><a href="/language">Language</a><a href="/architecture">Architecture</a></nav>
|
|
<div class="topbar-actions"><a class="preview-pill" href="/access">Private preview · v0.5.1</a><button data-wire-theme-toggle class="theme-button" aria-label="Toggle color theme" title="Toggle color theme">◐</button></div>
|
|
</header>
|
|
<div class="mobile-doc-nav"><details><summary>Browse documentation</summary><nav><a href="/getting-started">Get started</a><a href="/packages">Packages</a><a href="https://component.wrnexusjs.dev/">Components</a><a href="/language">Language</a><a href="/architecture">Architecture</a><a href="/tutorial">Tutorial</a><a href="/guides/project-structure">Guides</a><a href="/examples">Examples</a><a href="/search">Search</a></nav></details></div>
|
|
<main class="portal-main docs-layout">
|
|
<article id="main" class="documentation prose standalone package-document"><nav class="breadcrumbs" aria-label="Breadcrumb"><a href="/">Home</a><span>/</span><a href="/packages">Packages</a><span>/</span><span aria-current="page">@wrnexus/auth</span></nav><section class="doc-intro"><span class="eyebrow">Security · Package reference</span><h1>@wrnexus/auth</h1><p>Authentication routes, sessions, forms, guards, and account flows.</p><div class="doc-meta"><span>v0.5.1</span><span>Private registry</span><span>Security</span></div><section id="access" class="access-callout"><h2>Install the package</h2><p>After WorkRoot approves private registry access, install the release-aligned package:</p><pre><code>bun add @wrnexus/auth@0.5.1</code><button type="button" class="copy-button" aria-label="Copy installation command">Copy</button></pre><p><a href="/access">Request preview access</a>. Never put registry tokens in source control.</p></section></section><section id="guide"><p>Framework-native authentication, identity, account-security, and session management for WRNexusJS.</p>
|
|
<h3 id="capabilities">Capabilities</h3>
|
|
<ul>
|
|
<li>Password registration, login, recovery, reset, and authenticated password changes</li>
|
|
<li>Email, phone, and username identities with verification and generic resend responses</li>
|
|
<li>Magic links and passwordless email/SMS OTP login</li>
|
|
<li>MFA transactions using verified email OTP, verified SMS OTP, TOTP, or recovery codes</li>
|
|
<li>RFC 6238 TOTP with counter replay protection</li>
|
|
<li>One-use recovery codes; regeneration invalidates previous unused codes</li>
|
|
<li>Passkey/WebAuthn registration and strong passwordless sign-in through a provider contract</li>
|
|
<li>OAuth account linking and provider sign-in</li>
|
|
<li>Invitations, session rotation, idle and absolute expiry, revocation, and trusted devices</li>
|
|
<li>Deny-by-default audited support impersonation</li>
|
|
<li>Adaptive risk scoring, CAPTCHA escalation, temporary lockout, and optional login alerts</li>
|
|
<li>Memory and SQL stores</li>
|
|
<li>Optional encryption-keyring protection for TOTP and OAuth secrets</li>
|
|
<li>Automatic API routes, middleware, browser schemas, components, runtime, migrations, and DevToolbar checks</li>
|
|
</ul>
|
|
<p>Passkeys are a strong sign-in method. They are not currently exposed as a selectable second step in <code>TwoFactorChallenge</code>; the implemented MFA methods are email OTP, SMS OTP, TOTP, and recovery codes.</p>
|
|
<h3 id="install">Install</h3>
|
|
<pre data-language="bash"><code>bun add @wrnexus/auth</code></pre>
|
|
<p>WRNexusJS discovers the package automatically. Do not copy package components, client scripts, schemas, or standard <code>/api/auth/*</code> route files into the application.</p>
|
|
<h3 id="default-configuration">Default configuration</h3>
|
|
<p>Create the engine:</p>
|
|
<pre data-language="ts"><code>// app/lib/auth.ts
|
|
import { createAuthEngine, MemoryAuthStore } from "@wrnexus/auth";
|
|
|
|
export const auth = createAuthEngine({
|
|
store: new MemoryAuthStore(),
|
|
secret: process.env.AUTH_SECRET!,
|
|
issuer: "My application",
|
|
onSignedIn(ctx, returnTo) {
|
|
const safe = returnTo?.startsWith("/") && !returnTo.startsWith("//") ? returnTo : "/account";
|
|
return Response.redirect(new URL(safe, ctx.url), 303);
|
|
},
|
|
onSignedOut(ctx) {
|
|
return Response.redirect(new URL("/sign-in", ctx.url), 303);
|
|
},
|
|
onSuccessfulSignUp() {
|
|
return {
|
|
autoSignIn: true,
|
|
redirectTo: "/account",
|
|
};
|
|
},
|
|
delivery: {
|
|
async send(message) {
|
|
// Queue email/SMS through your provider. Never log message.code or message.token.
|
|
},
|
|
},
|
|
});</code></pre>
|
|
<p>Authentication behavior belongs in this engine definition: delivery, token URL mapping, successful sign-in/sign-out responses, password policy, risk thresholds, MFA, passkeys, and auditing can all be configured in one server-only location. The older <code>config.auth.onSignedIn</code> and <code>config.auth.onSignedOut</code> fields remain supported as compatibility overrides, but new applications should configure these hooks on <code>createAuthEngine</code>.</p>
|
|
<h4 id="successful-signup-behavior">Successful signup behavior</h4>
|
|
<p>Without <code>onSuccessfulSignUp</code>, a successful package registration redirects to <code>/sign-in</code>.</p>
|
|
<p>To sign in immediately after registration:</p>
|
|
<pre data-language="ts"><code>onSuccessfulSignUp(ctx, user) {
|
|
return {
|
|
autoSignIn: true,
|
|
redirectTo: "/account",
|
|
};
|
|
}</code></pre>
|
|
<p>Automatic sign-in runs the normal login policy. It does not bypass required email or phone verification, CAPTCHA, MFA, account status, or risk checks. The hook may also return a <code>Response</code> for a completely custom HTTP result, or return <code>{ redirectTo: "/welcome" }</code> to redirect without creating a session.</p>
|
|
<p>Register it through application configuration:</p>
|
|
<pre data-language="ts"><code>// wrnexus.config.ts
|
|
import type { AuthConfig } from "@wrnexus/auth";
|
|
import type { AppConfig } from "@wrnexus/styles";
|
|
import { auth } from "./app/lib/auth.ts";
|
|
|
|
const config = {
|
|
auth: {
|
|
engine: auth,
|
|
routes: true,
|
|
middleware: true,
|
|
migrations: false,
|
|
},
|
|
} satisfies AppConfig & { auth: AuthConfig };
|
|
|
|
export default config;</code></pre>
|
|
<p>That configuration automatically activates package routes, auth-session middleware, components, browser validation schemas, and the auth client runtime. <code>setDefaultAuthEngine()</code> remains available only for advanced manual integrations and tests.</p>
|
|
<h3 id="sql-production-configuration">SQL production configuration</h3>
|
|
<pre data-language="ts"><code>import { createAuthEngine, SqlAuthStore } from "@wrnexus/auth";
|
|
import { getDb } from "@wrnexus/db";
|
|
|
|
export const auth = createAuthEngine({
|
|
store: new SqlAuthStore(getDb()),
|
|
secret: process.env.AUTH_SECRET!,
|
|
});</code></pre>
|
|
<pre data-language="ts"><code>export default {
|
|
db: {
|
|
// Application database configuration.
|
|
},
|
|
auth: {
|
|
engine: auth,
|
|
routes: true,
|
|
middleware: true,
|
|
migrations: true,
|
|
},
|
|
};</code></pre>
|
|
<p>The package contributes both ordered migrations:</p>
|
|
<pre data-language="text"><code>001_auth.sql
|
|
002_auth_otp_purpose.sql</code></pre>
|
|
<p>Migrations are enabled automatically only when <code>auth.engine</code> and a default <code>config.db</code> are present. Set <code>auth.migrations</code> explicitly when an application needs different behavior.</p>
|
|
<h3 id="delivered-action-urls">Delivered action URLs</h3>
|
|
<p>By default, the engine builds links from the supplied <code>baseUrl</code> and token purpose. Applications can map those links to their own page structure without replacing package APIs:</p>
|
|
<pre data-language="ts"><code>const auth = createAuthEngine({
|
|
store: new SqlAuthStore(getDb()),
|
|
secret: process.env.AUTH_SECRET!,
|
|
tokenUrl({ purpose, token, baseUrl }) {
|
|
if (!baseUrl) return undefined;
|
|
|
|
const paths = {
|
|
"verify-email": `/verify-email?token=${encodeURIComponent(token)}`,
|
|
"verify-phone": `/verify-phone?token=${encodeURIComponent(token)}`,
|
|
"password-reset": `/recover/reset?token=${encodeURIComponent(token)}`,
|
|
"magic-link": `/magic-link?token=${encodeURIComponent(token)}`,
|
|
invite: `/invitation?token=${encodeURIComponent(token)}`,
|
|
};
|
|
|
|
const path = paths[purpose as keyof typeof paths];
|
|
return path ? new URL(path, baseUrl).toString() : undefined;
|
|
},
|
|
});</code></pre>
|
|
<p>Returning <code>undefined</code> intentionally omits the URL while still delivering the raw token. The callback runs only in trusted server code.</p>
|
|
<h3 id="built-in-validation">Built-in validation</h3>
|
|
<p>Every packaged auth form has a built-in <code>@wrnexus/validation</code> schema. The same resolved schema is used by the browser and the package API handler.</p>
|
|
<p>Default use requires no <code>app/schemas</code> files:</p>
|
|
<pre data-language="wrn"><code><SignUp />
|
|
<SignIn />
|
|
<ForgotPassword />
|
|
<ResetPassword token='{token}' />
|
|
<TwoFactorChallenge /></code></pre>
|
|
<p>To customize one schema, extend the package default and register only that override:</p>
|
|
<pre data-language="ts"><code>// app/schemas/custom-password-request.ts
|
|
import { authSchemas } from "@wrnexus/auth";
|
|
import { v } from "@wrnexus/validation";
|
|
|
|
export default authSchemas.passwordResetRequest.extend({
|
|
identifier: v
|
|
.string()
|
|
.trim()
|
|
.required("Enter your registered email address")
|
|
.email("Enter a valid registered email address"),
|
|
});</code></pre>
|
|
<pre data-language="ts"><code>import customPasswordRequest from "./app/schemas/custom-password-request.ts";
|
|
|
|
export default {
|
|
auth: {
|
|
engine: auth,
|
|
schemas: {
|
|
passwordResetRequest: customPasswordRequest,
|
|
},
|
|
},
|
|
};</code></pre>
|
|
<p><code><ForgotPassword /></code> can keep its default <code>schema="auth-password-request"</code>. The plugin automatically publishes the overridden browser descriptor under that same built-in schema ID. All other forms continue using package defaults.</p>
|
|
<h3 id="route-controls">Route controls</h3>
|
|
<p>Use a boolean to enable or disable all package routes:</p>
|
|
<pre data-language="ts"><code>auth: {
|
|
engine: auth,
|
|
routes: true,
|
|
}</code></pre>
|
|
<p>Or control feature groups:</p>
|
|
<pre data-language="ts"><code>routes: {
|
|
enabled: true,
|
|
registration: true,
|
|
login: true,
|
|
verification: true,
|
|
password: true,
|
|
invitations: true,
|
|
magicLink: true,
|
|
otp: true,
|
|
mfa: true,
|
|
sessions: true,
|
|
impersonation: false,
|
|
passkeys: true,
|
|
}</code></pre>
|
|
<p>Application routes have normal framework precedence. Disable a package group only when the application intentionally owns every endpoint in that group; no <code>excludeRoutes</code> list is required.</p>
|
|
<h3 id="package-endpoints">Package endpoints</h3>
|
|
<pre data-language="text"><code>POST /api/auth/register
|
|
POST /api/auth/login
|
|
POST /api/auth/logout
|
|
POST /api/auth/verification/request
|
|
GET|POST /api/auth/verify/email
|
|
POST /api/auth/verify/phone
|
|
POST /api/auth/password/request
|
|
POST /api/auth/password/reset
|
|
POST /api/auth/password/change
|
|
POST /api/auth/invitations/accept
|
|
POST /api/auth/magic-link/request
|
|
GET|POST /api/auth/magic-link
|
|
POST /api/auth/otp/login/request
|
|
POST /api/auth/otp/login/complete
|
|
POST /api/auth/otp
|
|
POST /api/auth/otp/verify
|
|
POST /api/auth/totp/setup
|
|
POST /api/auth/totp/confirm
|
|
POST /api/auth/totp/disable
|
|
POST /api/auth/recovery-codes
|
|
POST /api/auth/mfa/otp
|
|
POST /api/auth/mfa/complete
|
|
GET /api/auth/sessions
|
|
POST /api/auth/sessions/revoke
|
|
POST /api/auth/impersonation/start
|
|
POST /api/auth/impersonation/stop
|
|
POST /api/auth/passkeys/register/options
|
|
POST /api/auth/passkeys/register/verify
|
|
POST /api/auth/passkeys/login/options
|
|
POST /api/auth/passkeys/login/verify</code></pre>
|
|
<p>Each URL uses a route-specific module, so rewritten framework request URLs cannot make the handler fall through to a shared-dispatcher <code>404</code>.</p>
|
|
<p>Unsafe package routes validate the framework CSRF token by default. Set <code>auth.csrf: false</code> only when an external API gateway provides an equivalent protection model.</p>
|
|
<h3 id="components">Components</h3>
|
|
<pre data-language="wrn"><code><SignIn />
|
|
<SignUp />
|
|
<ForgotPassword />
|
|
<ResetPassword token='{token}' />
|
|
<OtpSignIn method="email-otp" />
|
|
<MagicLinkSignIn />
|
|
<PasskeyButton mode="authenticate" />
|
|
<TwoFactorChallenge mfaToken='{mfaToken}' challengeId='{challengeId}' />
|
|
<AuthenticatorSetup credentialId='{credentialId}' secret='{secret}' uri='{uri}' />
|
|
<RecoveryCodes codes='{codes}' />
|
|
<DeviceSessions sessions='{sessions}' currentSessionId='{currentSessionId}' />
|
|
<VerifyEmail token='{token}' identifier='{identifier}' />
|
|
<VerifyPhone token='{token}' identifier='{identifier}' />
|
|
<InvitationAccept token='{token}' />
|
|
<ImpersonationBanner targetName='{targetName}' />
|
|
<AccountStatus status='{account.status}' /></code></pre>
|
|
<p><code>identifier</code> is optional on verification components. Supply it when an unauthenticated verification page should support resending a token. The response remains generic whether the account exists or not.</p>
|
|
<h3 id="captcha-and-risk">CAPTCHA and risk</h3>
|
|
<p>The HTTP handlers never trust a browser <code>captchaVerified</code> field. CAPTCHA completion is accepted only from server-populated <code>ctx.locals.captcha.success</code> or <code>ctx.locals.captchaVerified === true</code>.</p>
|
|
<p>Rate limiting remains an application or gateway responsibility. Apply it to registration, login, reset, magic-link, OTP, verification, passkey, invitation, and impersonation endpoints.</p>
|
|
<h3 id="mfa">MFA</h3>
|
|
<p>1. Password, OAuth, magic-link, or OTP login may return <code>code: "mfa-required"</code> with a short-lived <code>mfaToken</code>. 2. The response lists only methods actually available to that user. 3. Email/SMS MFA is offered only for verified linked identities. 4. <code>beginMfaOtp()</code> issues an MFA-bound OTP when needed. 5. <code>completeMfa()</code> consumes the one-time transaction and creates the session.</p>
|
|
<h3 id="passkeys">Passkeys</h3>
|
|
<p>The browser runtime coordinates <code>navigator.credentials.create()</code> and <code>navigator.credentials.get()</code>. A configured server-side <code>PasskeyProvider</code> must verify the challenge, RP ID, origin, signature, user presence or verification, counter, and credential ownership.</p>
|
|
<p>Multi-process deployments must provide a shared <code>PasskeyChallengeStore</code>; the default memory implementation is process-local. Missing passkey providers return a controlled <code>503</code> response rather than crashing the route.</p>
|
|
<h3 id="protect-long-lived-secrets">Protect long-lived secrets</h3>
|
|
<pre data-language="ts"><code>import { createAuthSecretProtector } from "@wrnexus/auth";
|
|
import { createKeyring } from "@wrnexus/encryption";
|
|
|
|
const keyring = createKeyring([
|
|
{
|
|
id: "auth-2026-01",
|
|
secret: process.env.AUTH_ENCRYPTION_KEY!,
|
|
active: true,
|
|
},
|
|
]);
|
|
|
|
const auth = createAuthEngine({
|
|
store: new SqlAuthStore(getDb()),
|
|
secret: process.env.AUTH_SECRET!,
|
|
secretProtector: createAuthSecretProtector(keyring),
|
|
});</code></pre>
|
|
<p>TOTP seeds and OAuth access/refresh tokens are protected before persistence. Keep old keys available during rotation.</p>
|
|
<h3 id="custom-http-integration">Custom HTTP integration</h3>
|
|
<p><code>createAuthHttpHandlers()</code> remains available for custom route paths or response behavior. Prefer package routes for standard flows; copied application API files are unnecessary.</p>
|
|
<h3 id="development">Development</h3>
|
|
<pre data-language="bash"><code>bun run auth:dev
|
|
bun run validate:auth</code></pre>
|
|
<p>Read [SECURITY.md](./SECURITY.md) before production deployment.</p></section><section id="api" class="api"><h2>Complete TypeScript API</h2><p>Generated from the exact installed package declarations.</p><pre data-language="typescript"><code>export { A as AuthEngine, c as createAuthEngine, i as inferIdentityType, n as normalizeEmail, a as normalizeIdentity, b as normalizePhone, d as normalizeUsername, p as publicUser, s as safeAuthReturnTo } from './engine-jttXj6PP.js';
|
|
import { n as AuthRiskSignals, l as AuthRiskDecision } from './types-JLkQpcAt.js';
|
|
export { A as AuthAccountStatus, a as AuthClock, b as AuthDeliveryMessage, c as AuthDeliveryProvider, d as AuthEngineOptions, e as AuthIdentity, f as AuthIdentityType, g as AuthImpersonationDecision, h as AuthMfaMethod, i as AuthPublicUser, j as AuthRandom, k as AuthResult, m as AuthRiskLevel, o as AuthSecretProtector, p as AuthSecurityEvent, q as AuthSession, r as AuthSignedInHandler, s as AuthSignedOutHandler, M as AuthStore, t as AuthSuccessfulSignUpAction, u as AuthSuccessfulSignUpHandler, v as AuthTokenPurpose, w as AuthTokenUrlInput, x as AuthUser, y as AuthenticatedContext, L as LoginAttempt, z as LoginInput, N as MemoryPasskeyChallengeStore, O as OAuthAccount, B as OneTimeToken, C as OtpChallenge, P as PasskeyAuthenticationOptions, Q as PasskeyChallengeKind, S as PasskeyChallengeRecord, U as PasskeyChallengeStore, D as PasskeyCredential, E as PasskeyProvider, F as PasskeyRegistrationOptions, G as PasskeyVerificationResult, H as PasswordBreachProvider, I as PasswordCredential, R as RecoveryCodeRecord, J as RegisterInput, T as TotpCredential, K as TrustedDevice, V as assertPasskeyProvider } from './types-JLkQpcAt.js';
|
|
export { MemoryAuthStore } from './stores/memory.js';
|
|
export { SqlAuthStore } from './stores/sql.js';
|
|
export { AUTH_SESSION_KEY, authSession, clearAuthSession, establishAuthSession, getAuthSession, getAuthUser, isAuthenticatedContext, requireAuth } from './middleware.js';
|
|
export { A as AuthHttpOptions, a as AuthPasskeyHttpOptions, b as AuthSchemaOverrides, c as AuthSchemaSet, d as authBrowserSchemaDescriptors, e as authBrowserSchemaMap, f as authSchemas, g as authenticatorConfirmSchema, h as authenticatorDisableSchema, i as authenticatorSetupSchema, j as changePasswordSchema, k as createAuthHttpHandlers, l as emptyActionSchema, m as impersonationStartSchema, n as invitationAcceptSchema, o as loginSchema, p as magicLinkConsumeSchema, q as magicLinkRequestSchema, r as mfaOtpRequestSchema, s as mfaSchema, t as otpIssueSchema, u as otpLoginCompleteSchema, v as otpLoginRequestSchema, w as otpSchema, x as passkeyAuthenticationOptionsSchema, y as passkeyAuthenticationVerifySchema, z as passkeyRegistrationOptionsSchema, B as passkeyRegistrationVerifySchema, C as passwordResetRequestSchema, D as passwordResetSchema, E as recoveryCodesSchema, F as registerSchema, G as resolveAuthSchemas, H as sessionRevokeSchema, I as signUpSchema, J as verificationRequestSchema, K as verificationTokenSchema } from './index-CrF_lZDQ.js';
|
|
export { AuthAuditIssue, AuthConfig, AuthPluginOptions, AuthRoutesConfig, authComponentsDir, authPlugin } from './plugin.js';
|
|
export { DefaultAuthRouteOptions, clearDefaultAuthEngine, getDefaultAuthEngine, getDefaultAuthRouteOptions, getDefaultAuthSchemas, hasDefaultAuthEngine, setDefaultAuthEngine, setDefaultAuthRouteOptions, setDefaultAuthSchemas, tryGetDefaultAuthEngine } from './runtime.js';
|
|
export { createAuthSecretProtector } from './protector.js';
|
|
export { decodeBase32, encodeBase32, generateTotp, generateTotpSecret, totpUri, verifyTotp } from './totp/index.js';
|
|
import '@wrnexus/oauth';
|
|
import '@wrnexus/core';
|
|
import '@wrnexus/db';
|
|
import '@wrnexus/validation';
|
|
import '@wrnexus/plugin';
|
|
import '@wrnexus/encryption';
|
|
|
|
interface RiskPolicy {
|
|
captchaThreshold: number;
|
|
mfaThreshold: number;
|
|
blockThreshold: number;
|
|
}
|
|
declare function evaluateAuthRisk(signals?: AuthRiskSignals, policy?: RiskPolicy): AuthRiskDecision;
|
|
|
|
export { AuthRiskDecision, AuthRiskSignals, type RiskPolicy, evaluateAuthRisk };
|
|
</code></pre></section><section id="examples" class="examples"><h2>Examples</h2><p>Copy-ready examples from the installed package documentation.</p><div class="example-grid"><article class="example-card"><h3>## Install</h3><pre data-language="bash"><code>bun add @wrnexus/auth</code></pre></article><article class="example-card"><h3>Create the engine</h3><pre data-language="ts"><code>// app/lib/auth.ts
|
|
import { createAuthEngine, MemoryAuthStore } from "@wrnexus/auth";
|
|
|
|
export const auth = createAuthEngine({
|
|
store: new MemoryAuthStore(),
|
|
secret: process.env.AUTH_SECRET!,
|
|
issuer: "My application",
|
|
onSignedIn(ctx, returnTo) {
|
|
const safe = returnTo?.startsWith("/") && !returnTo.startsWith("//") ? returnTo : "/account";
|
|
return Response.redirect(new URL(safe, ctx.url), 303);
|
|
},
|
|
onSignedOut(ctx) {
|
|
return Response.redirect(new URL("/sign-in", ctx.url), 303);
|
|
},
|
|
onSuccessfulSignUp() {
|
|
return {
|
|
autoSignIn: true,
|
|
redirectTo: "/account",
|
|
};
|
|
},
|
|
delivery: {
|
|
async send(message) {
|
|
// Queue email/SMS through your provider. Never log message.code or message.token.
|
|
},
|
|
},
|
|
});</code></pre></article><article class="example-card"><h3>Successful signup behavior</h3><pre data-language="ts"><code>onSuccessfulSignUp(ctx, user) {
|
|
return {
|
|
autoSignIn: true,
|
|
redirectTo: "/account",
|
|
};
|
|
}</code></pre></article><article class="example-card"><h3>Successful signup behavior</h3><pre data-language="ts"><code>// wrnexus.config.ts
|
|
import type { AuthConfig } from "@wrnexus/auth";
|
|
import type { AppConfig } from "@wrnexus/styles";
|
|
import { auth } from "./app/lib/auth.ts";
|
|
|
|
const config = {
|
|
auth: {
|
|
engine: auth,
|
|
routes: true,
|
|
middleware: true,
|
|
migrations: false,
|
|
},
|
|
} satisfies AppConfig & { auth: AuthConfig };
|
|
|
|
export default config;</code></pre></article><article class="example-card"><h3>Successful signup behavior</h3><pre data-language="ts"><code>import { createAuthEngine, SqlAuthStore } from "@wrnexus/auth";
|
|
import { getDb } from "@wrnexus/db";
|
|
|
|
export const auth = createAuthEngine({
|
|
store: new SqlAuthStore(getDb()),
|
|
secret: process.env.AUTH_SECRET!,
|
|
});</code></pre></article><article class="example-card"><h3>Successful signup behavior</h3><pre data-language="ts"><code>export default {
|
|
db: {
|
|
// Application database configuration.
|
|
},
|
|
auth: {
|
|
engine: auth,
|
|
routes: true,
|
|
middleware: true,
|
|
migrations: true,
|
|
},
|
|
};</code></pre></article></div></section></article>
|
|
<aside class="on-this-page"><h2>On this page</h2><nav><a class="toc-level-2" href="#guide">Guide</a><a class="toc-level-3" href="#capabilities">Capabilities</a><a class="toc-level-3" href="#install">Install</a><a class="toc-level-3" href="#default-configuration">Default configuration</a><a class="toc-level-4" href="#successful-signup-behavior">Successful signup behavior</a><a class="toc-level-3" href="#sql-production-configuration">SQL production configuration</a><a class="toc-level-3" href="#delivered-action-urls">Delivered action URLs</a><a class="toc-level-3" href="#built-in-validation">Built-in validation</a><a class="toc-level-3" href="#route-controls">Route controls</a><a class="toc-level-3" href="#package-endpoints">Package endpoints</a><a class="toc-level-3" href="#components">Components</a><a class="toc-level-3" href="#captcha-and-risk">CAPTCHA and risk</a><a class="toc-level-3" href="#mfa">MFA</a><a class="toc-level-3" href="#passkeys">Passkeys</a><a class="toc-level-3" href="#protect-long-lived-secrets">Protect long-lived secrets</a><a class="toc-level-3" href="#custom-http-integration">Custom HTTP integration</a><a class="toc-level-3" href="#development">Development</a><a class="toc-level-2" href="#api">Complete API</a><a class="toc-level-2" href="#examples">Examples</a></nav></aside>
|
|
</main>
|
|
<footer><div class="footer-brand"><span class="footer-mark" aria-hidden="true">W</span><p><strong>WRNexusJS 0.5.1</strong><span>Complete API documentation generated from installed package declarations.</span></p></div><nav aria-label="Footer"><a href="/packages">All packages</a><a href="/getting-started">Get started</a><a href="/security">Security</a><a href="/support">Support</a><a href="/llms.txt">AI guide</a></nav><p class="footer-meta">Private Developer Preview · Bun-native</p></footer>
|
|
<BackToTop />
|
|
</div>
|
|
}
|
|
}
|