Skip to main content

Configuration

Complete guide to configuring @nauth-toolkit/client for your application.

Basic Configuration

import { NAuthClient } from '@nauth-toolkit/client';

const client = new NAuthClient({
baseUrl: 'https://api.example.com/auth',
tokenDelivery: 'cookies',
onSessionExpired: () => {
window.location.replace('/login');
},
});

See NAuthClientConfig for complete interface.

Required Options

OptionTypeDescription
baseUrlstringBackend auth API URL
tokenDelivery'json' | 'cookies'Token delivery mode (must match backend). See Token Management
onSessionExpired() => voidCallback when session expires

See NAuthClientConfig for all options.

Token Delivery Modes

Cookies (Web Applications)

{
baseUrl: 'https://api.example.com/auth',
tokenDelivery: 'cookies',
}
  • Tokens stored in HTTP-only cookies (server-managed)
  • Automatic CSRF protection required
  • Interceptor adds withCredentials: true
  • Most secure option for web browsers

JSON (Mobile/Native Apps)

{
baseUrl: 'https://api.example.com/mobile/auth', // Different endpoint for mobile
tokenDelivery: 'json',
}
  • Tokens returned in response body
  • Stored in provided storage adapter (secure storage recommended)
  • Interceptor adds Authorization: Bearer header
  • Required for Capacitor, React Native, etc.
Hybrid Backend Deployment

When your backend supports both web and mobile apps (hybrid deployment), it exposes separate endpoints for each delivery mode:

  • Web (cookies): /auth/*
  • Mobile (JSON): /mobile/auth/*

The frontend chooses ONE mode based on the platform and uses the appropriate baseUrl. See Token Delivery for backend setup.

CSRF Configuration

Required for cookies mode:

{
tokenDelivery: 'cookies',
csrf: {
cookieName: 'nauth_csrf_token', // Default
headerName: 'x-csrf-token', // Default
},
}

The interceptor automatically:

  1. Reads CSRF token from cookie
  2. Attaches to POST, PUT, PATCH, DELETE requests
warning

CSRF cookie and header names must match your backend configuration.

reCAPTCHA Configuration

When your backend enforces reCAPTCHA (e.g., for login/signup), configure the client to send tokens:

{
baseUrl: 'https://api.example.com/auth',
tokenDelivery: 'cookies',
recaptcha: {
enabled: true,
version: 'enterprise', // 'v2' | 'v3' | 'enterprise' - must match backend
siteKey: '6Le...your-site-key',
action: 'submit', // Optional: fallback action. Angular SDK auto-passes 'login'/'signup' per-endpoint.
autoLoadScript: true, // Optional: preload script at startup (default: true for v3/Enterprise)
},
}
  • Angular: Use provideRecaptcha({ enabled, version, siteKey }) from @nauth-toolkit/client-angular in addition to recaptcha in NAUTH_CLIENT_CONFIG. The SDK auto-generates and attaches tokens for v3/Enterprise, using 'login' and 'signup' as the action for their respective API calls.
  • Vanilla/React/Vue: Load the reCAPTCHA script, call grecaptcha.execute() (or grecaptcha.enterprise.execute() for Enterprise) before login/signup, and pass the token to client.login() / client.signup().

See reCAPTCHA Guide and NAuthClientConfig for full options.

Custom Storage

By default, uses localStorage in browser. Provide custom adapter for:

  • Mobile apps (Capacitor, React Native)
  • SSR (in-memory or server-side storage)
  • Session storage
import { NAuthClient, InMemoryStorage, BrowserStorage } from '@nauth-toolkit/client';

// Session storage instead of local storage
const client = new NAuthClient({
baseUrl: 'https://api.example.com/auth',
tokenDelivery: 'json',
storage: new BrowserStorage(window.sessionStorage),
onSessionExpired: () => {},
});

// In-memory for SSR
const ssrClient = new NAuthClient({
baseUrl: 'https://api.example.com/auth',
tokenDelivery: 'json',
storage: new InMemoryStorage(),
onSessionExpired: () => {},
});

See NAuthClientConfig for storage adapters.

Custom Storage Adapter

import { NAuthStorageAdapter } from '@nauth-toolkit/client';
import { Preferences } from '@capacitor/preferences';

class CapacitorStorage implements NAuthStorageAdapter {
async getItem(key: string): Promise<string | null> {
const { value } = await Preferences.get({ key });
return value;
}

async setItem(key: string, value: string): Promise<void> {
await Preferences.set({ key, value });
}

async removeItem(key: string): Promise<void> {
await Preferences.remove({ key });
}

async clear(): Promise<void> {
await Preferences.clear();
}
}

const client = new NAuthClient({
baseUrl: 'https://api.example.com/auth',
tokenDelivery: 'json',
storage: new CapacitorStorage(),
onSessionExpired: () => {},
});

Callbacks

onAuthResponse

Custom handler for all authentication responses. Overrides automatic navigation. Perfect for dialog-based flows:

{
onAuthResponse: (response, context) => {
// context.source: 'login' | 'signup' | 'social' | 'challenge'

if (response.challengeName) {
// Handle challenge (dialog, modal, or custom navigation)
dialog.open(ChallengeComponent, {
data: { challenge: response, source: context.source }
});
} else if (response.user) {
// Authentication complete
router.navigate(['/dashboard']);
}
},
}

When to use:

  • Dialog/modal-based challenge flows
  • Custom navigation logic
  • Complex UI state management
note

When onAuthResponse is provided, the SDK skips automatic navigation. You control all routing.

Custom navigation function. Use your framework's router instead of window.location:

{
navigationHandler: (url: string) => {
// Angular
inject(Router).navigateByUrl(url);

// React Router
navigate(url);

// Vue Router
router.push(url);
},
}

Default behavior:

  • Guards: window.location.replace(url)
  • Other contexts: window.location.href = url

onSessionExpired

Called when refresh fails (401 after refresh attempt):

{
onSessionExpired: () => {
// Clear app state
appState.reset();
// Redirect to login
window.location.replace('/login');
},
}

onAuthStateChange

Called when auth state changes (login, logout, token refresh):

{
onAuthStateChange: (user) => {
if (user) {
analytics.identify(user.sub);
} else {
analytics.reset();
}
},
}

onTokenRefresh

Called after successful token refresh:

{
onTokenRefresh: () => {
console.log('Tokens refreshed at', new Date());
},
}

onError

Global error handler:

{
onError: (error) => {
// Log to monitoring service
Sentry.captureException(error);

// Handle specific errors
if (error.code === 'NETWORK_ERROR') {
showToast('Network error. Please check your connection.');
}
},
}

Custom Endpoints

Override default endpoint paths:

{
baseUrl: 'https://api.example.com/auth',
tokenDelivery: 'cookies',
endpoints: {
login: '/signin',
signup: '/register',
logout: '/signout',
refresh: '/token/refresh',
profile: '/me',
},
onSessionExpired: () => {},
}

All Available Endpoints

Backend Implementation Required

To override or customize API endpoint paths, your backend must implement these endpoints according to the NAuth specification. Otherwise, authentication flows will fail. all endpoint paths listed below should be present and correctly handle the expected request/response formats.

See the API Reference for type requirements.

KeyDefaultDescription
login/loginLogin endpoint
signup/signupSignup endpoint
logout/logoutLogout endpoint
logoutAll/logout/allLogout all sessions
refresh/refreshToken refresh
respondChallenge/respond-challengeChallenge response
resendCode/challenge/resendResend verification code
getSetupData/challenge/setup-dataMFA setup data
getChallengeData/challenge/challenge-dataChallenge data
profile/profileGet profile
updateProfile/profileUpdate profile
changePassword/change-passwordChange password
mfaStatus/mfa/statusMFA status
mfaDevices/mfa/devicesMFA devices
mfaSetupData/mfa/setup-dataMFA setup
mfaVerifySetup/mfa/verify-setupVerify MFA setup
mfaRemove/mfa/removeRemove MFA device
mfaPreferred/mfa/preferredSet preferred MFA
mfaBackupCodes/mfa/backup-codesGenerate backup codes
socialRedirectStart/social/:provider/redirectStart web social login redirect
socialExchange/social/exchangeExchange exchangeToken (json/hybrid or cookies-with-challenge)
socialVerify/social/:provider/verifyVerify native social
socialLinked/social/linkedLinked accounts
socialLink/social/linkLink account
socialUnlink/social/unlinkUnlink account
trustDevice/trust-deviceTrust device
auditHistory/audit/historyAudit history

Device Trust

Configure device trust header:

{
deviceTrust: {
headerName: 'x-device-token', // Default
storageKey: 'nauth_device_token', // Default
},
}

Custom Headers

Add headers to all requests:

{
headers: {
'X-App-Version': '1.0.0',
'X-Platform': 'web',
},
}

Request Timeout

Set request timeout in milliseconds:

{
timeout: 30000, // 30 seconds
}

Debug Mode

Enable debug logging:

{
debug: process.env.NODE_ENV === 'development',
}

Full Configuration Example

import { AuthChallenge } from '@nauth-toolkit/client';

const client = new NAuthClient({
// Required
baseUrl: 'https://api.example.com/auth',
tokenDelivery: 'cookies',

// Challenge navigation
redirects: {
loginSuccess: '/dashboard',
signupSuccess: '/onboarding',
sessionExpired: '/login',
oauthError: '/login',
challengeBase: '/auth/challenge',

// Optional: Custom routes
challengeRoutes: {
[AuthChallenge.MFA_REQUIRED]: '/auth/mfa',
},

// Optional: Single route mode
// useSingleChallengeRoute: true,

// Optional: MFA-specific routes
mfaRoutes: {
passkey: '/auth/passkey',
selector: '/auth/choose-mfa',
default: '/auth/verify-code',
},
},

// Optional: Custom navigation
navigationHandler: (url) => inject(Router).navigateByUrl(url),

// Optional: Dialog-based flow
// onAuthResponse: (response, context) => {
// if (response.challengeName) {
// dialog.open(ChallengeComponent, { data: response });
// }
// },

// CSRF (for cookies mode)
csrf: {
cookieName: 'nauth_csrf_token',
headerName: 'x-csrf-token',
},

// Callbacks
onAuthStateChange: (user) => {
if (user) analytics.identify(user.sub);
},
onTokenRefresh: () => console.log('Tokens refreshed'),
onError: (error) => Sentry.captureException(error),

// Device trust
deviceTrust: {
headerName: 'x-device-token',
storageKey: 'nauth_device',
},

// Custom headers
headers: {
'X-App-Version': APP_VERSION,
},

// Timeout
timeout: 30000,

// Debug
debug: isDevelopment,
});

Redirects and Auto-Navigation

The SDK can automatically navigate after authentication and on certain error conditions using redirects.

  • redirects.loginSuccess: where to navigate after successful login/social (no challenge)
  • redirects.signupSuccess: where to navigate after successful signup (no challenge)
  • Legacy: redirects.success is a deprecated alias for loginSuccess

Disable auto-navigation (events-only routing)

If you want to do all routing manually (for example in Angular by subscribing to authEvents$), set the redirect to null.

redirects: {
loginSuccess: null,
signupSuccess: null,
oauthError: null,
sessionExpired: null,
}

Notes:

  • Use null to disable. Leaving a key undefined/omitted means “not set” and falls back to defaults.
  • Challenge routing (MFA, verify-email, etc.) is controlled by challengeBase, challengeRoutes, mfaRoutes, and useSingleChallengeRoute.