Skip to main content

Node.js SDK API Reference

OAuth Exchange

exchangeCodeForClaims(options)

Exchanges a Hawcx authorization code for verified JWT claims. Parameters:
interface ExchangeCodeForClaimsOptions {
  code: string;                    // Authorization code from Hawcx
  oauthTokenUrl: string;           // Token endpoint URL
  clientId: string;                // OAuth client ID
  publicKey: string | Buffer;      // Public key (PEM string or file path)
  codeVerifier?: string;           // PKCE code verifier (optional)
  audience?: string;               // Expected 'aud' claim (optional)
  issuer?: string;                 // Expected 'iss' claim (optional)
  leeway?: number;                 // Clock skew tolerance in seconds (default: 0)
}
Returns:
interface Claims {
  sub: string;                     // Subject (user ID)
  email: string;                   // User email
  email_verified: boolean;         // Whether email is verified
  aud: string;                     // Audience
  iss: string;                     // Issuer
  iat: number;                     // Issued at (Unix timestamp)
  exp: number;                     // Expiration (Unix timestamp)
  [key: string]: any;              // Additional claims
}
Throws:
  • OAuthExchangeError - Failed to exchange code for token
  • JWTVerificationError - JWT signature or claims validation failed
  • InvalidPublicKeyError - Public key is malformed
Example:
try {
  const claims = await exchangeCodeForClaims({
    code: 'auth_code_from_client',
    oauthTokenUrl: 'https://oauth.hawcx.com/token',
    clientId: 'your_client_id',
    publicKey: process.env.OAUTH_PUBLIC_KEY,
    audience: 'your_client_id'
  });
  
  console.log('User ID:', claims.sub);
  console.log('Email:', claims.email);
} catch (error) {
  console.error('Exchange failed:', error.message);
}

JWT Verification

verifyJwt(token, publicKey, options?)

Manually verify a JWT token using the provided public key. Parameters:
interface VerifyJwtOptions {
  algorithms?: string[];           // Allowed algorithms (default: ['RS256'])
  audience?: string;               // Expected 'aud' claim
  issuer?: string;                 // Expected 'iss' claim
  leeway?: number;                 // Clock skew tolerance in seconds
}
Returns:
interface JwtPayload {
  [key: string]: any;
}
Example:
import { verifyJwt } from '@hawcx/oauth-client';

const payload = verifyJwt(token, publicKey, {
  audience: 'my-app',
  issuer: 'https://oauth.hawcx.com'
});

Delegation Client

The HawcxDelegationClient provides high-level APIs for managing user MFA settings and credentials.

HawcxDelegationClient.fromKeys(options)

Initialize the delegation client with explicit cryptographic keys. Parameters:
interface DelegationClientOptions {
  spSigningKey: string;            // Service provider ED25519 private key (PEM)
  spEncryptionKey: string;         // Service provider X25519 private key (PEM)
  idpVerifyKey: string;            // Identity provider ED25519 public key (PEM)
  idpEncryptionKey: string;        // Identity provider X25519 public key (PEM)
  baseUrl: string;                 // Hawcx base URL (default: 'https://ceasar-api.hawcx.com')
  spId: string;                    // Service provider ID (usually your client ID)
}
Example:
import { HawcxDelegationClient } from '@hawcx/oauth-client';

const client = HawcxDelegationClient.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,
  spId: process.env.OAUTH_CLIENT_ID
});

initiateMfaChange(options)

Initiate MFA setup or change for a user. Parameters:
interface InitiateMfaChangeOptions {
  userid: string;                  // User email or ID
  mfaMethod: MfaMethod;            // MFA method (EMAIL, SMS, TOTP)
  phoneNumber?: string;            // Phone number (required for SMS)
}

enum MfaMethod {
  EMAIL = 'email',
  SMS = 'sms',
  TOTP = 'totp'
}
Returns:
interface MfaChangeResult {
  session_id: string;              // Session ID for verification
  status: string;
  message?: string;
}
Example:
import { MfaMethod } from '@hawcx/oauth-client';

const result = await client.initiateMfaChange({
  userid: '[email protected]',
  mfaMethod: MfaMethod.SMS,
  phoneNumber: '+15551234567'
});

console.log('Session ID:', result.session_id);

verifyMfaChange(options)

Verify OTP and complete MFA setup or change. Parameters:
interface VerifyMfaChangeOptions {
  userid: string;                  // User email or ID
  sessionId: string;               // Session ID from initiateMfaChange
  otp: string;                     // One-time password (6 digits)
}
Returns:
interface VerifyMfaChangeResult {
  status: 'success' | 'failed';
  message?: string;
}
Example:
const result = await client.verifyMfaChange({
  userid: '[email protected]',
  sessionId: sessionFromInitiate,
  otp: '123456'
});

if (result.status === 'success') {
  console.log('MFA setup complete!');
}

getUserCredentials(userid)

Retrieve the current MFA method and credentials for a user. Parameters:
  • userid (string) - User email or ID
Returns:
interface UserCredentials {
  mfa_method: string;              // Current MFA method
  status: string;
  message?: string;
}
Example:
const creds = await client.getUserCredentials('[email protected]');
console.log('Current MFA:', creds.mfa_method);

Exception Types

OAuthExchangeError

Thrown when OAuth code exchange fails.
try {
  await exchangeCodeForClaims(options);
} catch (error) {
  if (error instanceof OAuthExchangeError) {
    console.error('OAuth error:', error.message);
  }
}

JWTVerificationError

Thrown when JWT signature or claims validation fails.
try {
  verifyJwt(token, publicKey);
} catch (error) {
  if (error instanceof JWTVerificationError) {
    console.error('JWT verification failed:', error.message);
  }
}

InvalidPublicKeyError

Thrown when the provided public key is malformed.
try {
  await exchangeCodeForClaims({
    publicKey: 'invalid-key'
  });
} catch (error) {
  if (error instanceof InvalidPublicKeyError) {
    console.error('Key format error:', error.message);
  }
}

Type Definitions

All types are fully exported and available for import:
import {
  Claims,
  JwtPayload,
  MfaMethod,
  ExchangeCodeForClaimsOptions,
  UserCredentials,
  OAuthExchangeError,
  JWTVerificationError,
  InvalidPublicKeyError,
  HawcxDelegationClient
} from '@hawcx/oauth-client';

Best Practices

1. Environment Variable Management

// Use environment variables for all sensitive keys
const client = HawcxDelegationClient.fromEnv();

2. Error Handling

import {
  exchangeCodeForClaims,
  OAuthExchangeError,
  JWTVerificationError
} from '@hawcx/oauth-client';

try {
  const claims = await exchangeCodeForClaims({
    code: authCode,
    oauthTokenUrl: process.env.OAUTH_TOKEN_ENDPOINT!,
    clientId: process.env.OAUTH_CLIENT_ID!,
    publicKey: process.env.OAUTH_PUBLIC_KEY!
  });
} catch (error) {
  if (error instanceof OAuthExchangeError) {
    // Handle OAuth errors (invalid code, expired, etc.)
  } else if (error instanceof JWTVerificationError) {
    // Handle JWT validation errors
  } else {
    throw error;
  }
}

3. Clock Skew Tolerance

For distributed systems, add clock skew tolerance:
const claims = await exchangeCodeForClaims({
  code: authCode,
  oauthTokenUrl: tokenEndpoint,
  clientId: clientId,
  publicKey: publicKey,
  leeway: 10  // Allow 10 seconds of clock skew
});

4. MFA Flow

// Step 1: Initiate
const mfaSession = await client.initiateMfaChange({
  userid: '[email protected]',
  mfaMethod: MfaMethod.SMS,
  phoneNumber: '+15551234567'
});

// Step 2: User receives OTP via SMS

// Step 3: Verify
const result = await client.verifyMfaChange({
  userid: '[email protected]',
  sessionId: mfaSession.session_id,
  otp: userProvidedOtp
});

if (result.status === 'success') {
  // MFA setup complete
}

Environment Variables

Configure these required variables for the delegation client:
SP_ED25519_PRIVATE_KEY_PEM=-----BEGIN PRIVATE KEY-----\n...
SP_X25519_PRIVATE_KEY_PEM=-----BEGIN PRIVATE KEY-----\n...
IDP_ED25519_PUBLIC_KEY_PEM=-----BEGIN PUBLIC KEY-----\n...
IDP_X25519_PUBLIC_KEY_PEM=-----BEGIN PUBLIC KEY-----\n...
OAUTH_CLIENT_ID=your_client_id