Node.js SDK API Reference
Complete API reference for Hawcx OAuth Client SDK for Node.js
Node.js SDK API Reference
The SDK exposes two construction paths on HawcxOAuth:
| Path | Constructor | When to use |
|---|---|---|
| Discovery (recommended) | await HawcxOAuth.fromIssuer({ issuer, configId, clientId }) | New code. Discovers /.well-known/openid-configuration once at startup and enforces signature + iss + aud + exp + nbf on every verify. |
| Legacy | new HawcxOAuth({ configId, baseUrl }) | 4.x callers. Hits fixed endpoints <baseUrl>/oauth2/token and <baseUrl>/keys; verifies signature only — iss and aud are not checked. |
Both modes share the same exchangeCode / verifyToken / clearCache methods.
HawcxOAuth (discovery mode)
HawcxOAuth.fromIssuer(config)
Async factory. Fetches <issuer>/.well-known/openid-configuration once at
construction, reads the token endpoint + JWKS URI + supported id_token
signing algorithm, and wires a verifier that enforces signature, iss,
aud, exp, and nbf on subsequent verifyToken calls.
import { HawcxOAuth } from '@hawcx/oauth-client';
const oauth = await HawcxOAuth.fromIssuer({
issuer: process.env.HAWCX_BASE_URL!, // discovery + expected `iss`
configId: process.env.HAWCX_CONFIG_ID!, // → X-Config-Id header
clientId: process.env.HAWCX_CLIENT_ID!, // → expected `aud` on id_tokens
});Config:
| Property | Type | Required | Description |
|---|---|---|---|
issuer | string | Yes | Hawcx issuer URL. Discovery target and expected iss claim. |
configId | string | Yes | Tenant routing key. Sent as X-Config-Id header on token exchange. |
clientId | string | Yes | The value the tenant has configured (Admin Console) as the aud claim on issued id_tokens. |
timeout | number | No | Per-request timeout in ms (default 10_000). |
discoveryTimeout | number | No | Discovery fetch timeout in ms (default 5_000). |
configId and clientId are distinct
configId routes the token exchange (header); clientId is matched
against the aud claim. They are configured separately in the Admin
Console and may be different strings. Passing the same value for both
fails verification with Unexpected JWT audience unless the tenant has
configured them identically.
Throws DiscoveryError if the discovery document is unreachable,
returns non-2xx, isn't valid JSON, or is missing any of token_endpoint,
jwks_uri, id_token_signing_alg_values_supported. The underlying
network / parse error is preserved as err.cause.
oauth.discoveryMetadata
The resolved OIDC discovery document. Useful for diagnostics — confirm which endpoints and signing algs were picked up.
oauth.discoveryMetadata?.token_endpoint;
oauth.discoveryMetadata?.jwks_uri;
oauth.discoveryMetadata?.id_token_signing_alg_values_supported;null on clients constructed via the legacy constructor.
HawcxOAuth (legacy mode)
For 4.x callers; new code should prefer the discovery path above.
import { HawcxOAuth } from '@hawcx/oauth-client';
const oauth = new HawcxOAuth({
configId: process.env.HAWCX_CONFIG_ID!,
baseUrl: process.env.HAWCX_BASE_URL!,
timeout: 10_000,
});Config:
| Property | Type | Required | Description |
|---|---|---|---|
configId | string | Yes | Hawcx Config ID. |
baseUrl | string | No | Defaults to https://api.hawcx.com. |
timeout | number | No | Request timeout in ms (default 10_000). |
Verifies signature + exp + nbf. iss and aud are not checked
(the legacy constructor has no way to know what to expect).
Shared methods
exchangeCode(code, codeVerifier, redirectUri?)
Exchange an authorization code for verified claims.
const { idToken, claims } = await oauth.exchangeCode(authCode, codeVerifier);
// With redirect_uri (RFC 6749 §4.1.3) when your auth request registered one:
const { idToken, claims } = await oauth.exchangeCode(
authCode,
codeVerifier,
'https://app.example.com/auth/callback',
);Returns:
| Property | Type | Description |
|---|---|---|
idToken | string | Raw JWT (do not use as access token) |
claims | object | Verified JWT claims |
verifyToken(token, options?)
Verify a JWT and return its claims.
- Discovery mode enforces signature +
iss+aud+exp+nbf. - Legacy mode enforces signature +
exp+nbf.issandaudare not checked — the legacy SDK has no way to know what to expect. options.nonceis checked in both modes when provided. If the token'snonceclaim doesn't match,TokenVerificationErroris thrown regardless of construction path.
const claims = await oauth.verifyToken(idToken);
// With expected nonce, when your auth request bound one:
const claims = await oauth.verifyToken(idToken, { nonce: 'expected-nonce' });clearCache()
Clear the JWKS cache (useful for key rotation or tests).
oauth.clearCache();Error Types
import {
HawcxOAuthError,
DiscoveryError,
TokenExchangeError,
TokenVerificationError,
} from '@hawcx/oauth-client';DiscoveryError—fromIssuercould not resolve a usable discovery document. Underlying network / parse error is preserved aserr.cause.TokenExchangeError— code exchange failed (invalid/expired code, network error, missingid_tokenin response). CarriesstatusCode.TokenVerificationError— JWT verification failed. Messages includeToken expired,Invalid signature,Token not yet valid, and (in discovery mode)Unexpected JWT audience/Unexpected JWT issuer.
Delegation Client
Use the delegation client for backend-driven MFA setup and user/device management.
DelegationClient.fromSecretKey(options)
import { DelegationClient } from '@hawcx/oauth-client';
const client = DelegationClient.fromSecretKey({
secretKey: process.env.HAWCX_SECRET_KEY!,
baseUrl: process.env.HAWCX_BASE_URL!,
apiKey: process.env.HAWCX_CONFIG_ID
});DelegationClient.fromKeys(options)
const client = DelegationClient.fromKeys({
spSigningKey: process.env.SP_ED25519_PRIVATE_KEY_PEM!,
spEncryptionKey: process.env.SP_X25519_PRIVATE_KEY_PEM!,
idpVerifyKey: process.env.IDP_ED25519_PUBLIC_KEY_PEM!,
idpEncryptionKey: process.env.IDP_X25519_PUBLIC_KEY_PEM!,
spKid: process.env.SP_KEY_ID!,
idpKid: process.env.IDP_KEY_ID!,
baseUrl: process.env.HAWCX_BASE_URL!,
apiKey: process.env.HAWCX_CONFIG_ID
});MFA
import { MfaMethod } from '@hawcx/oauth-client';
const result = await client.mfa.initiate({
userId: '[email protected]',
mfaMethod: MfaMethod.SMS,
phoneNumber: '+15551234567'
});
await client.mfa.verify({
userId: '[email protected]',
sessionId: result.session_id,
otp: '123456'
});Users
const creds = await client.users.getCredentials('[email protected]');Devices
const devices = await client.devices.list('[email protected]');
await client.devices.revoke({ userId: '[email protected]', deviceId: 'h2index' });