Synq Docs
SDK reference

@synqauth/nextjs

Synq for Next.js: a backend-for-frontend session, so the browser never holds a Synq token.

@synqauth/nextjs

createSynqCore

Function. The framework-neutral core synqAuth() runs on, over any cookie jar: for a server that answers the same routes without Next. Most apps use synqAuth() instead.

function createSynqCore(config: SynqConfig): SynqCore

defineSynqConfig

Function. Declares the app's Synq configuration: SYNQ_* environment variables fill in whatever it leaves out.

function defineSynqConfig<const T extends SynqAuthOptions>(options: T): T

defineSynqPlugin

Function. Declares a server plugin, checking its id and routes once, when the module loads.

function defineSynqPlugin<const T extends SynqPlugin>(plugin: T): T

jarOf

Function. Next's cookie store as the cookie jar createSynqCore reads and writes.

function jarOf(store: Omit<RequestCookies, "set" | "clear" | "delete"> & Pick<ResponseCookies, "set" | "delete">): CookieJar

KeyValue

Interface. The few operations a key-value store (Redis, Valkey, Upstash...) gives keyValueSessionStore.

interface KeyValue {
    get(key: string): Promise<string | null | undefined>;
    set(key: string, value: string, options: {
        ttlMs: number;
        onlyIfAbsent?: boolean;
    }): Promise<boolean>;
    delete(key: string): Promise<void>;
    deleteIfEquals?(key: string, value: string): Promise<void>;
}

keyValueSessionStore

Function. Sessions in a key-value store every server process shares, such as Redis or Valkey: the store an app on several processes (replicas, serverless functions) needs. Its lock is SET … NX PX with a token, polled until free, and released only by its holder; it expires on its own, so a dead process never holds a session for ever.

``ts keyValueSessionStore({ get: (key) => redis.get(key), set: async (key, value, { ttlMs, onlyIfAbsent }) => (await redis.set(key, value, { PX: ttlMs, NX: onlyIfAbsent })) === 'OK', delete: async (key) => void (await redis.del(key)), }) ``

function keyValueSessionStore(kv: KeyValue, options?: KeyValueSessionStoreOptions): SynqSessionStore

KeyValueSessionStoreOptions

Interface. What keyValueSessionStore takes besides the store itself.

interface KeyValueSessionStoreOptions {
    prefix?: string;
    lockTtlMs?: number;
    lockWaitMs?: number;
}

memorySessionStore

Function. A store in this process's memory: for tests and a single server process, where the default cookie does as well.

function memorySessionStore(): SynqSessionStore

resolveConfig

Function. The configuration from options and the environment; throws invalid_options for anything missing or unsafe.

function resolveConfig(options?: SynqAuthOptions, env?: Env): SynqConfig

SessionValues

Type. What a session keeps: tokens per API and the refresh token, as strings.

type SessionValues = Record<string, string>;

SIGN_IN_ERROR_PARAM

Constant. The query parameter the route mount adds to returnTo when a sign-in fails.

const SIGN_IN_ERROR_PARAM: "synq_error"

signInErrorMessage

Function. What a sign-in error code means, in plain words.

function signInErrorMessage(code: string): string

synqAuth

Function. Synq for this app, configured from SYNQ_ISSUER, SYNQ_CLIENT_ID, SYNQ_CLIENT_SECRET, SYNQ_APP_URL and SYNQ_SESSION_SECRET unless options (defineSynqConfig, shared with the proxy) says.

function synqAuth(options?: SynqAuthOptions): SynqAuth

SynqAuth

Interface. What synqAuth() returns: the route mount's handlers and the server's view of the session.

interface SynqAuth {
    readonly handlers: {
        readonly GET: (request: Request) => Promise<Response>;
        readonly POST: (request: Request) => Promise<Response>;
        readonly PATCH: (request: Request) => Promise<Response>;
        readonly DELETE: (request: Request) => Promise<Response>;
    };
    me(): Promise<SynqUser | null>;
    getSession(): Promise<SynqSessionInfo>;
    getAccessToken(options?: {
        resource?: string;
        minValiditySeconds?: number;
    }): Promise<string>;
    signInPath(options?: {
        returnTo?: string;
        method?: string;
        loginHint?: string;
        prompt?: 'login' | 'none' | 'consent' | 'select_account' | 'create';
        maxAge?: number;
    }): string;
    readonly signOutPath: string;
    signInError(searchParams: URLSearchParams | Record<string, string | string[] | undefined>, returnTo?: string): SynqSignInError | null;
}

SynqAuthOptions

Interface. What synqAuth() and defineSynqConfig() take. Every option the environment can give (SYNQ_*) is optional here; an option given wins.

interface SynqAuthOptions {
    issuer?: string;
    clientId?: string;
    clientSecret?: string;
    appUrl?: string;
    sessionSecret?: string;
    previousSessionSecrets?: readonly string[];
    basePath?: string;
    resource?: string;
    account?: boolean;
    scope?: string;
    postLogoutRedirectUri?: string;
    store?: SynqSessionStore;
    allowSingleProcessCookieMode?: boolean;
    sessionMaxAge?: number;
    refreshLeewaySeconds?: number;
    plugins?: readonly SynqPlugin[];
    fetch?: typeof fetch;
    clientAddress?: (request: Request) => string | undefined;
}

SynqPlugin

Interface. A server plugin: routes under the route mount, at <basePath>/<id>/…. Declare one with defineSynqPlugin.

interface SynqPlugin {
    readonly id: string;
    readonly routes?: Readonly<Record<string, SynqPluginRoute>>;
}

SynqPluginContext

Interface. What a plugin's route is handed.

interface SynqPluginContext {
    user(): Promise<SynqUser | null>;
    getAccessToken(options?: {
        resource?: string;
    }): Promise<string>;
    readonly issuer: string;
    readonly clientId: string;
    readonly basePath: string;
}

SynqPluginRoute

Type. A route: GET /status, POST /verify... relative to the plugin's own path.

type SynqPluginRoute = (context: SynqPluginContext, request: Request) => Response | Promise<Response>;

SynqSessionInfo

Interface. Who is signed in, as the browser may see it: never a token.

interface SynqSessionInfo {
    readonly user: SynqUser | null;
    readonly expiresAt: number | null;
}

SynqSessionStore

Interface. Where sessions live server-side when the cookie holds only the session's id (synqAuth({ store })): needed where several processes serve the app. keyValueSessionStore makes one from any key-value store.

interface SynqSessionStore {
    get(id: string): Promise<SessionValues | null>;
    set(id: string, values: SessionValues, maxAgeSeconds: number): Promise<void>;
    delete(id: string): Promise<void>;
    lock<T>(id: string, fn: () => Promise<T>): Promise<T>;
}

SynqSignInError

Interface. Why the last sign-in didn't finish, and the ways on.

interface SynqSignInError {
    readonly code: string;
    readonly message: string;
    readonly retryPath: string;
    readonly anotherAccountPath: string;
}

SynqUser

Interface. A signed-in person, from the ID token Synq issued at sign-in.

interface SynqUser {
    readonly sub: string;
    readonly email?: string;
    readonly email_verified?: boolean;
    readonly name?: string;
    readonly preferred_username?: string;
    readonly picture?: string;
    readonly auth_time?: number;
    readonly amr?: readonly string[];
    readonly linked_accounts?: readonly LinkedAccount[];
    readonly [claim: string]: unknown;
}

@synqauth/nextjs/proxy

SignUpChoice

Interface. What a visitor picked: a plan's code and its interval, and the onboarding visit.

interface SignUpChoice {
    readonly plan?: string;
    readonly interval?: 'month' | 'year';
    readonly onboarding?: string;
}

synqProxy

Function. Next's proxy for Synq: refreshes a session that is due, and sends a request to a protected path without one to sign in, or, when a sign-in just failed, to the page that says why.

function synqProxy(config: SynqAuthOptions, options: SynqProxyOptions): (request: Request) => Promise<Response | undefined>

SynqProxyOptions

Interface. What synqProxy() takes: which paths need a session.

interface SynqProxyOptions {
    readonly protect: readonly string[] | ((pathname: string) => boolean);
    readonly signInError?: string;
    readonly signUp?: readonly string[] | ((pathname: string) => boolean);
    readonly choice?: (url: URL) => SignUpChoice | undefined;
}

@synqauth/nextjs/client

defineSynqClientPlugin

Function. Declares a browser plugin, its id the same as its server plugin's.

function defineSynqClientPlugin<const Id extends string, Actions>(plugin: SynqClientPlugin<Id, Actions>): SynqClientPlugin<Id, Actions>

mountRequest

Function. A request to basePath's routes from the app's own page: same origin, with the cookie, never cached.

function mountRequest(basePath?: string, fetcher?: { (input: URL | RequestInfo, init?: RequestInit | undefined): Promise<Response>; (input: string | URL | Request, init?: RequestInit | undefined): Promise<Response>; }): SynqMountRequest

SynqClientPlugin

Interface. A browser plugin: actions over its server plugin's routes (defineSynqPlugin), which

interface SynqClientPlugin<Id extends string = string, Actions = unknown> {
    readonly id: Id;
    actions(request: SynqMountRequest): Actions;
}

SynqMountRequest

Type. Calls the app's route mount: request('session'), request('account/v1/profile', { method: 'PATCH',... }).

type SynqMountRequest = (path: string, init?: RequestInit) => Promise<Response>;

@synqauth/nextjs/config

defineSynqConfig

Function. Declares the app's Synq configuration: SYNQ_* environment variables fill in whatever it leaves out.

function defineSynqConfig<const T extends SynqAuthOptions>(options: T): T

SynqAuthOptions

Interface. What synqAuth() and defineSynqConfig() take. Every option the environment can give (SYNQ_*) is optional here; an option given wins.

interface SynqAuthOptions {
    issuer?: string;
    clientId?: string;
    clientSecret?: string;
    appUrl?: string;
    sessionSecret?: string;
    previousSessionSecrets?: readonly string[];
    basePath?: string;
    resource?: string;
    account?: boolean;
    scope?: string;
    postLogoutRedirectUri?: string;
    store?: SynqSessionStore;
    allowSingleProcessCookieMode?: boolean;
    sessionMaxAge?: number;
    refreshLeewaySeconds?: number;
    plugins?: readonly SynqPlugin[];
    fetch?: typeof fetch;
    clientAddress?: (request: Request) => string | undefined;
}

See every package.

On this page