Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/workos/workos-node/llms.txt

Use this file to discover all available pages before exploring further.

This guide covers implementing authentication flows using the WorkOS User Management API, including password authentication, magic links, MFA, and session management.

Prerequisites

npm install @workos-inc/node
import { WorkOS } from '@workos-inc/node';

const workos = new WorkOS(process.env.WORKOS_API_KEY, {
  clientId: process.env.WORKOS_CLIENT_ID
});

Password Authentication

1

Create a User

Create a user with email and password:
const user = await workos.userManagement.createUser({
  email: 'user@example.com',
  password: 'secure-password',
  firstName: 'John',
  lastName: 'Doe',
  emailVerified: false
});

console.log(user.id);           // user_123
console.log(user.email);        // user@example.com
console.log(user.emailVerified); // false
2

Authenticate with Password

Authenticate users with their email and password:
const { user, accessToken, refreshToken } = 
  await workos.userManagement.authenticateWithPassword({
    clientId: process.env.WORKOS_CLIENT_ID,
    email: 'user@example.com',
    password: 'secure-password'
  });

console.log('Logged in:', user.email);
console.log('Access token:', accessToken);
3

Handle Session Cookies

Seal session data in encrypted cookies:
const response = await workos.userManagement.authenticateWithPassword({
  clientId: process.env.WORKOS_CLIENT_ID,
  email: 'user@example.com',
  password: 'secure-password',
  session: {
    sealSession: true,
    cookiePassword: process.env.COOKIE_PASSWORD // 32+ character secret
  }
});

// Set the encrypted session cookie
res.cookie('wos-session', response.sealedSession, {
  httpOnly: true,
  secure: true,
  sameSite: 'lax',
  maxAge: 7 * 24 * 60 * 60 * 1000 // 7 days
});
4

Verify Session Cookies

Authenticate requests using session cookies:
const session = await workos.userManagement.authenticateWithSessionCookie({
  sessionData: req.cookies['wos-session'],
  cookiePassword: process.env.COOKIE_PASSWORD
});

if (session.authenticated) {
  console.log('User:', session.user.email);
  console.log('Session ID:', session.sessionId);
  console.log('Organization:', session.organizationId);
  console.log('Permissions:', session.permissions);
} else {
  console.log('Invalid session:', session.reason);
}
1

Create a Magic Auth Link

Generate a magic authentication link:
const magicAuth = await workos.userManagement.createMagicAuth({
  email: 'user@example.com',
  invitationToken: 'optional_invitation_token'
});

console.log(magicAuth.id);    // magic_auth_123
console.log(magicAuth.code);  // Secret code for email
console.log(magicAuth.email); // user@example.com

// Send magicAuth.code via email to the user
2

Authenticate with Magic Auth Code

Verify the code when user clicks the link:
const { user, accessToken } = 
  await workos.userManagement.authenticateWithMagicAuth({
    clientId: process.env.WORKOS_CLIENT_ID,
    code: '123456',
    email: 'user@example.com'
  });

console.log('User authenticated:', user.email);

OAuth 2.0 Flow

1

Generate Authorization URL

Redirect users to the WorkOS authentication page:
const authorizationUrl = workos.userManagement.getAuthorizationUrl({
  provider: 'authkit',
  clientId: process.env.WORKOS_CLIENT_ID,
  redirectUri: 'http://localhost:3000/callback',
  state: 'random-state'
});

res.redirect(authorizationUrl);
For public clients, use automatic PKCE:
const { url, state, codeVerifier } = 
  await workos.userManagement.getAuthorizationUrlWithPKCE({
    provider: 'authkit',
    clientId: process.env.WORKOS_CLIENT_ID,
    redirectUri: 'myapp://callback'
  });

// Store state and codeVerifier securely
2

Exchange Authorization Code

Exchange the authorization code for tokens:
const { user, accessToken, refreshToken } = 
  await workos.userManagement.authenticateWithCode({
    clientId: process.env.WORKOS_CLIENT_ID,
    code: req.query.code as string
  });

// For public clients with PKCE:
const result = await workos.userManagement.authenticateWithCode({
  clientId: process.env.WORKOS_CLIENT_ID,
  code: req.query.code as string,
  codeVerifier: storedCodeVerifier
});
3

Refresh Access Tokens

Use refresh tokens to get new access tokens:
const { accessToken, refreshToken } = 
  await workos.userManagement.authenticateWithRefreshToken({
    clientId: process.env.WORKOS_CLIENT_ID,
    refreshToken: storedRefreshToken
  });

console.log('New access token:', accessToken);

Multi-Factor Authentication

1

Enroll TOTP Factor

Enroll users in TOTP-based MFA:
const { authenticationFactor, authenticationChallenge } = 
  await workos.userManagement.enrollAuthFactor({
    userId: 'user_123',
    type: 'totp'
  });

// Display authenticationFactor.totp.qrCode to user
console.log('QR Code:', authenticationFactor.totp?.qrCode);
console.log('Secret:', authenticationFactor.totp?.secret);
2

Verify TOTP Code

After initial password authentication, verify the TOTP code:
// First authenticate with password
const passwordAuth = await workos.userManagement.authenticateWithPassword({
  clientId: process.env.WORKOS_CLIENT_ID,
  email: 'user@example.com',
  password: 'secure-password'
});

// User is prompted for MFA
if (passwordAuth.authenticationMethod === 'Password') {
  // Verify TOTP code
  const { user, accessToken } = 
    await workos.userManagement.authenticateWithTotp({
      clientId: process.env.WORKOS_CLIENT_ID,
      code: '123456',
      authenticationChallengeId: passwordAuth.authenticationChallengeId,
      pendingAuthenticationToken: passwordAuth.pendingAuthenticationToken
    });

  console.log('MFA verified:', user.email);
}
3

List Authentication Factors

View all enrolled MFA factors for a user:
const factors = await workos.userManagement.listAuthFactors({
  userId: 'user_123'
});

for await (const factor of factors.autoPagination()) {
  console.log(factor.id, factor.type, factor.totp);
}

Email Verification

1

Send Verification Email

Send a verification email to a user:
const { user } = await workos.userManagement.sendVerificationEmail({
  userId: 'user_123'
});

console.log('Verification sent to:', user.email);
2

Verify Email with Code

Complete email verification:
const { user } = await workos.userManagement.verifyEmail({
  userId: 'user_123',
  code: '123456'
});

console.log('Email verified:', user.emailVerified);
3

Authenticate with Email Verification

Complete authentication after email verification:
const { user, accessToken } = 
  await workos.userManagement.authenticateWithEmailVerification({
    clientId: process.env.WORKOS_CLIENT_ID,
    code: '123456',
    pendingAuthenticationToken: 'pending_token'
  });

Password Reset

1

Create Password Reset

Generate a password reset token:
const passwordReset = await workos.userManagement.createPasswordReset({
  email: 'user@example.com'
});

console.log('Reset token:', passwordReset.passwordResetToken);
console.log('Reset URL:', passwordReset.passwordResetUrl);

// Send passwordReset.passwordResetUrl via email
2

Complete Password Reset

Reset the password with the token:
const { user } = await workos.userManagement.resetPassword({
  token: 'password_reset_token',
  newPassword: 'new-secure-password'
});

console.log('Password reset for:', user.email);

Managing Users

Get User

const user = await workos.userManagement.getUser('user_123');

console.log(user.email);
console.log(user.firstName);
console.log(user.emailVerified);
console.log(user.createdAt);

List Users

const users = await workos.userManagement.listUsers({
  email: 'user@example.com',
  organizationId: 'org_123',
  limit: 10
});

for await (const user of users.autoPagination()) {
  console.log(user.email);
}

Update User

const user = await workos.userManagement.updateUser({
  userId: 'user_123',
  firstName: 'Jane',
  lastName: 'Smith',
  emailVerified: true
});

Delete User

await workos.userManagement.deleteUser('user_123');

Session Management

List User Sessions

const sessions = await workos.userManagement.listSessions('user_123');

for await (const session of sessions.autoPagination()) {
  console.log(session.id, session.ipAddress);
}

Revoke Session

await workos.userManagement.revokeSession({
  sessionId: 'session_123'
});

Get Logout URL

const logoutUrl = workos.userManagement.getLogoutUrl({
  sessionId: 'session_123',
  returnTo: 'https://yourapp.com'
});

res.redirect(logoutUrl);

Complete Authentication Example

import { WorkOS } from '@workos-inc/node';
import express from 'express';
import cookieParser from 'cookie-parser';

const workos = new WorkOS(process.env.WORKOS_API_KEY, {
  clientId: process.env.WORKOS_CLIENT_ID
});

const app = express();
app.use(express.json());
app.use(cookieParser());

// Login endpoint
app.post('/login', async (req, res) => {
  try {
    const { user, sealedSession } = 
      await workos.userManagement.authenticateWithPassword({
        clientId: process.env.WORKOS_CLIENT_ID,
        email: req.body.email,
        password: req.body.password,
        session: {
          sealSession: true,
          cookiePassword: process.env.COOKIE_PASSWORD
        }
      });

    res.cookie('wos-session', sealedSession, {
      httpOnly: true,
      secure: true,
      sameSite: 'lax'
    });

    res.json({ user });
  } catch (error) {
    res.status(401).json({ error: 'Authentication failed' });
  }
});

// Protected route
app.get('/profile', async (req, res) => {
  const session = await workos.userManagement.authenticateWithSessionCookie({
    sessionData: req.cookies['wos-session'],
    cookiePassword: process.env.COOKIE_PASSWORD
  });

  if (!session.authenticated) {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  res.json({ user: session.user });
});

// Logout endpoint
app.post('/logout', async (req, res) => {
  const session = await workos.userManagement.getSessionFromCookie({
    sessionData: req.cookies['wos-session'],
    cookiePassword: process.env.COOKIE_PASSWORD
  });

  if (session) {
    await workos.userManagement.revokeSession({
      sessionId: session.sessionId
    });
  }

  res.clearCookie('wos-session');
  res.json({ success: true });
});

app.listen(3000);