bknd
Version:
Lightweight Firebase/Supabase alternative built to run anywhere — incl. Next.js, React Router, Astro, Cloudflare, Bun, Node, AWS Lambda & more.
239 lines (238 loc) • 11.2 kB
TypeScript
import type { DB } from "../..";
import type { Context } from "hono";
import { sign } from "hono/jwt";
import type { ServerEnv } from "../../modules/Controller";
import { s } from "bknd/utils";
import type { AuthStrategy } from "./strategies/Strategy";
export type JWTPayload = Parameters<typeof sign>[0];
export declare const strategyActions: readonly ["create", "change"];
export type StrategyActionName = (typeof strategyActions)[number];
export type StrategyAction<S extends s.ObjectSchema = s.ObjectSchema> = {
schema: S;
preprocess: (input: s.Static<S>) => Promise<Omit<DB["users"], "id" | "strategy">>;
};
export type StrategyActions = Partial<Record<StrategyActionName, StrategyAction>>;
export type User = DB["users"];
export type ProfileExchange = {
email?: string;
strategy?: string;
strategy_value?: string;
[key: string]: any;
};
export type SafeUser = Omit<User, "strategy_value">;
export type CreateUser = Pick<User, "email"> & {
[key: string]: any;
};
export type AuthResponse = {
user: SafeUser;
token: string;
};
export interface UserPool {
findBy: (strategy: string, prop: keyof SafeUser, value: string | number) => Promise<User>;
create: (strategy: string, user: CreateUser) => Promise<User>;
}
export declare const cookieConfig: s.ObjectSchema<{
readonly domain: s.Schema<s.ISchemaOptions, string | undefined, string | undefined>;
readonly path: s.Schema<s.ISchemaOptions, string | undefined, string | undefined>;
readonly sameSite: s.Schema<s.ISchemaOptions, "strict" | "lax" | "none" | undefined, "strict" | "lax" | "none" | undefined>;
readonly secure: s.Schema<s.ISchemaOptions, boolean | undefined, boolean | undefined>;
readonly httpOnly: s.Schema<s.ISchemaOptions, boolean | undefined, boolean | undefined>;
readonly expires: s.Schema<s.ISchemaOptions, number | undefined, number | undefined>;
readonly partitioned: s.Schema<s.ISchemaOptions, boolean | undefined, boolean | undefined>;
readonly renew: s.Schema<s.ISchemaOptions, boolean | undefined, boolean | undefined>;
readonly pathSuccess: s.Schema<s.ISchemaOptions, string | undefined, string | undefined>;
readonly pathLoggedOut: s.Schema<s.ISchemaOptions, string | undefined, string | undefined>;
}, s.Merge<s.IObjectOptions & {
additionalProperties: false;
}>>;
export declare const jwtConfig: s.ObjectSchema<{
readonly secret: import("bknd/utils").SecretSchema<{
default: string;
}> & {
default: string;
};
readonly alg: {
readonly default: "HS256";
readonly enum: ["HS256", "HS384", "HS512"];
} & s.Schema<s.ISchemaOptions, "HS256" | "HS384" | "HS512" | undefined, "HS256" | "HS384" | "HS512" | undefined>;
readonly expires: {
default?: any;
enum?: (readonly any[] | any[]) | undefined;
const?: any;
multipleOf?: number | undefined;
maximum?: number | undefined;
exclusiveMaximum?: number | undefined;
minimum?: number | undefined;
exclusiveMinimum?: number | undefined;
} & s.Schema<s.ISchemaOptions, number | undefined, number | undefined>;
readonly issuer: {
default?: any;
maxLength?: number | undefined;
minLength?: number | undefined;
pattern?: (string | RegExp) | undefined;
format?: string | undefined;
enum?: (readonly any[] | any[]) | undefined;
const?: any;
} & s.Schema<s.ISchemaOptions, string | undefined, string | undefined>;
readonly fields: s.ArraySchema<s.StringSchema<s.IStringOptions> & s.IStringOptions, {
readonly default: readonly ["id", "email", "role"];
}> & {
readonly default: readonly ["id", "email", "role"];
};
}, s.Merge<{
readonly default: {};
} & {
additionalProperties: false;
}>>;
export declare const authenticatorConfig: s.ObjectSchema<{
readonly jwt: s.ObjectSchema<{
readonly secret: import("bknd/utils").SecretSchema<{
default: string;
}> & {
default: string;
};
readonly alg: {
readonly default: "HS256";
readonly enum: ["HS256", "HS384", "HS512"];
} & s.Schema<s.ISchemaOptions, "HS256" | "HS384" | "HS512" | undefined, "HS256" | "HS384" | "HS512" | undefined>;
readonly expires: {
default?: any;
enum?: (readonly any[] | any[]) | undefined;
const?: any;
multipleOf?: number | undefined;
maximum?: number | undefined;
exclusiveMaximum?: number | undefined;
minimum?: number | undefined;
exclusiveMinimum?: number | undefined;
} & s.Schema<s.ISchemaOptions, number | undefined, number | undefined>;
readonly issuer: {
default?: any;
maxLength?: number | undefined;
minLength?: number | undefined;
pattern?: (string | RegExp) | undefined;
format?: string | undefined;
enum?: (readonly any[] | any[]) | undefined;
const?: any;
} & s.Schema<s.ISchemaOptions, string | undefined, string | undefined>;
readonly fields: s.ArraySchema<s.StringSchema<s.IStringOptions> & s.IStringOptions, {
readonly default: readonly ["id", "email", "role"];
}> & {
readonly default: readonly ["id", "email", "role"];
};
}, s.Merge<{
readonly default: {};
} & {
additionalProperties: false;
}>>;
readonly cookie: s.ObjectSchema<{
readonly domain: s.Schema<s.ISchemaOptions, string | undefined, string | undefined>;
readonly path: s.Schema<s.ISchemaOptions, string | undefined, string | undefined>;
readonly sameSite: s.Schema<s.ISchemaOptions, "strict" | "lax" | "none" | undefined, "strict" | "lax" | "none" | undefined>;
readonly secure: s.Schema<s.ISchemaOptions, boolean | undefined, boolean | undefined>;
readonly httpOnly: s.Schema<s.ISchemaOptions, boolean | undefined, boolean | undefined>;
readonly expires: s.Schema<s.ISchemaOptions, number | undefined, number | undefined>;
readonly partitioned: s.Schema<s.ISchemaOptions, boolean | undefined, boolean | undefined>;
readonly renew: s.Schema<s.ISchemaOptions, boolean | undefined, boolean | undefined>;
readonly pathSuccess: s.Schema<s.ISchemaOptions, string | undefined, string | undefined>;
readonly pathLoggedOut: s.Schema<s.ISchemaOptions, string | undefined, string | undefined>;
}, s.Merge<s.IObjectOptions & {
additionalProperties: false;
}>>;
readonly default_role_register: {
default?: any;
maxLength?: number | undefined;
minLength?: number | undefined;
pattern?: (string | RegExp) | undefined;
format?: string | undefined;
enum?: (readonly any[] | any[]) | undefined;
const?: any;
} & s.Schema<s.ISchemaOptions, string | undefined, string | undefined>;
}, s.IObjectOptions> & s.IObjectOptions;
type AuthConfig = s.Static<typeof authenticatorConfig>;
export type AuthAction = "login" | "register";
export type AuthResolveOptions = {
identifier?: "email" | string;
redirect?: string;
forceJsonResponse?: boolean;
};
export type AuthUserResolver = (action: AuthAction, strategy: AuthStrategy, profile: ProfileExchange, opts?: AuthResolveOptions) => Promise<ProfileExchange | undefined>;
type AuthClaims = SafeUser & {
iat: number;
iss?: string;
exp?: number;
};
export declare class Authenticator<Strategies extends Record<string, AuthStrategy> = Record<string, AuthStrategy>> {
private readonly strategies;
private readonly userPool;
private readonly config;
constructor(strategies: Strategies, userPool: UserPool, config?: AuthConfig);
resolveLogin(c: Context, strategy: AuthStrategy, profile: Partial<SafeUser>, verify: (user: User) => Promise<void>, opts?: AuthResolveOptions): Promise<(Response & import("hono").TypedResponse<{
user: {
id: string | number | {
readonly __select__: string | number;
readonly __insert__: string | number | undefined;
readonly __update__: string | number;
};
email: string;
role?: string | undefined;
strategy: string;
};
token: string;
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<undefined, 302, "redirect">)>;
resolveRegister(c: Context, strategy: AuthStrategy, profile: CreateUser, verify: (user: User) => Promise<void>, opts?: AuthResolveOptions): Promise<(Response & import("hono").TypedResponse<{
user: {
id: string | number | {
readonly __select__: string | number;
readonly __insert__: string | number | undefined;
readonly __update__: string | number;
};
email: string;
role?: string | undefined;
strategy: string;
};
token: string;
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<undefined, 302, "redirect">)>;
private respondWithUser;
respondWithError(c: Context, error: Error, opts?: AuthResolveOptions): Promise<Response & import("hono").TypedResponse<undefined, 302, "redirect">>;
getStrategies(): Strategies;
strategy<StrategyName extends keyof Strategies, Strat extends AuthStrategy = Strategies[StrategyName]>(strategy: StrategyName): Strat;
jwt(_user: SafeUser | ProfileExchange): Promise<string>;
safeAuthResponse(_user: User): Promise<AuthResponse>;
verify(jwt: string): Promise<AuthClaims | undefined>;
private get cookieOptions();
private getAuthCookie;
requestCookieRefresh(c: Context<ServerEnv>): Promise<void>;
private setAuthCookie;
getAuthCookieHeader(token: string, headers?: Headers): Promise<Headers>;
removeAuthCookieHeader(headers?: Headers): Promise<Headers>;
unsafeGetAuthCookie(token: string): Promise<string | undefined>;
private deleteAuthCookie;
logout(c: Context<ServerEnv>): Promise<void>;
isJsonRequest(c: Context): boolean;
getBody(c: Context): Promise<any>;
private getSafeUrl;
resolveAuthFromRequest(c: Context | Request | Headers): Promise<SafeUser | undefined>;
toJSON(secrets?: boolean): {
jwt: {
alg?: "HS256" | "HS384" | "HS512" | undefined;
expires?: number | undefined;
issuer?: string | undefined;
secret: string;
fields: string[];
} | undefined;
default_role_register?: string | undefined;
cookie: {
path?: string | undefined;
expires?: number | undefined;
domain?: string | undefined;
sameSite?: "strict" | "lax" | "none" | undefined;
secure?: boolean | undefined;
httpOnly?: boolean | undefined;
partitioned?: boolean | undefined;
renew?: boolean | undefined;
pathSuccess?: string | undefined;
pathLoggedOut?: string | undefined;
};
};
}
export {};