Client SDK

The OpenAuthsterClient class (from openauthster-shared/client/user) is the recommended way to integrate authentication into your application. It manages the full lifecycle: PKCE login flow, token storage, automatic refresh, session read/write, and authenticated requests.


Creating a Client

import { createOpenAuthsterClient } from "openauthster-shared/client/user";
 
const client = createOpenAuthsterClient({
  clientID: "my_project",
  issuerURI: "https://randomUUID-auth.yourdomain.com",
  redirectURI: "https://myapp.com/",
  copyID: "en-us", // copy template for i18n (null if unused)
  secret: undefined, // server-side only
});

Options Reference

OptionTypeRequiredDescription
clientIDstringYesProject slug from the Web UI
issuerURIstringYesBase URL of the OpenAuthster issuer generated during the project creation
redirectURIstringYesURL the issuer redirects to after login
copyIDstring | nullNoCopy template ID for i18n (e.g. "en-us")
secretstringNoClient secret — server-side only, needed for private sessions
tokenstring | nullNoPre-existing access token
refreshTokenstring | nullNoPre-existing refresh token

Initialisation

init()

Call once in the browser on page load:

await client.init();

This method:

  1. Checks if a code query parameter exists (OAuth callback).
  2. Check if a invite_id query parameter exists (invite flow).
  3. If so, exchanges it for tokens using the stored PKCE challenge.
  4. Otherwise, restores tokens from localStorage.
  5. Fires all registered initialisation listeners.

Authentication

login()

Redirects the user to the issuer's login page:

await client.login();

Under the hood this calls client.authorize(redirectURI, "code"), stores a PKCE challenge in localStorage, and sets window.location.href.

logout()

Clears all tokens and session data:

client.logout();

After calling logout():

  • isAuthenticated becomes false
  • data.public and data.private are reset to {}
  • Tokens are removed from localStorage
  • The refresh timer is cancelled

Auth State

client.isAuthenticated; // boolean — true once tokens are obtained
client.isLoaded; // boolean — true after init() completes
client.expiresIn; // number | undefined — seconds until access token expires
client.userMeta; // { user_id: string | null, user_identifier: string | null }

Authenticated Fetch

client.fetch() works like the global fetch() but adds auth headers automatically:

const res = await client.fetch("/api/v1/profile");
const data = await res.json();

Headers added:

  • Authorization: Bearer <accessToken>
  • X-Client-Secret: <secret> (only when a secret is configured)

Auto Token Refresh

The client schedules a silent refresh 60 seconds before the access token expires. New tokens are persisted to localStorage automatically. If the refresh fails, a warning is logged to the console.


Listeners

Register callbacks that fire when auth state changes:

client.addInitializationListener("my-key", () => {
  console.log("Auth state changed:", client.isAuthenticated);
});

Call triggerUpdate() manually after state-changing operations like updateUserSession():

await client.updateUserSession("public", { theme: "dark" });
client.triggerUpdate(); // listeners fire

Updating Copy Template

Switch the i18n copy template at runtime:

client.updateOptions({ copyID: "fr-fr" });

This recreates the internal OpenAuth client with the new template.


Low-Level Client

If you only need the raw @openauthjs/openauth client with OpenAuthster cookies, import from openauthster-shared/client:

import { createClient, createServerClient } from "openauthster-shared/client";
 
const rawClient = createClient({
  clientID: "my_project",
  issuer: "https://auth.yourdomain.com",
  copyID: "en-us",
});

This returns a plain OpenAuth Client — you handle tokens, storage, and refreshing yourself.


Next Steps