@corvushold/guard-sdk
v0.18.0
Published
Guard CAS TypeScript SDK for Node.js, browsers, and React Native (beta)
Downloads
637
Readme
Reference SDK for Guard CAS targeting Node.js, browsers, and React Native.
This SDK uses a spec‑first approach. Core auth flows implemented:
- Password login (MFA challenge aware)
- MFA verify (TOTP / backup)
- Refresh tokens
- Logout (revoke refresh)
- Current user profile (
me) - Token introspection
- Magic link: send + verify
OAuth2 Authorization Code (PKCE)
Use the SDK to build the authorization URL from the configured baseUrl (Guard API host),
instead of manually composing /oauth/authorize against the current page origin.
import { GuardClient } from '@corvushold/guard-sdk';
const client = new GuardClient({
baseUrl: 'http://localhost:8082', // Guard API URL
});
const authorizeUrl = client.buildOAuth2AuthorizeUrl({
client_id: 'gc_VXfCQgfwZChIpUFVCLAgEecI_OKSMszh',
redirect_uri: 'http://localhost:3000/callback',
code_challenge: 'PKCE_CODE_CHALLENGE',
code_challenge_method: 'S256',
scope: ['openid', 'profile', 'email'],
state: crypto.randomUUID(),
});
window.location.href = authorizeUrl;Notes:
response_typedefaults tocode.scopeaccepts either a string ("openid profile email") or a string array.- When
code_challengeis set andcode_challenge_methodis omitted, the SDK defaults toS256.
WorkOS Organization Portal Link
Generate a WorkOS Admin Portal link for an organization (server enforces admin-only RBAC):
import { GuardClient } from '@corvushold/guard-sdk';
const client = new GuardClient({
baseUrl: 'https://guard.example.com',
tenantId: '00000000-0000-4000-8000-000000000000',
});
// Provide an admin access token in storage or via default headers
await client['storage'].setAccessToken('ADMIN_ACCESS_TOKEN');
const { data } = await client.getSsoOrganizationPortalLink('workos', {
organization_id: 'org_01H...',
intent: 'sso', // optional. allowed: sso, dsync, audit_logs, log_streams, domain_verification, certificate_renewal, user_management
});
console.log(data.link); // e.g., https://dashboard.workos.com/organizations/.../portalNotes:
tenant_idis required; if omitted in params, the client instancetenantIdis used.organization_idis required.intentis optional; unsupported values are rejected by the server.
Explicit configuration is required for baseUrl. The X-Guard-Client header is set automatically as ts-sdk/<package.version>.
Install
npm install @corvushold/guard-sdkNode (>=18)
import { GuardClient, InMemoryStorage, isTokensResp, isMfaChallengeResp } from '@corvushold/guard-sdk';
const client = new GuardClient({
baseUrl: 'https://guard.example.com', // required
storage: new InMemoryStorage(),
// fetchImpl: global fetch in Node 18+; inject a polyfill if needed
});
// Password login returns a union: Tokens or MFA Challenge
const login = await client.passwordLogin({ email: '[email protected]', password: 'pw', tenant_id: 'tenant_123' });
if (login.meta.status === 200 && isTokensResp(login.data)) {
// access/refresh tokens persisted into storage
} else if (login.meta.status === 202 && isMfaChallengeResp(login.data)) {
// MFA challenge flow
const verify = await client.mfaVerify({ challenge_token: login.data.challenge_token, method: 'totp', code: '123456' });
}
// Me (Authorization header auto‑injected from storage)
const me = await client.me();
// Refresh
const refreshed = await client.refresh(); // uses stored refresh token if omitted
// Logout
await client.logout(); // clears stored refresh on 204
// Introspect
const info = await client.introspect();
// Magic link
await client.magicSend({ tenant_id: 'tenant_123', email: '[email protected]', redirect_url: 'https://app.example.com/callback' });
const verified = await client.magicVerify({ token: 'magic_token_from_email' });
// SSO callback token parsing (after redirect from IdP)
// Works with query params, fragments, or full URLs
const tokens = client.parseSsoCallbackTokens(window.location.hash); // or window.location.search
if (tokens) {
console.log('Access token:', tokens.access_token);
// refresh_token may be undefined in some SSO flows
if (tokens.refresh_token) {
console.log('Refresh token available');
}
}Browser
import { GuardClient, WebLocalStorage } from '@corvushold/guard-sdk';
const client = new GuardClient({
baseUrl: 'https://guard.example.com',
storage: new WebLocalStorage('myapp'), // persists in localStorage
});
// Then same as Node usage aboveReact Native
import { GuardClient, reactNativeStorageAdapter } from '@corvushold/guard-sdk';
import AsyncStorage from '@react-native-async-storage/async-storage';
const client = new GuardClient({
baseUrl: 'https://guard.example.com',
storage: reactNativeStorageAdapter(AsyncStorage, 'myapp'),
// fetchImpl: RN provides global fetch; inject custom fetch if desired
});Errors and rate limits
- Non‑2xx responses throw
ApiErrorwith fields:status,message,code?,requestId?,headers?,raw?. - 429 responses throw
RateLimitErrorand parseRetry-AfterintoretryAfterseconds andnextRetryAt: Date.
Notes
baseUrlmust be provided explicitly.Authorization: Bearer <access_token>is injected automatically from the configured storage, when present.X-Guard-Clientis sent asts-sdk/<pkg.version>.passwordLogin()returns a union of tokens or MFA challenge. Use the exported type guardsisTokensResp()andisMfaChallengeResp()to narrow.- The SDK uses generated DTOs; see
src/generated/openapi.d.tsfor types.
