Auth API reference
Current emitted signatures and options for @db3.ai/app/auth.
On this page
Source-backed MarkdownImports and examples
Import supported APIs from @db3.ai/app/auth. These signatures come from the staged package used by consumers. Relative filenames in declarations describe type dependencies; they are not extra supported deep imports.
Use the guide for setup, executable examples, failure handling and ownership. A signature is not proof that every deployment or provider has been exercised.
Account, provider and session operations
ts
import { type Database } from '../db/index.js';
import type { Config } from '../config/index.js';
import { AuthProvider } from './AuthProvider.js';
import { AuthToken, type AuthTokenUsage, type CreateAuthTokenOptions } from './AuthToken.js';
import { PasswordResetToken } from './PasswordResetToken.js';
import { type PasswordHash } from './passwordHash.js';
import { UserIdentity, type UserIdentityModel } from './UserIdentity.js';
import type * as auth from './contracts/index.js';
/**
* Credentials accepted by the built-in password provider.
*
* Apps may include the configured identity field, usually `email`, alongside
* the password so the auth service can locate the provider row.
*/
export interface PasswordCredentials {
/**
* Plaintext password submitted by the user.
*/
password: string;
/**
* Additional credential fields, including the configured identity value.
*/
[fieldName: string]: unknown;
}
/**
* Input used when creating a user through the built-in password provider.
*/
export interface RegisterPasswordInput extends PasswordCredentials {
/**
* Additional user fields accepted by the configured identity model.
*/
[fieldName: string]: unknown;
}
/**
* Backwards-compatible alias for password credentials.
*/
export type AuthCredentials = PasswordCredentials;
/**
* Backwards-compatible alias for password registration input.
*/
export type RegisterIdentityInput = RegisterPasswordInput;
/**
* Request payload used to redeem a password reset token.
*
* Additional fields allow apps to include the configured identity value, such
* as an email address, so token redemption can confirm the link belongs to the
* submitted identity.
*/
export interface ResetPasswordInput {
[fieldName: string]: unknown;
token: string;
password: string;
}
/**
* Bearer token issued for an authenticated user.
*/
export interface IssuedAuthToken<TIdentity extends UserIdentity = UserIdentity> {
/**
* Token type used in HTTP Authorization headers.
*/
type: 'Bearer';
/**
* Plaintext bearer token shown once to the caller.
*/
token: string;
/**
* Absolute expiry time, or null for a non-expiring token.
*/
expiresAt: Date | null;
/**
* Authenticated identity the token belongs to.
*/
user: TIdentity;
}
/**
* Password reset token issued for an identity.
*/
export interface IssuedPasswordResetToken<TIdentity extends UserIdentity = UserIdentity> {
/**
* Token purpose marker.
*/
type: 'password_reset';
/**
* Plaintext reset token shown once to the caller.
*/
token: string;
/**
* Absolute expiry time for the reset token.
*/
expiresAt: Date;
/**
* Identity the reset token belongs to.
*/
user: TIdentity;
}
/**
* Options used when issuing a bearer token.
*/
export interface AuthTokenOptions extends CreateAuthTokenOptions {
/**
* Relative token lifetime in milliseconds. Null disables token expiry.
*/
expiresInMs?: number | null;
}
export interface PasswordResetTokenOptions {
/**
* Absolute timestamp when the token should stop being usable.
*/
expiresAt?: Date;
/**
* Relative token lifetime in milliseconds when an absolute expiry is not supplied.
*/
expiresInMs?: number;
}
/**
* Initial values accepted by an auth request context.
*/
export type AuthRequestContextValues = Map<string, unknown> | Record<string, unknown> | Iterable<readonly [string, unknown]>;
/**
* Request-scoped storage used to isolate auth state between concurrent requests.
*/
export interface AuthRequestContext {
/**
* True when code is running inside an active request context.
*/
active: boolean;
/**
* Runs a callback with optional initial request-scoped values.
*
* @param callback - Work to run inside the request context.
* @param initialValues - Optional values to seed into the context.
* @returns The callback result.
*/
run<TResult>(callback: () => TResult, initialValues?: AuthRequestContextValues): TResult;
/**
* Reads a request-scoped value.
*
* @param key - Context key to read.
* @returns Stored value, or undefined when missing.
*/
get<TValue = unknown>(key: string): TValue | undefined;
/**
* Stores a request-scoped value.
*
* @param key - Context key to write.
* @param value - Value to store.
* @returns The stored value.
*/
set<TValue>(key: string, value: TValue): TValue;
/**
* Reads a value or stores the factory result when missing.
*
* @param key - Context key to read or populate.
* @param factory - Factory used when no value has been stored.
* @returns Existing or newly-created value.
*/
remember<TValue>(key: string, factory: () => TValue): TValue;
}
/**
* Runtime options for the framework auth service.
*/
export interface AuthOptions<TIdentity extends UserIdentity = UserIdentity> {
/**
* Database wrapper used for auth persistence.
*/
db: Database;
/**
* User identity model for the host app.
*/
identityModel?: UserIdentityModel<TIdentity>;
/**
* Provider-link model. Override only when extending provider persistence.
*/
providerModel?: typeof AuthProvider;
/**
* Authentication providers enabled for the app.
*/
providers?: auth.AuthProviderRegistry<TIdentity>;
/**
* App config repository used to read `auth.providers` when explicit
* providers are not supplied.
*/
config?: Config;
/**
* Password hashing service for password provider credentials.
*/
passwordHash?: PasswordHash;
/**
* Bearer token model.
*/
tokenModel?: typeof AuthToken;
/**
* Default bearer token lifetime in milliseconds. Null disables expiry.
*/
tokenLifetimeMs?: number | null;
/**
* Password reset token model.
*/
passwordResetTokenModel?: typeof PasswordResetToken;
/**
* Default password reset token lifetime in milliseconds.
*/
passwordResetTokenLifetimeMs?: number;
/**
* Request context used to isolate current-user state.
*/
requestContext?: AuthRequestContext;
}
/**
* Error thrown when registration would duplicate an existing identity.
*/
export declare class AuthIdentityExistsError extends Error {
readonly field: string;
readonly value: unknown;
/**
* Creates an identity duplication error.
*
* @param field - Logical identity field that collided.
* @param value - Submitted identity value.
*/
constructor(field: string, value: unknown);
}
/**
* Error thrown when code attempts to use a disabled auth provider.
*/
export declare class AuthProviderNotConfiguredError extends Error {
readonly provider: string;
/**
* Creates a provider configuration error.
*
* @param provider - Provider name that is not enabled.
*/
constructor(provider: string);
}
/**
* Error thrown when unlinking a provider would leave a user unable to log in.
*/
export declare class AuthLastProviderError extends Error {
/**
* Creates a last-provider removal error.
*/
constructor();
}
export declare const AUTH_USER_CONTEXT_KEY = "auth.user";
/**
* Authentication service for the current app/request scope.
*/
export declare class Auth<TIdentity extends UserIdentity = UserIdentity> {
private fallbackAuthenticatedUser;
private fallbackAuthenticatedToken;
private readonly db;
private readonly IdentityModel;
private readonly ProviderModel;
private readonly TokenModel;
private readonly PasswordResetTokenModel;
private readonly providerRegistry;
private readonly passwordHash;
private readonly tokenLifetimeMs;
private readonly passwordResetTokenLifetimeMs;
private readonly requestContext?;
/**
* Creates an auth service bound to a database and provider registry.
*
* @param options - Auth runtime options.
*/
constructor(options: AuthOptions<TIdentity>);
/**
* Hashes a plaintext password using the configured auth password service.
*
* @param plainText - Plaintext password to hash.
* @returns Stored password hash.
*/
hashPassword(plainText: string): Promise<string>;
/**
* Verifies a plaintext password against a stored password hash.
*
* @param plainText - Plaintext password supplied by the user.
* @param hash - Stored password hash.
* @returns True when the password matches.
*/
verifyPassword(plainText: string, hash: string): Promise<boolean>;
/**
* Returns configured authentication provider names.
*
* @returns Enabled provider names.
*/
configuredProviders(): string[];
/**
* True when a user is currently authenticated.
*/
get check(): boolean;
/**
* The currently authenticated user, or null when no user is authenticated.
*/
get user(): TIdentity | null;
/**
* Returns the bearer-token record authenticated for the current request.
*/
get token(): AuthToken | null;
/**
* Runs work inside an isolated auth scope.
*
* HTTP routes should use this so `auth.user` cannot bleed between concurrent
* requests on the shared app singleton.
*
* @param user - User to expose as authenticated inside the callback.
* @param callback - Work to run inside the auth scope.
* @returns The callback result.
*/
runWithUser<TResult>(user: TIdentity | null, callback: () => TResult): TResult;
/**
* Attempts to authenticate password credentials and stores the user on success.
*
* @param credentials - Password provider credentials.
* @returns True when credentials authenticated successfully.
*/
attempt(credentials: PasswordCredentials): Promise<boolean>;
/**
* Authenticates password credentials and returns the user on success.
*
* @param credentials - Password provider credentials.
* @returns Authenticated user, or null when credentials fail.
*/
authenticate(credentials: PasswordCredentials): Promise<TIdentity | null>;
/**
* Authenticates password credentials and returns the user on success.
*
* @param credentials - Password provider credentials.
* @returns Authenticated user, or null when credentials fail.
*/
authenticatePassword(credentials: PasswordCredentials): Promise<TIdentity | null>;
/**
* Authenticates credentials and creates a bearer token on success.
*
* @param credentials - Password provider credentials.
* @param options - Token creation options.
* @returns Issued token, or null when credentials fail.
*/
issueToken(credentials: PasswordCredentials, options?: AuthTokenOptions): Promise<IssuedAuthToken<TIdentity> | null>;
/**
* Authenticates password credentials and creates a bearer token on success.
*
* @param credentials - Password provider credentials.
* @param options - Token creation options.
* @returns Issued token, or null when credentials fail.
*/
issueTokenForPassword(credentials: PasswordCredentials, options?: AuthTokenOptions): Promise<IssuedAuthToken<TIdentity> | null>;
/**
* Authenticates through a configured provider and creates a bearer token.
*
* @param provider - Configured provider name.
* @param input - Provider-specific credential payload.
* @param options - Token creation options.
* @returns Issued token, or null when provider verification fails.
*/
issueTokenForProvider(provider: string, input: unknown, options?: AuthTokenOptions): Promise<IssuedAuthToken<TIdentity> | null>;
/**
* Creates a new password-backed identity and returns its first bearer token.
*
* @param input - User fields and password provider credential.
* @param options - Token creation options.
* @returns Issued token for the new user.
*/
register(input: RegisterPasswordInput, options?: AuthTokenOptions): Promise<IssuedAuthToken<TIdentity>>;
/**
* Creates a new user and links the built-in password provider.
*
* @param input - User fields and password provider credential.
* @param options - Token creation options.
* @returns Issued token for the new user.
*/
registerWithPassword(input: RegisterPasswordInput, options?: AuthTokenOptions): Promise<IssuedAuthToken<TIdentity>>;
/**
* Returns the authentication providers linked to a user.
*
* @param user - User whose providers should be loaded.
* @returns Provider rows linked to the user.
*/
providersFor(user: TIdentity): Promise<AuthProvider[]>;
/**
* Links a configured provider to an existing user.
*
* @param user - User receiving the new provider link.
* @param provider - Configured provider name.
* @param input - Provider-specific credential payload.
* @returns Linked provider row, or null when verification fails.
*/
linkProvider(user: TIdentity, provider: string, input: unknown): Promise<AuthProvider | null>;
/**
* Removes one provider from a user while preserving at least one login path.
*
* @param user - User whose provider should be removed.
* @param providerIdOrName - Provider row id or provider name to remove.
* @returns True when a provider row was deleted.
*/
unlinkProvider(user: TIdentity, providerIdOrName: string): Promise<boolean>;
/**
* Creates or replaces the built-in password provider for a user.
*
* @param user - User who owns the password provider.
* @param password - New plaintext password to hash and store.
* @returns Saved password provider row.
*/
setPasswordProvider(user: TIdentity, password: string): Promise<AuthProvider>;
/**
* Changes a user's password provider after verifying the current password.
*
* @param user - User whose password should change.
* @param currentPassword - Current plaintext password for verification.
* @param nextPassword - Replacement plaintext password.
* @returns True when the password was changed.
*/
changePasswordProvider(user: TIdentity, currentPassword: string, nextPassword: string): Promise<boolean>;
/**
* Authenticates through a non-password provider and stores the user on success.
*
* @param provider - Configured provider name.
* @param input - Provider-specific credential payload.
* @returns Authenticated user, or null when verification fails.
*/
authenticateProvider(provider: string, input: unknown): Promise<TIdentity | null>;
/**
* Creates a single-use password reset token for an already-loaded identity.
*
* Callers should find the identity at the request boundary and pass the
* loaded model here so token creation only owns token persistence.
*
* @param user - Identity receiving the reset token.
* @param options - Reset token creation options.
* @returns Issued password reset token.
*/
createPasswordResetToken(user: TIdentity, options?: PasswordResetTokenOptions): Promise<IssuedPasswordResetToken<TIdentity>>;
/**
* Resets the password provider using a valid password reset token.
*
* @param input - Reset token, new password, and optional identity value.
* @returns Identity whose password changed, or null when redemption fails.
*/
resetPassword(input: ResetPasswordInput): Promise<TIdentity | null>;
/**
* Creates a bearer token for an already-authenticated identity.
*
* @param user - Identity receiving the bearer token.
* @param options - Token creation options.
* @returns Issued bearer token.
*/
createToken(user: TIdentity, options?: AuthTokenOptions): Promise<IssuedAuthToken<TIdentity>>;
/**
* Authenticates a bearer token and stores the matching identity on success.
*
* @param token - Plaintext bearer token.
* @param usage - Request metadata observed while authenticating the token.
* @returns Authenticated identity, or null when the token is invalid.
*/
authenticateToken(token: string, usage?: AuthTokenUsage): Promise<TIdentity | null>;
/**
* Returns active bearer sessions belonging to a user.
*
* @param user - Account whose sessions should be listed.
* @returns Active, non-expired sessions ordered newest first.
*/
tokensFor(user: TIdentity): Promise<AuthToken[]>;
/**
* Revokes one bearer session owned by a user.
*
* @param user - Account that owns the session.
* @param tokenId - Auth token primary key.
* @returns True when an active session was revoked.
*/
revokeToken(user: TIdentity, tokenId: string): Promise<boolean>;
/**
* Revokes the bearer session authenticated for the current request.
*
* @returns True when the current session was revoked.
*/
revokeCurrentToken(): Promise<boolean>;
/**
* Builds the request-context key used to memoize bearer-token authentication.
*
* @param tokenHash - Hashed bearer token.
* @returns Request-context cache key.
*/
private tokenContextKey;
/**
* Authenticates a pre-hashed bearer token against persistent auth records.
*
* @param tokenHash - Hashed bearer token.
* @returns Authenticated identity, or null when the token is invalid.
*/
private authenticateTokenHash;
/**
* Marks a user model as authenticated.
*
* @param user - User to mark as authenticated.
* @returns The saved authenticated user.
*/
login(user: TIdentity): Promise<TIdentity>;
/**
* Clears the authenticated user.
*/
logout(): void;
/**
* Returns the authenticated user or throws when auth is missing.
*
* @returns The current authenticated user.
*/
requireUser(): TIdentity;
/**
* Verifies provider-specific input and normalizes the returned profile.
*
* @param provider - Configured provider name.
* @param input - Provider-specific credential payload.
* @param user - Current user when linking a provider.
* @returns Normalized provider profile, or null when verification fails.
*/
private verifyProvider;
/**
* Resolves a configured provider or throws a configuration error.
*
* @param provider - Provider name to resolve.
* @returns Provider configuration.
*/
private requireProvider;
/**
* Resolves the configured password provider.
*
* @returns Password provider driver with password mutation helpers.
*/
private passwordProvider;
/**
* Saves a verified provider profile onto a user account.
*
* @param user - User receiving the provider link.
* @param profile - Verified provider profile.
* @returns Saved provider row.
*/
private saveLinkedProvider;
/**
* Finds a provider row by provider-owned identity.
*
* @param provider - Provider name.
* @param providerUserId - Provider-owned account id.
* @returns Matching provider row, or null.
*/
private findProvider;
/**
* Loads the user attached to a provider row.
*
* @param provider - Persisted provider row.
* @returns Linked identity, or null when missing.
*/
private userForProvider;
/**
* Creates a user account from a verified external provider profile.
*
* @param profile - Verified provider profile.
* @returns Created identity, or null when no email is available.
*/
private createIdentityForProvider;
/**
* Backfills account-owned profile fields from a verified provider profile.
*
* Provider values are defaults only. Existing account values are preserved
* so a later user-selected avatar is not overwritten during provider login.
* The normal login save persists any backfilled values.
*
* @param user - Authenticated account receiving missing defaults.
* @param profile - Verified provider profile.
*/
private applyProviderProfileDefaults;
/**
* Stores the current authenticated user in request or fallback scope.
*
* @param user - User to expose as authenticated.
*/
private setAuthenticatedUser;
/**
* Stores the authenticated token in request or fallback scope.
*
* @param token - Token record to expose for session management.
*/
private setAuthenticatedToken;
/**
* Runs a callback with a temporary fallback user outside request scope.
*
* @param user - User to expose during the callback.
* @param callback - Work to run with the temporary user.
* @returns The callback result.
*/
private runWithFallbackUser;
/**
* Finds an identity by the configured identity field.
*
* @param input - Payload containing the configured identity value.
* @returns Matching identity, or null.
*/
private findIdentity;
/**
* Checks whether password reset input belongs to the loaded user.
*
* @param input - Reset password payload.
* @param user - User loaded from the reset token.
* @returns True when the submitted identity is absent or matches the token user.
*/
private passwordResetIdentityMatches;
/**
* Reads a user primary key as a non-empty string.
*
* @param user - User model to inspect.
* @returns Primary key string, or null when missing.
*/
private userPrimaryKey;
/**
* Reads the configured identity value from a user.
*
* @param user - User model to inspect.
* @returns Normalized identity value, or null when missing.
*/
private userIdentityValue;
/**
* Reads the configured identity value from a payload.
*
* @param input - Payload to inspect.
* @returns Normalized identity value, or null when missing.
*/
private normalizedIdentity;
/**
* Calculates the default bearer token expiry.
*
* @param expiresInMs - Optional token lifetime override.
* @returns Absolute expiry time, or null for a non-expiring token.
*/
private defaultTokenExpiry;
/**
* Calculates the default password reset token expiry.
*
* @param expiresInMs - Optional reset token lifetime override.
* @returns Absolute expiry time.
*/
private defaultPasswordResetTokenExpiry;
}
Account model
ts
import { ActiveRecord, type ActiveRecordClass, type FieldBuilder } from '../db/index.js';
type RecoveryCodes = string[];
export type UserIdentityModel<TIdentity extends UserIdentity = UserIdentity> = ActiveRecordClass<TIdentity> & {
identityField: string;
};
/**
* Auth-owned base user model.
*
* Apps can extend this model to add domain-specific fields and behaviour while
* the auth package keeps ownership of account identity fields. Credential
* storage lives on `AuthProvider` rows so users can link multiple login methods.
*/
export declare class UserIdentity extends ActiveRecord {
static table: string;
static primaryKey: string;
static identityField: string;
static fields(field: FieldBuilder): {
id: import("../db/index.js").UlidField;
name: import("../db/index.js").StringField;
email: import("../db/index.js").EmailField;
emailVerifiedAt: import("../db/index.js").TimestampField;
avatarUrl: import("../db/index.js").StringField;
rememberToken: import("../db/index.js").StringField;
createdAt: import("../db/index.js").TimestampField;
updatedAt: import("../db/index.js").TimestampField;
twoFactorSecret: import("../db/index.js").TextField;
twoFactorRecoveryCodes: import("../db/index.js").JsonStringField<RecoveryCodes>;
twoFactorConfirmedAt: import("../db/index.js").TimestampField;
lastLoginAt: import("../db/index.js").TimestampField;
};
id: string | null;
name: string | null;
email: string | null;
emailVerifiedAt: Date | null;
avatarUrl: string | null;
rememberToken: string | null;
createdAt: Date | null;
updatedAt: Date | null;
twoFactorSecret: string | null;
twoFactorRecoveryCodes: RecoveryCodes | null;
twoFactorConfirmedAt: Date | null;
lastLoginAt: Date | null;
get emailDomain(): string | null;
markEmailVerified(date?: Date): void;
}
export {};
Provider model and safe summary
ts
import { ActiveRecord, PasswordField, type FieldBuilder } from '../db/index.js';
import type * as auth from './contracts/index.js';
import { type PasswordHash } from './passwordHash.js';
export declare const PASSWORD_AUTH_PROVIDER = "password";
/** Safe provider metadata suitable for account-management screens. */
export interface AuthProviderSummary {
/** Persistent provider-row identifier used for scoped removal. */
id: string;
/** Stable provider name such as password or google. */
provider: string;
/** Human-friendly provider label. */
label: string | null;
/** Email address reported or owned by the provider. */
email: string | null;
/** Avatar URL reported by the provider. */
avatarUrl: string | null;
/** Most recent successful login through this provider. */
lastLoginAt: string | null;
/** Time the provider was linked to the account. */
createdAt: string | null;
}
/**
* Persisted authentication method linked to one user account.
*
* Password, Google, magic-link, and future login mechanisms all share this
* model. Provider-specific verification happens in the auth service or a
* provider driver; this model owns the durable account-to-provider link.
*/
export declare class AuthProvider extends ActiveRecord {
static table: string;
static primaryKey: string;
static comment: string;
/**
* Defines the provider link, credential, and display metadata columns.
*
* @param field - Framework field builder.
* @returns Field definitions for the auth provider table.
*/
static fields(field: FieldBuilder): {
id: import("../db/index.js").UlidField;
userId: import("../db/index.js").StringField;
provider: import("../db/index.js").StringField;
providerUserId: import("../db/index.js").StringField;
label: import("../db/index.js").StringField;
email: import("../db/index.js").EmailField;
emailVerifiedAt: import("../db/index.js").TimestampField;
name: import("../db/index.js").StringField;
avatarUrl: import("../db/index.js").StringField;
password: PasswordField;
profile: import("../db/index.js").JsonStringField<Record<string, unknown>>;
lastLoginAt: import("../db/index.js").TimestampField;
createdAt: import("../db/index.js").TimestampField;
updatedAt: import("../db/index.js").TimestampField;
};
/**
* Applies normalized provider metadata to this row.
*
* @param profile - Provider profile returned by a driver.
*/
applyProfile(profile: auth.AuthProviderProfile): void;
/**
* Marks this provider as used for authentication.
*
* @param date - Login time to store.
*/
markUsed(date?: Date): void;
/**
* Returns true when this provider stores a local password credential.
*
* @returns Whether this row is the built-in password provider.
*/
isPasswordProvider(): boolean;
/**
* Returns settings-safe provider metadata.
*
* Password hashes, provider-owned identifiers, and raw profile metadata are
* deliberately excluded from this projection.
*
* @returns Provider summary for account-management APIs.
*/
toSummary(): AuthProviderSummary;
/**
* Verifies a plaintext password against the provider password hash.
*
* @param plainText - Password supplied by the user.
* @param passwordHash - Password hashing service to use.
* @returns True when the password matches this provider.
*/
verifyPassword(plainText: string, passwordHash?: PasswordHash): Promise<boolean>;
id: string | null;
userId: string | null;
provider: string | null;
providerUserId: string | null;
label: string | null;
email: string | null;
emailVerifiedAt: Date | null;
name: string | null;
avatarUrl: string | null;
password: null;
profile: Record<string, unknown> | null;
lastLoginAt: Date | null;
createdAt: Date | null;
updatedAt: Date | null;
}
Token model and safe session
ts
import { ActiveRecord, type FieldBuilder } from '../db/index.js';
export interface CreateAuthTokenOptions {
/** Human-friendly session name displayed to the user. */
name?: string;
/** Absolute token expiry. Null creates a non-expiring token. */
expiresAt?: Date | null;
/** Latest client IP address observed for the session. */
ipAddress?: string | null;
/** Raw user-agent string captured when the session was created. */
userAgent?: string | null;
/** Parsed browser name, such as Chrome or Mobile Safari. */
browser?: string | null;
/** Parsed operating-system name, such as macOS or iOS. */
operatingSystem?: string | null;
/** Parsed device label, such as iPhone or Desktop. */
device?: string | null;
}
/**
* Request metadata refreshed when a bearer token is authenticated.
*/
export interface AuthTokenUsage {
/** Latest client IP address observed for the session. */
ipAddress?: string | null;
}
/**
* Safe session information suitable for account-management APIs.
*/
export interface AuthSessionData {
id: string;
name: string | null;
ipAddress: string | null;
browser: string | null;
operatingSystem: string | null;
device: string | null;
expiresAt: string | null;
lastUsedAt: string | null;
createdAt: string | null;
}
/**
* Persisted bearer token for API/mobile clients.
*
* The raw token is only returned to the client once. The database stores a
* SHA-256 hash so a token table leak does not expose immediately usable bearer
* tokens.
*/
export declare class AuthToken extends ActiveRecord {
static table: string;
static primaryKey: string;
static fields(field: FieldBuilder): {
id: import("../db/index.js").UlidField;
userId: import("../db/index.js").StringField;
tokenHash: import("../db/index.js").StringField;
name: import("../db/index.js").StringField;
ipAddress: import("../db/index.js").StringField;
userAgent: import("../db/index.js").TextField;
browser: import("../db/index.js").StringField;
operatingSystem: import("../db/index.js").StringField;
device: import("../db/index.js").StringField;
expiresAt: import("../db/index.js").TimestampField;
lastUsedAt: import("../db/index.js").TimestampField;
revokedAt: import("../db/index.js").TimestampField;
createdAt: import("../db/index.js").TimestampField;
};
id: string | null;
userId: string | null;
tokenHash: string | null;
name: string | null;
ipAddress: string | null;
userAgent: string | null;
browser: string | null;
operatingSystem: string | null;
device: string | null;
expiresAt: Date | null;
lastUsedAt: Date | null;
revokedAt: Date | null;
createdAt: Date | null;
/**
* Generates a cryptographically random bearer token.
*
* @returns Plaintext bearer token shown to the client once.
*/
static generatePlainTextToken(): string;
/**
* Hashes a plaintext bearer token for persistent lookup.
*
* @param token - Plaintext bearer token.
* @returns SHA-256 token hash.
*/
static hashToken(token: string): string;
/**
* Returns whether the token has passed its expiry time.
*
* @param date - Comparison time.
* @returns True when the session is expired.
*/
isExpired(date?: Date): boolean;
/**
* Returns whether the session can currently authenticate.
*
* @param date - Comparison time.
* @returns True when the token is neither revoked nor expired.
*/
isActive(date?: Date): boolean;
/**
* Records token activity and optional request metadata.
*
* @param date - Activity time.
* @param usage - Request metadata observed during authentication.
*/
markUsed(date?: Date, usage?: AuthTokenUsage): void;
/**
* Permanently revokes this session.
*
* @param date - Revocation time.
*/
revoke(date?: Date): void;
/**
* Returns safe session information without the token hash or raw user agent.
*
* @returns Session data for account-management APIs.
*/
toSessionData(): AuthSessionData;
}
Reset tokens
ts
import { ActiveRecord, type FieldBuilder } from '../db/index.js';
/**
* Single-use password reset token.
*
* The raw token is only sent in email. The database stores a SHA-256 hash so
* reset-token table leaks do not expose usable reset links.
*/
export declare class PasswordResetToken extends ActiveRecord {
static table: string;
static primaryKey: string;
static fields(field: FieldBuilder): {
id: import("../db/index.js").UlidField;
userId: import("../db/index.js").StringField;
email: import("../db/index.js").EmailField;
tokenHash: import("../db/index.js").StringField;
expiresAt: import("../db/index.js").TimestampField;
usedAt: import("../db/index.js").TimestampField;
createdAt: import("../db/index.js").TimestampField;
};
id: string | null;
userId: string | null;
email: string | null;
tokenHash: string | null;
expiresAt: Date | null;
usedAt: Date | null;
createdAt: Date | null;
static generatePlainTextToken(): string;
static hashToken(token: string): string;
isExpired(date?: Date): boolean;
isUsed(): boolean;
isUsable(date?: Date): boolean;
markUsed(date?: Date): void;
}
Provider verification contract
ts
import type { UserIdentity } from '../UserIdentity.js';
/**
* Normalized identity details returned by an authentication provider.
*
* Provider drivers translate their own proof mechanism into this shape. The
* auth service owns persistence and session issuance after the driver proves
* that the caller controls the provider account.
*/
export interface AuthProviderProfile {
/**
* Stable provider name, such as `password`, `google`, or `magic_link`.
*/
provider: string;
/**
* Stable provider-owned account id.
*
* For OAuth/OIDC providers this should be the provider subject/id, not an
* email address. The built-in password and magic-link providers use the
* normalized email address because the email inbox/account is the proof.
*/
providerUserId: string;
/**
* Email address reported or proven by the provider.
*/
email?: string | null;
/**
* When the provider proved the email address belongs to the user.
*/
emailVerifiedAt?: Date | null;
/**
* Human-friendly provider account name.
*/
name?: string | null;
/**
* Provider account avatar URL for account settings displays.
*/
avatarUrl?: string | null;
/**
* Optional UI label for the linked provider row.
*/
label?: string | null;
/**
* Safe provider metadata that callers may need to inspect later.
*/
profile?: Record<string, unknown> | null;
}
/**
* Pluggable authentication provider driver.
*
* Drivers perform provider-specific verification. They should not create users
* or sessions; provider-owned helpers may update provider rows when the auth
* service explicitly calls them for flows such as password setup.
*/
export interface AuthProviderDriver<TInput = unknown, TIdentity extends UserIdentity = UserIdentity> {
/**
* Stable provider name used in `auth_providers.provider`.
*/
provider: string;
/**
* Verifies provider-specific input and returns a normalized profile.
*
* @param input - Provider-specific credential payload.
* @returns Normalized provider profile, or null when verification fails.
*/
verify(input: TInput): Promise<AuthProviderProfile | null>;
}
/**
* Object-style provider config read from the app config repository.
*/
export interface AuthProviderOptions {
/**
* Built-in or custom driver name. Defaults to the provider key.
*/
driver?: string;
/**
* Whether this provider should be registered. Defaults to true.
*/
enabled?: boolean;
/**
* Provider-specific configuration values.
*/
[option: string]: unknown;
}
/**
* Provider configuration accepted by the auth service.
*
* `true` enables a built-in provider such as `password`; driver instances
* enable external or custom first-party providers.
*/
export type AuthProviderConfig<TIdentity extends UserIdentity = UserIdentity> = true | false | AuthProviderOptions | AuthProviderDriver<unknown, TIdentity>;
/**
* Map of provider names enabled for an app.
*/
export type AuthProviderRegistry<TIdentity extends UserIdentity = UserIdentity> = Record<string, AuthProviderConfig<TIdentity>>;
Password hashing helpers
ts
export interface PasswordHash {
hash(plainText: string): Promise<string>;
verify(plainText: string, hash: string): Promise<boolean>;
}
export interface ScryptPasswordHashOptions {
cost?: number;
blockSize?: number;
parallelization?: number;
keyLength?: number;
saltLength?: number;
maxmem?: number;
}
export declare class ScryptPasswordHash implements PasswordHash {
private readonly cost;
private readonly blockSize;
private readonly parallelization;
private readonly keyLength;
private readonly saltLength;
private readonly maxmem?;
constructor(options?: ScryptPasswordHashOptions);
hash(plainText: string): Promise<string>;
verify(plainText: string, hash: string): Promise<boolean>;
private derive;
private parse;
}
export declare const defaultPasswordHash: ScryptPasswordHash;
Google provider
ts
import type { webcrypto } from 'node:crypto';
import type * as auth from '../contracts/index.js';
import type { UserIdentity } from '../UserIdentity.js';
export declare const GOOGLE_AUTH_PROVIDER = "google";
export type GoogleJsonWebKey = webcrypto.JsonWebKey & {
kid?: string;
};
type Fetch = typeof fetch;
/**
* Input accepted by the Google auth provider.
*/
export interface GoogleAuthProviderInput {
/**
* Google Identity Services credential field containing the ID token.
*/
credential?: string;
/**
* Alternative explicit ID-token field for non-GIS clients.
*/
idToken?: string;
/**
* CSRF token submitted in the request body by Google Identity Services.
*/
g_csrf_token?: string;
/**
* Alternative explicit CSRF token field.
*/
csrfToken?: string;
/**
* CSRF token read from the request cookie by the route.
*/
csrfCookie?: string;
}
/**
* Runtime options for Google ID-token verification.
*/
export interface GoogleAuthProviderOptions {
/**
* Single Google OAuth web client id.
*/
clientId?: string;
/**
* Accepted Google OAuth web client ids.
*/
clientIds?: string[];
/**
* Optional Google Workspace hosted domain restriction.
*/
hostedDomain?: string;
/**
* JWK endpoint used to fetch Google signing keys.
*/
jwksUrl?: string;
/**
* Fetch implementation, injectable for tests.
*/
fetch?: Fetch;
/**
* Static signing keys, injectable for deterministic tests.
*/
jwks?: GoogleJsonWebKey[];
/**
* Clock skew allowance in seconds.
*/
clockSkewSeconds?: number;
/**
* Time source used for expiry checks.
*/
now?: () => Date | number;
}
/**
* Provider driver for Google Sign-In ID tokens.
*
* This provider verifies a Google-signed ID token and translates the verified
* claims into the framework's normalized provider profile. It intentionally
* does not store OAuth access or refresh tokens.
*/
export declare class GoogleAuthProvider<TIdentity extends UserIdentity = UserIdentity> implements auth.AuthProviderDriver<GoogleAuthProviderInput, TIdentity> {
readonly provider = "google";
private readonly clientIds;
private readonly hostedDomain;
private readonly jwksUrl;
private readonly fetcher;
private readonly staticJwks;
private readonly clockSkewSeconds;
private readonly now;
private jwksCache;
/**
* Creates a Google auth provider.
*
* @param options - Google provider verification options.
*/
constructor(options?: GoogleAuthProviderOptions);
/**
* Verifies a Google ID token and returns the normalized provider profile.
*
* @param input - Google credential payload.
* @returns Normalized Google provider profile, or null when verification fails.
*/
verify(input: GoogleAuthProviderInput): Promise<auth.AuthProviderProfile | null>;
/**
* Checks whether supplied CSRF values match when either value is present.
*
* @param input - Google credential payload.
* @returns True when CSRF values are absent or exactly match.
*/
private csrfTokensMatch;
/**
* Verifies a compact JWT from Google.
*
* @param idToken - Compact Google ID token.
* @returns Verified header and payload, or null when invalid.
*/
private verifyIdToken;
/**
* Validates the required Google ID-token claims.
*
* @param payload - Decoded JWT payload.
* @returns True when required claims are acceptable.
*/
private claimsAreValid;
/**
* Returns Google JWKs, using cache-control when keys are fetched remotely.
*
* @returns Google signing keys.
*/
private jwks;
/**
* Returns the current time in milliseconds.
*
* @returns Current epoch milliseconds.
*/
private nowMs;
}
export {};
Password provider
ts
import { AuthProvider } from '../AuthProvider.js';
import type * as auth from '../contracts/index.js';
import type { PasswordCredentials } from '../Auth.js';
import type { UserIdentity, UserIdentityModel } from '../UserIdentity.js';
import { type PasswordHash } from '../passwordHash.js';
/**
* Construction options for the password auth provider.
*/
export interface PasswordAuthProviderOptions<TIdentity extends UserIdentity = UserIdentity> {
/**
* User identity model configured for the host app.
*/
identityModel: UserIdentityModel<TIdentity>;
/**
* Provider-link model configured for the auth service.
*/
providerModel?: typeof AuthProvider;
/**
* Password hashing service used to verify stored hashes.
*/
passwordHash?: PasswordHash;
}
/**
* Provider driver for first-party email and password authentication.
*
* The password provider is not OAuth, but it still satisfies the same provider
* contract by proving control of a provider-owned identity: the account email
* plus a valid password hash stored on `auth_providers`.
*/
export declare class PasswordAuthProvider<TIdentity extends UserIdentity = UserIdentity> implements auth.AuthProviderDriver<PasswordCredentials, TIdentity> {
readonly provider = "password";
private readonly IdentityModel;
private readonly ProviderModel;
private readonly passwordHash;
/**
* Creates a password auth provider.
*
* @param options - Password provider dependencies configured at app startup.
*/
constructor(options: PasswordAuthProviderOptions<TIdentity>);
/**
* Verifies submitted password credentials against the stored provider row.
*
* @param input - Submitted password credential payload.
* @returns Normalized password provider profile, or null when verification fails.
*/
verify(input: PasswordCredentials): Promise<auth.AuthProviderProfile | null>;
/**
* Creates or replaces the password provider for a user.
*
* @param user - User who owns the password provider.
* @param password - Plaintext password to hash and store.
* @returns Saved password provider row.
*/
setPassword(user: TIdentity, password: string): Promise<AuthProvider>;
/**
* Changes a user's password after verifying the current password.
*
* @param user - User whose password should change.
* @param currentPassword - Current plaintext password.
* @param nextPassword - Replacement plaintext password.
* @returns True when the password provider was changed.
*/
changePassword(user: TIdentity, currentPassword: string, nextPassword: string): Promise<boolean>;
/**
* Links the password provider to an existing user.
*
* @param user - User receiving the password provider.
* @param input - Submitted password credential payload.
* @returns Saved provider row, or null when no password was supplied.
*/
link(user: TIdentity, input: unknown): Promise<AuthProvider | null>;
/**
* Finds a password provider by normalized email identity.
*
* @param identity - Normalized email identity.
* @returns Matching password provider row, or null.
*/
private findProvider;
/**
* Finds the password provider linked to a user.
*
* @param userId - User primary key.
* @returns Matching password provider row, or null.
*/
private findUserProvider;
/**
* Reads a user primary key as a non-empty string.
*
* @param user - User model to inspect.
* @returns Primary key string, or null when missing.
*/
private userPrimaryKey;
/**
* Reads the configured identity value from a user.
*
* @param user - User model to inspect.
* @returns Normalized identity value, or null when missing.
*/
private userIdentityValue;
}
/**
* Checks whether a value can be used as password credentials.
*
* @param value - Unknown credential payload.
* @returns True when a password string is present.
*/
export declare function isPasswordCredentials(value: unknown): value is PasswordCredentials;
/**
* Normalizes an auth identity value for provider matching.
*
* @param value - Unknown identity value.
* @returns Lowercase trimmed identity string, or null.
*/
export declare function normalizeIdentity(value: unknown): string | null;