TypeScript SDK
The @DarkAuth/client package helps browser applications start OIDC login, handle callbacks, manage token state, refresh sessions, and process ZK key delivery.
Basic setup
Section titled “Basic setup”Configure the SDK with your issuer, client ID, redirect URI, scopes, and whether the app uses ZK delivery.
import { handleCallback, initiateLogin, setConfig } from "@DarkAuth/client";
setConfig({ issuer: "https://auth.example.com", clientId: "app-web", redirectUri: "https://app.example.com/callback", scope: "openid profile email", zk: true,});
await initiateLogin();On the callback page:
const session = await handleCallback();Defaults
Section titled “Defaults”The SDK defaults are designed for hosted browser apps:
- PKCE for login.
- OAuth state validation.
- Cookie-based refresh where appropriate.
- Memory-only token view.
- Memory-only delivered-key custody.
- ZK validation when ZK artifacts are present.
The SDK can support explicit legacy storage options, but persistent token, ARK, CAK, or legacy DRK storage should be a conscious decision rather than an accidental default.
Session shape
Section titled “Session shape”The callback returns an auth session with an ID token, optional access token, and delivered key material when the client uses ZK delivery. Current v2 flows deliver a CAK and metadata. Non-ZK flows return no usable encryption key, so application code should branch on the ZK fields instead of assuming every login returns a root key.
Organization switching
Section titled “Organization switching”DarkAuth organization switching selects a new authorization context. The selected organization is represented in freshly issued ID and access tokens, not just in app UI state.
App-owned switcher
Section titled “App-owned switcher”Use this pattern when the app renders its own workspace rail, account menu, or organization picker.
import { getCurrentUser, listOrganizations, switchOrganization,} from "@DarkAuth/client";
const organizations = await listOrganizations();const activeOrganizationId = getCurrentUser()?.org_id;
async function chooseOrganization(organizationId: string) { const session = await switchOrganization(organizationId); const selectedOrganizationId = getCurrentUser()?.org_id;}App-owned switching updates the DarkAuth session organization, forces a token refresh, and returns the refreshed org-scoped session. DarkAuth validates active membership before changing the session. After the refresh, verify the token org_id before loading workspace data.
Use mode: "authorize" when a deployment should re-enter the redirect-based OAuth flow with PKCE and state for every organization switch.
Treat every organization switch as a tenant or workspace state reset. Clear tenant-local caches, selected records, in-flight requests, realtime subscriptions, and cached authorization decisions before rendering data for the new organization.
Hosted switcher
Section titled “Hosted switcher”Use this pattern when DarkAuth should own the organization picker UI.
import { refreshSession, switchOrganization } from "@DarkAuth/client";
await switchOrganization("org_123", { mode: "hosted", returnTo: window.location.href,});
await refreshSession({ force: true });Hosted mode redirects to /switch-org, updates the first-party DarkAuth session organization, and returns to the app. The app then forces a refresh so the current ID and access tokens reflect the selected organization.
When to send organization_id
Section titled “When to send organization_id”Send organization_id on /authorize when the app already knows the intended organization. Common cases are:
- The user clicked an organization in an app-owned switcher.
- A workspace URL or subdomain maps to a known organization.
- The app is starting login from an organization-specific invite or deep link.
With the SDK, call initiateLogin({ organizationId }) to send organization_id on /authorize. For an already signed-in first-party browser app, call switchOrganization(organizationId) to silently update the session organization and refresh tokens. Without the SDK, include organization_id=<uuid> in the authorization request. Omit it when DarkAuth should select the user’s only active organization or show the hosted selector for multi-organization users.
Selected organization claims
Section titled “Selected organization claims”When organization context is resolved, tokens can include:
org_id: selected organization ID.org_slug: selected organization slug.roles: roles for the selected organization only.permissions: permissions for the selected organization only.
Applications should use sub as the user identity and org_id as the active tenant or workspace. Do not merge roles or permissions across organizations. Reject access when a token’s org_id does not match the resource organization.
Crypto helpers
Section titled “Crypto helpers”The client package also exports helper functions for base64url encoding, SHA-256, HKDF, AES-GCM encryption, note-style DEK derivation, and private-key wrapping. Use these helpers when building apps that need client-side encryption aligned with DarkAuth’s custody model.
When to skip the SDK
Section titled “When to skip the SDK”Server-side applications can use ordinary OAuth/OIDC libraries instead. Use the SDK when your browser app needs DarkAuth-specific callback handling, ZK delivery, or client-side encryption helpers.