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-toolkit 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.