Synq Docs
SDK reference

@synqauth/js

Synq's framework-agnostic client: sign-in and sessions in the browser, the account API, and token and webhook verification on your server.

@synqauth/js

AccountApiKey

Type. One of the person's API keys for the brand's APIs: never the key itself.

type AccountApiKey = Schemas['UserApiKey'];

AccountApiKeyCreate

Type. What apiKeys.create() takes: the API's identifier, a name, its scopes, and an expiry if any.

type AccountApiKeyCreate = Schemas['UserApiKeyCreate'];

accountApiUrl

Function. The account API's URL for a brand: the resource its access tokens are for.

function accountApiUrl(issuer: string | URL): string

AccountClient

Interface. The brand's account API for the signed-in person, as createAccountClient makes it: every call answers { data, error }.

interface AccountClient {
    me: (options?: ReadOptions) => Promise<AccountResult<AccountProfile>>;
    user: {
        update: (changes: AccountProfileUpdate, options?: ChangeOptions) => Promise<AccountResult<AccountProfile>>;
        metadata: (options?: ReadOptions) => Promise<AccountResult<Record<string, unknown>>>;
        usernameAvailable: (username: string, options?: ReadOptions) => Promise<AccountResult<AccountUsernameAvailability>>;
    };
    wallets: {
        list: (options?: ReadOptions) => Promise<AccountResult<readonly AccountWallet[]>>;
        update: (wallet: string, changes: AccountWalletUpdate, options?: ChangeOptions) => Promise<AccountResult<AccountWallet>>;
        remove: (wallet: string, options?: ChangeOptions) => Promise<AccountResult<null>>;
    };
    accounts: {
        list: (options?: ReadOptions) => Promise<AccountResult<readonly AccountIdentity[]>>;
        link: (method: LinkMethod, options?: ChangeOptions) => Promise<AccountResult<AccountLinkRequest>>;
        unlink: (identity: string, options?: ChangeOptions) => Promise<AccountResult<null>>;
    };
    sessions: {
        list: (options?: ReadOptions) => Promise<AccountResult<readonly AccountSession[]>>;
        revoke: (session: string, options?: ChangeOptions) => Promise<AccountResult<null>>;
    };
    passkeys: {
        list: (options?: ReadOptions) => Promise<AccountResult<readonly AccountPasskey[]>>;
        registrationOptions: (options?: ChangeOptions) => Promise<AccountResult<Record<string, unknown>>>;
        register: (credential: Record<string, unknown>, options?: ChangeOptions) => Promise<AccountResult<AccountPasskey>>;
        remove: (passkey: string, options?: ChangeOptions) => Promise<AccountResult<null>>;
    };
    consents: {
        list: (options?: ReadOptions) => Promise<AccountResult<readonly AccountConsent[]>>;
        withdraw: (consent: string, options?: ChangeOptions) => Promise<AccountResult<null>>;
    };
    apiKeys: {
        apis: (options?: ReadOptions) => Promise<AccountResult<readonly AccountKeyableApi[]>>;
        list: (options?: ReadOptions) => Promise<AccountResult<readonly AccountApiKey[]>>;
        create: (input: AccountApiKeyCreate, options?: ChangeOptions) => Promise<AccountResult<AccountNewApiKey>>;
        revoke: (key: string, options?: ChangeOptions) => Promise<AccountResult<null>>;
    };
    activity: (options?: ReadOptions) => Promise<AccountResult<readonly AccountSignIn[]>>;
    deletion: {
        schedule: (options?: ChangeOptions) => Promise<AccountResult<unknown>>;
        cancel: (options?: ChangeOptions) => Promise<AccountResult<unknown>>;
    };
}

AccountClientOptions

Interface. What createAccountClient takes.

interface AccountClientOptions {
    issuer: string | URL;
    accessToken: () => string | Promise<string>;
    fetch?: typeof fetch;
}

AccountComponents

Interface. The account API's schemas, generated from its OpenAPI document.

type AccountComponents // generated from the API's OpenAPI document: see the API reference

AccountConsent

Type. What the person allowed an app outside the brand's own to do.

type AccountConsent = Schemas['Consent'];

AccountIdentity

Type. One of the person's ways to sign in: a wallet, an email address or a provider's account.

type AccountIdentity = Schemas['Identity'];

AccountKeyableApi

Type. An API the person may make keys for, with the scopes it defines.

type AccountKeyableApi = Schemas['KeyableApi'];

AccountLinkRequest

Type. A link request: the sign-in that adds a way in carries its authorization_params.

type AccountLinkRequest = Schemas['LinkRequest'];

AccountNewApiKey

Type. A new API key: key is the key itself, in this answer only.

type AccountNewApiKey = Schemas['NewUserApiKey'];

AccountOperations

Type. The account API's operations, generated from its OpenAPI document.

type AccountOperations // generated from the API's OpenAPI document: see the API reference

AccountPasskey

Type. One of the person's passkeys.

type AccountPasskey = Schemas['Passkey'];

AccountPaths

Interface. The account API's paths, generated from its OpenAPI document.

type AccountPaths // generated from the API's OpenAPI document: see the API reference

AccountProfile

Type. The signed-in person's profile, as the account API answers it.

type AccountProfile = Schemas['Profile'];

AccountProfileUpdate

Type. What user.update() may change: only the fields given.

type AccountProfileUpdate = Schemas['ProfileUpdate'];

AccountResult

Type. A call's outcome: its data, or the SynqError it failed with (branch on error.code).

type AccountResult<T> = {
    readonly data: T;
    readonly error: null;
} | {
    readonly data: null;
    readonly error: SynqError;
};

AccountSession

Type. One of the person's sessions at the brand; current marks the one the call came from.

type AccountSession = Schemas['Session'];

AccountSignIn

Type. One recent sign-in: when, how and to which app.

type AccountSignIn = Schemas['SignIn'];

AccountUsernameAvailability

Type. Whether a username is free for the person to take, and why not.

type AccountUsernameAvailability = Schemas['UsernameAvailability'];

AccountWallet

Type. One of the person's wallets.

type AccountWallet = Schemas['Wallet'];

AccountWalletUpdate

Type. What wallets.update() may change: the label, or making it primary.

type AccountWalletUpdate = Schemas['WalletUpdate'];

AuthorizationUrlOptions

Interface. What to ask for when sending someone to sign in.

interface AuthorizationUrlOptions {
    method?: string;
    loginHint?: string;
    prompt?: 'none' | 'login' | 'consent' | 'select_account' | 'create';
    maxAge?: number;
    scope?: string;
    resource?: string;
    additionalResources?: readonly string[];
    params?: Readonly<Record<string, string>>;
    pushed?: boolean;
    acr?: {
        readonly values: readonly string[];
        readonly essential?: boolean;
    };
}

browserLocalStorage

Function. The browser's localStorage, which every tab of the app's origin shares. Where a sign-in's transaction goes by default in a browser: a magic link or an email's link opens a new tab, which finishes the sign-in and comes back to the app there, so the tab that started it can't be the only one that knows it. Each transaction is kept under its own state, for an hour at most, deleted when it finishes, and swept away when stale. The price: any script on the app's origin can read a transaction meanwhile (its PKCE verifier and nonce, useless without the code Synq sends to the app's own redirect URI), as it can read anything else the app keeps. As the session's store it keeps the access and ID tokens only, never the refresh token.

function browserLocalStorage(): SynqStorage

browserSessionStorage

Function. The tab's sessionStorage: it ends with the tab, and no other tab reads it. As the session's store it keeps the access and ID tokens only, never the refresh token.

function browserSessionStorage(): SynqStorage

CHALLENGE_METHODS

Constant. The ways in an app's own screens sign people in with (synq_method).

type CHALLENGE_METHODS // generated from the API's OpenAPI document: see the API reference

CHALLENGE_PROBLEMS

Constant. What went wrong with a step (synq_problem): branch on it, never on the English.

type CHALLENGE_PROBLEMS // generated from the API's OpenAPI document: see the API reference

ChallengeMethod

Type. One of CHALLENGE_METHODS.

type ChallengeMethod // generated from the API's OpenAPI document: see the API reference

ChallengeProblem

Type. One of CHALLENGE_PROBLEMS.

type ChallengeProblem // generated from the API's OpenAPI document: see the API reference

ChangeOptions

Interface. What every change takes.

interface ChangeOptions {
    idempotencyKey?: string;
    signal?: AbortSignal;
}

createAccountClient

Function. A client for the brand's account API, for an app that holds its own session: everything the signed-in person can do to their own account.

function createAccountClient(options: AccountClientOptions): AccountClient

createSynqClient

Function. A client for one app at one of a brand's Synq issuers.

function createSynqClient(options: SynqClientOptions): SynqClient

DeniedReason

Type. One of DENIED_REASONS.

type DeniedReason // generated from the API's OpenAPI document: see the API reference

ERROR_CODES

Constant. Each code a Synq API's problem documents carry, with its HTTP status.

type ERROR_CODES // generated from the API's OpenAPI document: see the API reference

IdTokenClaims

Interface. The claims of a validated ID token: who signed in, when, and how.

interface IdTokenClaims {
    readonly iss: string;
    readonly sub: string;
    readonly aud: string | string[];
    readonly iat: number;
    readonly exp: number;
    readonly auth_time?: number;
    readonly amr?: string[];
    readonly acr?: string;
    readonly linked_accounts?: readonly LinkedAccount[];
    readonly [claim: string]: unknown;
}

isSynqError

Function. Whether error is a SynqError, with code when given.

function isSynqError(error: unknown, code?: SynqAnyErrorCode | undefined): error is SynqError

LinkedAccount

Interface. One account at an upstream provider the person signs in with, with what the provider said of it at their last sign-in with it. Someone who links GitHub and Google to one account is one sub, with two of these.

interface LinkedAccount {
    readonly provider: string;
    readonly subject: string;
    readonly username: string | null;
    readonly details_read_at: string | null;
    readonly account_type?: string;
    readonly created_at?: string;
    readonly public_repos?: number;
    readonly followers?: number;
    readonly email_verified?: boolean;
    readonly workspace_domain?: string | null;
    readonly test?: true;
}

LinkMethod

Type. A way to sign in a link request can add.

type LinkMethod = Schemas['NewLinkRequest']['method'];

linkSignIn

Function. The sign-in that finishes a link request, for SynqClient.signIn or authorizationUrl: a fresh sign-in (prompt=login) carrying the request.

function linkSignIn(request: { readonly authorization_params: { readonly prompt: "login"; readonly synq_intent: "link"; readonly synq_link: string; }; readonly expires_at: string; readonly method: string; }): AuthorizationUrlOptions

ManagementComponents

Interface. The management API's schemas, generated from its OpenAPI document.

type ManagementComponents // generated from the API's OpenAPI document: see the API reference

ManagementOperations

Type. The management API's operations, generated from its OpenAPI document.

type ManagementOperations // generated from the API's OpenAPI document: see the API reference

ManagementPaths

Interface. The management API's paths, generated from its OpenAPI document: what createManagementClient is typed by.

type ManagementPaths // generated from the API's OpenAPI document: see the API reference

memoryStorage

Function. Keeps everything in this process's memory: the default, and the only store that holds refresh tokens unless told. Clients that share one share its lock, so they never refresh one session twice at once.

function memoryStorage(): SynqStorage

OAuthErrorCode

Type. OAuth's and OpenID Connect's error codes, which Synq's issuers answer with.

type OAuthErrorCode = 'invalid_request' | 'invalid_client' | 'invalid_grant' | 'unauthorized_client' | 'unsupported_grant_type' | 'invalid_scope' | 'invalid_target' | 'access_denied' | 'login_required' | 'consent_required' | 'interaction_required' | 'unmet_authentication_requirements' | 'invalid_token' | 'insufficient_scope' | 'server_error' | 'temporarily_unavailable' | 'invalid_session' | 'redirect_to_web' | 'too_many_requests';

PasskeyAssertionJSON

Type. A passkey's assertion, as PublicKeyCredential.toJSON() gives it.

type PasskeyAssertionJSON = Record<string, unknown>;

PasskeyRequestOptionsJSON

Type. A passkey's request options, for PublicKeyCredential.parseRequestOptionsFromJSON.

type PasskeyRequestOptionsJSON = Record<string, unknown>;

Problem

Type. A problem document from a Synq API (RFC 9457, application/problem+json).

type Problem = {
    type?: string;
    title?: string;
    status?: number;
    code?: string;
    detail?: string;
    [field: string]: unknown;
};

problemError

Function. A SynqError for a problem document a Synq API answered with.

function problemError(status: number, problem: Problem, retryAfter?: number | undefined): SynqError

ReadOptions

Interface. What every read takes.

interface ReadOptions {
    signal?: AbortSignal;
}

RedirectReason

Type. One of REDIRECT_REASONS.

type RedirectReason // generated from the API's OpenAPI document: see the API reference

SavedSignIn

Interface. A flow as toJSON saves it, for resumeSignIn: keep it where only the app reads it.

interface SavedSignIn {
    readonly v: 1;
    readonly verifier: string;
    readonly nonce: string;
    readonly scope: string;
    readonly resource?: string;
    readonly additionalResources?: readonly string[];
    readonly acr?: {
        readonly values: readonly string[];
        readonly essential?: boolean;
    };
    readonly authSession?: string;
    readonly email?: string;
    readonly step: SignInFlowStep;
}

ServerSignInOptions

Interface. What a server signing people in for its app's own screens adds to a flow (@synqauth/nextjs).

interface ServerSignInOptions {
    endUserIp?: string;
}

Session

Interface. A signed-in session, without its refresh token, which the client keeps to itself.

interface Session {
    readonly accessToken: string;
    readonly tokenType: string;
    readonly expiresAt: number | undefined;
    readonly scope: string | undefined;
    readonly idToken: string | undefined;
    readonly claims: IdTokenClaims | undefined;
    readonly refreshable: boolean;
    readonly via: 'hosted' | 'app';
}

SessionEvent

Type. A change to the session, as subscribe reports it.

type SessionEvent = {
    readonly type: 'signed-in';
    readonly session: Session;
} | {
    readonly type: 'refreshed';
    readonly session: Session;
} | {
    readonly type: 'signed-out';
    readonly session: null;
};

SignInFlow

Class. One sign-in on an app's own screens.

class SignInFlow

SignInFlowStep

Type. Where a flow is: what the app's screen asks for now.

type SignInFlowStep = 'start' | 'password' | 'email' | 'code' | 'verify-email' | 'passkey' | 'done';

SignInStepResult

Type. What a step of a sign-in came to: what to show next.

type SignInStepResult<S> = {
    readonly status: 'signed-in';
    readonly session: S;
} | {
    readonly status: 'code-sent';
    readonly email: string;
    readonly expiresAt: Date;
} | {
    readonly status: 'verify-email';
    readonly email: string;
    readonly canSkip: boolean;
} | {
    readonly status: 'passkey';
    readonly options: PasskeyRequestOptionsJSON;
    readonly related?: {
        readonly rpId: string;
        readonly options: PasskeyRequestOptionsJSON;
    };
    readonly problem?: ChallengeProblem;
    readonly message?: string;
} | {
    readonly status: 'retry';
    readonly problem: ChallengeProblem;
    readonly message: string;
    readonly retryAfter?: number;
} | {
    readonly status: 'hosted';
    readonly reason: RedirectReason;
    readonly method?: ChallengeMethod;
    readonly loginHint?: string;
    continue(): Promise<void>;
} | {
    readonly status: 'refused';
    readonly reason: DeniedReason;
    readonly message: string;
};

SignOutOptions

Interface. What signOut takes: where the browser lands afterwards, and the state handed back there.

interface SignOutOptions {
    postLogoutRedirectUri?: string;
    state?: string;
}

StartSignInOptions

Interface. What a sign-in asks for, beyond the client's own.

interface StartSignInOptions {
    scope?: string;
    resource?: string;
    additionalResources?: readonly string[];
    acr?: {
        readonly values: readonly string[];
        readonly essential?: boolean;
    };
}

SynqAnyErrorCode

Type. Every code a SynqError can carry; an unknown one from a newer Synq passes through as a string.

type SynqAnyErrorCode = SynqErrorCode | OAuthErrorCode | SynqClientErrorCode | (string & Record<never, never>);

SynqClient

Interface. A client for one app at one brand's issuer, made by createSynqClient: it signs people in with the authorization code flow, keeps the session, and refreshes and ends it.

interface SynqClient {
    authorizationUrl(options?: AuthorizationUrlOptions): Promise<URL>;
    signIn(options?: AuthorizationUrlOptions): Promise<void>;
    handleCallback(url: string | URL): Promise<Session>;
    getSession(): Promise<Session | null>;
    restoreSession(options?: Omit<AuthorizationUrlOptions, 'prompt'>): Promise<Session | null>;
    getAccessToken(options?: {
        minValiditySeconds?: number;
    }): Promise<string>;
    refresh(): Promise<Session>;
    subscribe(listener: (event: SessionEvent) => void): () => void;
    signOut(options?: SignOutOptions): Promise<URL | null>;
    startSignIn(options?: StartSignInOptions & ServerSignInOptions): SignInFlow<Session>;
    resumeSignIn(saved: SavedSignIn | string, options?: ServerSignInOptions): SignInFlow<Session>;
}

SynqClientErrorCode

Type. The errors the SDK raises itself, before or after asking Synq.

type SynqClientErrorCode = 'invalid_options' | 'discovery_failed' | 'unknown_state' | 'not_signed_in' | 'cancelled' | 'no_refresh_token' | 'invalid_response' | 'network_error' | 'invalid_signature' | 'stale_webhook';

SynqClientOptions

Interface. What a Synq client needs to know about the app it signs people in to.

interface SynqClientOptions {
    issuer: string | URL;
    clientId: string;
    clientSecret?: string;
    redirectUri: string;
    postLogoutRedirectUri?: string;
    scope?: string;
    resource?: string;
    storage?: SynqStorage;
    transactionStorage?: SynqStorage;
    fetch?: typeof fetch;
    refreshLeewaySeconds?: number;
}

SynqError

Class. Every error the SDK throws. Branch on code, which is stable: the API's problem code, OAuth's error, or one of the SDK's own; never on the message.

class SynqError

SynqErrorCode

Type. A stable code from a Synq API's problem document: branch on it, never on the English.

type SynqErrorCode // generated from the API's OpenAPI document: see the API reference

SynqStorage

Interface. Where the client keeps what it must remember: the session, and a sign-in's transaction (its PKCE verifier, state and nonce) across the redirect to Synq and back. Any key-value store fits; each method may be async.

Refresh tokens are kept only by a store that says it may hold them (holdsRefreshTokens): the memory store, or one on a server or in a device's secure storage. Everything else keeps the session without its refresh token, which then lives in the client's memory alone, so a refresh token never lands in localStorage or sessionStorage, where any script on the page reads it.

Synq rotates refresh tokens and ends the whole grant when a used one comes back, so only one refresh may run at a time for one session. One client makes sure of that by itself. When several clients share a store (requests on one server, or replicas sharing a cookie or Redis), the store must give them a lock (lock); a store without one is for one client per process.

interface SynqStorage {
    get(key: string): string | null | undefined | Promise<string | null | undefined>;
    set(key: string, value: string): void | Promise<void>;
    remove(key: string): void | Promise<void>;
    readonly holdsRefreshTokens?: boolean;
    lock?<T>(name: string, fn: () => Promise<T>): Promise<T>;
    keys?(): Iterable<string> | Promise<Iterable<string>>;
}

TestAccount

Interface. A made-up GitHub or Google account for a test sign-in, on Synq's stages other than production, for an app with test_sign_ins on: who the person is there, and what the provider says of the account. Unnamed details take an ordinary account's (a year old, one public repository; a verified personal Google account). It becomes a linked account with test: true, a subject of test-<account>, and an address Synq never verifies.

interface TestAccount {
    readonly provider: 'github' | 'google';
    readonly account: string;
    readonly username?: string;
    readonly email?: string;
    readonly name?: string;
    readonly accountType?: 'User' | 'Organization' | 'Bot';
    readonly accountAgeDays?: number;
    readonly createdAt?: string;
    readonly publicRepos?: number;
    readonly followers?: number;
    readonly emailVerified?: boolean;
    readonly workspaceDomain?: string;
}

@synqauth/js/server

AccessTokenClaims

Interface. A Synq access token's claims (RFC 9068), once checked.

interface AccessTokenClaims {
    readonly iss: string;
    readonly sub: string;
    readonly aud: string | string[];
    readonly azp: string | undefined;
    readonly scopes: readonly string[];
    readonly iat: number;
    readonly exp: number;
    readonly auth_time: number | undefined;
    readonly acr: string | undefined;
    readonly amr: readonly string[] | undefined;
    readonly act: {
        readonly type?: string;
        readonly client_id?: string;
    } | undefined;
    readonly email: string | undefined;
    readonly email_verified: boolean | undefined;
    readonly linked_accounts: readonly LinkedAccount[] | undefined;
    readonly payload: JWTPayload;
}

AccessTokenVerifier

Type. Checks one access token for your API, as createAccessTokenVerifier makes it: the claims when the token is good, else a SynqError (invalid_token, insufficient_scope or fresh_sign_in_required).

type AccessTokenVerifier = (token: string, options?: VerifyAccessTokenOptions) => Promise<AccessTokenClaims>;

AccessTokenVerifierOptions

Interface. What an API checks every access token against.

interface AccessTokenVerifierOptions {
    issuer: string;
    audience: string;
    algorithms?: string[];
    clockToleranceSeconds?: number;
    fetch?: typeof fetch;
    keys?: JWTVerifyGetKey;
}

ApiKeyClaims

Interface. One of your users' API keys, once Synq said it works.

interface ApiKeyClaims {
    readonly iss: string;
    readonly sub: string;
    readonly aud: string;
    readonly scopes: readonly string[];
    readonly keyId: string;
    readonly name: string;
    readonly iat: number;
    readonly exp: number | undefined;
    readonly email: string | undefined;
    readonly email_verified: boolean | undefined;
    readonly linked_accounts: readonly LinkedAccount[] | undefined;
}

ApiKeyVerifier

Type. Checks one of your users' API keys, as createApiKeyVerifier makes it: the claims when the key works, else a SynqError (invalid_token for a key that doesn't, insufficient_scope for one without a scope asked for).

type ApiKeyVerifier = (key: string, options?: VerifyApiKeyOptions) => Promise<ApiKeyClaims>;

ApiKeyVerifierOptions

Interface. What an API checks its users' API keys with: the brand's issuer, and the API's own app.

interface ApiKeyVerifierOptions {
    issuer: string;
    clientId: string;
    clientSecret: string;
    fetch?: typeof fetch;
}

createAccessTokenVerifier

Function. A verifier for one API's access tokens. It reads the issuer's JWKS once and keeps it, fetching it again when a token names a key it doesn't have (a rotation), at most every 30 seconds. A discovery that failed is retried after 30 seconds, not on every token. Keep one per API, not one per request. The issuer and its JWKS must be https (http only on this machine).

function createAccessTokenVerifier(options: AccessTokenVerifierOptions): AccessTokenVerifier

createApiKeyVerifier

Function. A verifier for the API keys your users make for your API. It asks the brand's issuer about every key (POST /api-keys/verify, as the API's own app), and keeps nothing: revoking a key works from its next check. A key Synq says doesn't work is invalid_token (401), never why; your app's credentials refused are invalid_client.

function createApiKeyVerifier(options: ApiKeyVerifierOptions): ApiKeyVerifier

createManagementClient

Function. A client for Synq's management API (/v1), typed by its contract. Server only: an API key never reaches a browser. Failures throw a SynqError with the problem's code, such as insufficient_permissions.

function createManagementClient(options: ManagementClientOptions): ManagementClient

createOwnUiSignIn

Function. Own-UI sign-in for a server: its forms post to it, it calls Synq's Authorization Challenge Endpoint as its app, and a sign-in ends with tokens, not a cookie at Synq. The app keeps them, and the person's password or code never reaches a browser but the form they typed it in. hosted results can't continue() here: send the browser to an ordinary authorization request with the method and loginHint given.

function createOwnUiSignIn(options: OwnUiSignInOptions): OwnUiSignIn

isApiKey

Function. Whether credential is one of your users' API keys (ak_live_… or ak_test_…,) rather than an access token: what tells an API which of createApiKeyVerifier and createAccessTokenVerifier to check a bearer credential with.

function isApiKey(credential: unknown): credential is string

isSynqError

Function. Whether error is a SynqError, with code when given.

function isSynqError(error: unknown, code?: SynqAnyErrorCode | undefined): error is SynqError

LinkedAccount

Interface. One account at an upstream provider the person signs in with, with what the provider said of it at their last sign-in with it. Someone who links GitHub and Google to one account is one sub, with two of these.

interface LinkedAccount {
    readonly provider: string;
    readonly subject: string;
    readonly username: string | null;
    readonly details_read_at: string | null;
    readonly account_type?: string;
    readonly created_at?: string;
    readonly public_repos?: number;
    readonly followers?: number;
    readonly email_verified?: boolean;
    readonly workspace_domain?: string | null;
    readonly test?: true;
}

ManagementClient

Type. The management API's typed client: every path, parameter, body and answer from its contract.

type ManagementClient = ApiClient<paths>;

ManagementClientOptions

Interface. Who a management API client acts as.

interface ManagementClientOptions {
    baseUrl: string;
    apiKey?: string;
    accessToken?: () => string | Promise<string>;
    fetch?: typeof fetch;
}

ManagementComponents

Interface. The management API's schemas, generated from its OpenAPI document.

type ManagementComponents // generated from the API's OpenAPI document: see the API reference

ManagementPaths

Interface. The management API's paths, generated from its OpenAPI document: what createManagementClient is typed by.

type ManagementPaths // generated from the API's OpenAPI document: see the API reference

OwnUiSignIn

Interface. A server's own-UI sign-ins: one flow per sign-in, kept between requests with toJSON.

interface OwnUiSignIn {
    start(options?: StartSignInOptions & {
        endUserIp?: string;
    }): SignInFlow<OwnUiTokens>;
    resume(saved: SavedSignIn | string, options?: {
        endUserIp?: string;
    }): SignInFlow<OwnUiTokens>;
}

OwnUiSignInOptions

Interface. What a server needs to sign people in on its app's own screens.

interface OwnUiSignInOptions {
    issuer: string;
    clientId: string;
    clientSecret?: string;
    privateKey?: CryptoKey | {
        key: CryptoKey;
        kid?: string;
    };
    fetch?: typeof fetch;
}

OwnUiTokens

Interface. What a server's own-UI sign-in ends with: the app keeps them as its session.

interface OwnUiTokens {
    readonly accessToken: string;
    readonly tokenType: string;
    readonly expiresAt: number | undefined;
    readonly scope: string | undefined;
    readonly idToken: string;
    readonly refreshToken: string | undefined;
    readonly claims: IdTokenClaims;
}

SavedSignIn

Interface. A flow as toJSON saves it, for resumeSignIn: keep it where only the app reads it.

interface SavedSignIn {
    readonly v: 1;
    readonly verifier: string;
    readonly nonce: string;
    readonly scope: string;
    readonly resource?: string;
    readonly additionalResources?: readonly string[];
    readonly acr?: {
        readonly values: readonly string[];
        readonly essential?: boolean;
    };
    readonly authSession?: string;
    readonly email?: string;
    readonly step: SignInFlowStep;
}

SignInFlow

Class. One sign-in on an app's own screens.

class SignInFlow

SignInFlowStep

Type. Where a flow is: what the app's screen asks for now.

type SignInFlowStep = 'start' | 'password' | 'email' | 'code' | 'verify-email' | 'passkey' | 'done';

SignInStepResult

Type. What a step of a sign-in came to: what to show next.

type SignInStepResult<S> = {
    readonly status: 'signed-in';
    readonly session: S;
} | {
    readonly status: 'code-sent';
    readonly email: string;
    readonly expiresAt: Date;
} | {
    readonly status: 'verify-email';
    readonly email: string;
    readonly canSkip: boolean;
} | {
    readonly status: 'passkey';
    readonly options: PasskeyRequestOptionsJSON;
    readonly related?: {
        readonly rpId: string;
        readonly options: PasskeyRequestOptionsJSON;
    };
    readonly problem?: ChallengeProblem;
    readonly message?: string;
} | {
    readonly status: 'retry';
    readonly problem: ChallengeProblem;
    readonly message: string;
    readonly retryAfter?: number;
} | {
    readonly status: 'hosted';
    readonly reason: RedirectReason;
    readonly method?: ChallengeMethod;
    readonly loginHint?: string;
    continue(): Promise<void>;
} | {
    readonly status: 'refused';
    readonly reason: DeniedReason;
    readonly message: string;
};

StartSignInOptions

Interface. What a sign-in asks for, beyond the client's own.

interface StartSignInOptions {
    scope?: string;
    resource?: string;
    additionalResources?: readonly string[];
    acr?: {
        readonly values: readonly string[];
        readonly essential?: boolean;
    };
}

SynqError

Class. Every error the SDK throws. Branch on code, which is stable: the API's problem code, OAuth's error, or one of the SDK's own; never on the message.

class SynqError

VerifiedWebhook

Interface. A delivery that passed its check.

interface VerifiedWebhook {
    readonly id: string;
    readonly timestamp: Date;
    readonly event: WebhookEvent;
}

VerifyAccessTokenOptions

Interface. What one route wants of a token, on top of the verifier's checks.

interface VerifyAccessTokenOptions {
    scopes?: readonly string[];
    authorizedParties?: readonly string[];
    maxAuthAgeSeconds?: number;
}

VerifyApiKeyOptions

Interface. What one route wants of a key, on top of the verifier's checks.

interface VerifyApiKeyOptions {
    scopes?: readonly string[];
}

verifyWebhook

Function. Checks a delivery's Standard Webhooks signature (webhook-id, webhook-timestamp, webhook-signature, HMAC-SHA256 over <id>.<timestamp>.<body>) against the subscription's whsec_ secret, and that Synq signed it within toleranceSeconds (5 minutes by default), so a captured delivery can't be replayed later. Pass both secrets while one is being rotated: Synq signs with both for 24 hours. body is the request's raw body, exactly as it arrived.

function verifyWebhook(body: string, headers: HeadersLike, secrets: string | readonly string[], options?: { toleranceSeconds?: number | undefined; now?: Date | undefined; }): Promise<VerifiedWebhook>

WebhookEvent

Type. A Synq webhook's event: one row of the org's audit log (the management API's WebhookEvent).

type WebhookEvent = components['schemas']['WebhookEvent'];

See every package.

On this page

@synqauth/jsAccountApiKeyAccountApiKeyCreateaccountApiUrlAccountClientAccountClientOptionsAccountComponentsAccountConsentAccountIdentityAccountKeyableApiAccountLinkRequestAccountNewApiKeyAccountOperationsAccountPasskeyAccountPathsAccountProfileAccountProfileUpdateAccountResultAccountSessionAccountSignInAccountUsernameAvailabilityAccountWalletAccountWalletUpdateAuthorizationUrlOptionsbrowserLocalStoragebrowserSessionStorageCHALLENGE_METHODSCHALLENGE_PROBLEMSChallengeMethodChallengeProblemChangeOptionscreateAccountClientcreateSynqClientDeniedReasonERROR_CODESIdTokenClaimsisSynqErrorLinkedAccountLinkMethodlinkSignInManagementComponentsManagementOperationsManagementPathsmemoryStorageOAuthErrorCodePasskeyAssertionJSONPasskeyRequestOptionsJSONProblemproblemErrorReadOptionsRedirectReasonSavedSignInServerSignInOptionsSessionSessionEventSignInFlowSignInFlowStepSignInStepResultSignOutOptionsStartSignInOptionsSynqAnyErrorCodeSynqClientSynqClientErrorCodeSynqClientOptionsSynqErrorSynqErrorCodeSynqStorageTestAccount@synqauth/js/serverAccessTokenClaimsAccessTokenVerifierAccessTokenVerifierOptionsApiKeyClaimsApiKeyVerifierApiKeyVerifierOptionscreateAccessTokenVerifiercreateApiKeyVerifiercreateManagementClientcreateOwnUiSignInisApiKeyisSynqErrorLinkedAccountManagementClientManagementClientOptionsManagementComponentsManagementPathsOwnUiSignInOwnUiSignInOptionsOwnUiTokensSavedSignInSignInFlowSignInFlowStepSignInStepResultStartSignInOptionsSynqErrorVerifiedWebhookVerifyAccessTokenOptionsVerifyApiKeyOptionsverifyWebhookWebhookEvent