Node.js Backend SDK Quickstart
Integrate Hawcx OAuth authentication in your Node.js backend
Hawcx OAuth Client SDK for Node.js
Add passwordless authentication to your Node.js backend. Exchange authorization codes for verified user claims and manage MFA.
Installation
npm install @hawcx/oauth-clientQuick Start
OAuth Code Exchange
The most common flow: exchange authCode + codeVerifier for verified user claims.
import { HawcxOAuth } from '@hawcx/oauth-client';
const oauth = new HawcxOAuth({
configId: process.env.HAWCX_API_KEY!,
baseUrl: process.env.HAWCX_BASE_URL // optional
});
app.post('/exchange', async (req, res) => {
try {
const { authCode, codeVerifier } = req.body;
// Exchange the authorization code for verified claims
const { claims } = await oauth.exchangeCode(authCode, codeVerifier);
// Use the verified claims
const userId = claims.sub;
const email = claims.email;
// Mint your own access token or session
const sessionToken = jwt.sign(
{ sub: claims.sub, email: claims.email },
process.env.APP_SESSION_SECRET!,
{ expiresIn: '1h' }
);
res.json({ sessionToken, userId });
} catch (error) {
console.error('OAuth exchange failed:', error);
res.status(401).json({ error: 'Authentication failed' });
}
});Delegation Client (MFA Setup)
For advanced use cases like setting up MFA for users programmatically:
import { DelegationClient, MfaMethod } from '@hawcx/oauth-client';
// Initialize the delegation client with your secret key blob
const client = DelegationClient.fromSecretKey({
secretKey: process.env.HAWCX_SECRET_KEY!,
baseUrl: process.env.HAWCX_BASE_URL || 'https://api.hawcx.com',
apiKey: process.env.HAWCX_API_KEY
});
// Initiate MFA setup (Email, SMS, or TOTP)
const result = await client.mfa.initiate({
userId: '[email protected]',
mfaMethod: MfaMethod.SMS,
phoneNumber: '+15551234567'
});
// Verify OTP and complete MFA setup
await client.mfa.verify({
userId: '[email protected]',
sessionId: result.session_id,
otp: '123456'
});
// Get user credentials
const creds = await client.users.getCredentials('[email protected]');
console.log(`MFA method: ${creds.mfa_method}`);Configuration
Environment Variables
For OAuth Code Exchange:
# Config ID (public identifier)
HAWCX_API_KEY="your-config-id"
# Optional base URL override
HAWCX_BASE_URL="https://api.hawcx.com"For Delegation (MFA setup / management):
# Credential blob from the Hawcx dashboard
HAWCX_SECRET_KEY="hwx_sk_v1_..."Error Handling
import {
HawcxOAuth,
TokenExchangeError,
TokenVerificationError
} from '@hawcx/oauth-client';
const oauth = new HawcxOAuth({ configId: process.env.HAWCX_API_KEY! });
try {
const { claims } = await oauth.exchangeCode(authCode, codeVerifier);
} catch (error) {
if (error instanceof TokenExchangeError) {
console.error('Exchange failed:', error.message);
} else if (error instanceof TokenVerificationError) {
console.error('Verification failed:', error.message);
} else {
throw error;
}
}Integration Examples
Express.js
import express, { Request, Response } from 'express';
import { HawcxOAuth } from '@hawcx/oauth-client';
const app = express();
app.use(express.json());
const oauth = new HawcxOAuth({ configId: process.env.HAWCX_API_KEY! });
app.post('/exchange', async (req: Request, res: Response) => {
const { authCode, codeVerifier } = req.body;
if (!authCode || !codeVerifier) {
return res.status(400).json({ error: 'Missing authCode or codeVerifier' });
}
try {
const { claims } = await oauth.exchangeCode(authCode, codeVerifier);
// Create user session
req.session.userId = claims.sub;
req.session.email = claims.email;
res.json({ success: true, userId: claims.sub });
} catch (error) {
console.error('Authentication failed:', error);
res.status(401).json({ error: 'Authentication failed' });
}
});
app.listen(3000, () => console.log('Server running on port 3000'));Fastify
import Fastify, { FastifyRequest, FastifyReply } from 'fastify';
import { HawcxOAuth } from '@hawcx/oauth-client';
const app = Fastify();
const oauth = new HawcxOAuth({ configId: process.env.HAWCX_API_KEY! });
app.post<{ Body: { authCode: string; codeVerifier: string } }>(
'/exchange',
async (request: FastifyRequest, reply: FastifyReply) => {
const { authCode, codeVerifier } = request.body;
try {
const { claims } = await oauth.exchangeCode(authCode, codeVerifier);
reply.send({ success: true, userId: claims.sub });
} catch (error) {
reply.status(401).send({ error: 'Authentication failed' });
}
}
);
app.listen({ port: 3000 }, (err) => {
if (err) throw err;
console.log('Server running on port 3000');
});PKCE Support
codeVerifier is required for the exchange. Store it on the client and send it alongside authCode when your backend calls exchangeCode().
Next Steps
- View the complete API reference for advanced features and detailed method signatures
- Set up MFA management for your users
- Join our developer community on Slack for support and updates