Skip to main content

Browser Client — window.AwesomeNodeAuth

awesome-node-auth ships a zero-config browser authentication client as a static asset served at /auth/ui/assets/auth.js.

Include it once in your HTML to get a complete, framework-agnostic auth layer — no npm install, no build step, no configuration required.

<!-- Add to <head> — works with Express, NestJS, Next.js, or any server -->
<script src="/auth/ui/assets/auth.js"></script>

Replace /auth with your actual apiPrefix if different from the default.


What it does automatically

CapabilityDetails
CSRF injectionIntercepts every fetch() call and adds X-CSRF-Token from the csrf-token cookie
Credentials propagationForces credentials: 'include' on all requests so HttpOnly cookies are sent
Token auto-refreshOn any 401 or 403, transparently calls POST /auth/refresh and retries; on failure, calls logout and redirects
apiPrefix auto-detectionDerives the backend base path from the page URL (e.g. /auth at /auth/ui/login) — zero config needed with built-in UI pages

Registered globals

GlobalPurpose
window.AwesomeNodeAuthPublic API — use from any JS/framework
window.AuthServiceInternal helper used by the built-in HTML pages; available for low-level API calls

AwesomeNodeAuth.init(options?) — optional configuration

init() is not required. Call it only if you need to customise paths, lifecycle hooks, or override individual methods.

// Zero config — works out of the box with built-in UI pages
// AwesomeNodeAuth.init() is not required

// Custom prefix + login URL
AwesomeNodeAuth.init({
apiPrefix: '/api/v1/auth',
loginUrl: '/sign-in',
homeUrl: '/dashboard',
});

// Lifecycle hooks for SPA routing (no full-page redirect)
AwesomeNodeAuth.init({
apiPrefix: '/api/auth',
onSessionExpired: () => router.navigate('/login'),
onLogout: () => { clearLocalStorage(); router.navigate('/login'); },
onRefreshFail: () => console.warn('[auth] token refresh failed'),
onRefreshSuccess: (result) => console.debug('[auth] refreshed', result),
});

// Override an individual auth method (e.g. add audit logging)
// Call AuthService.apiCall directly — calling AwesomeNodeAuth.login() here
// would recurse infinitely since this IS the login override.
AwesomeNodeAuth.init({
login: async (email, password) => {
console.log('[audit] login attempt for', email);
return AuthService.apiCall('/login', 'POST', { email, password });
},
});

init() options

OptionTypeDefaultDescription
apiPrefixstringDerived from URLBase path of the auth backend
loginUrlstring{apiPrefix}/ui/loginLogin page URL
homeUrlstring/Redirect target after successful login
siteNamestring'Awesome Node Auth'Site name (used by built-in pages)
onLogoutFunctionAuto-redirect to loginUrlCalled after logout instead of redirect
onSessionExpiredFunctionAuto-redirect to loginUrlCalled when token refresh fails instead of redirect
onRefreshSuccessFunction(result)Called after a successful transparent token refresh
onRefreshFailFunctionAuto-logoutCalled when token refresh fails (before logout fallback)
loginFunctionBuilt-inOverride the login() implementation
logoutFunctionBuilt-inOverride the logout() implementation
registerFunctionBuilt-inOverride the register() implementation
(any method)FunctionBuilt-inAny public method can be overridden the same way

State

AwesomeNodeAuth.isAuthenticated()  // → boolean
AwesomeNodeAuth.isInitialized() // → boolean (true after first checkSession)
AwesomeNodeAuth.getUser() // → user object or null
AwesomeNodeAuth.config // → { apiPrefix, loginUrl, homeUrl, features, ui, … }

Session & route guards

// Verify current session (calls GET /auth/me)
const loggedIn = await AwesomeNodeAuth.checkSession();

// Redirect to login if not authenticated
await AwesomeNodeAuth.guardPage();
await AwesomeNodeAuth.guardPage('/custom-login'); // custom redirect target

// Redirect if user lacks the required role
await AwesomeNodeAuth.guardRole('admin');
await AwesomeNodeAuth.guardRole('editor', '/unauthorized');

Auth methods

Login & register

// Login
const result = await AwesomeNodeAuth.login(email, password);
// result.success → boolean
// result.error → string | undefined
// result.requires2fa → boolean (TOTP/SMS challenge required)
// result.tempToken → string (2FA flow token)
// result.availableMethods → string[] (e.g. ['totp', 'sms'])
// result.requires2FASetup → boolean (first-time 2FA enrollment required)

// Register
await AwesomeNodeAuth.register(email, password, firstName?, lastName?);

// Logout
await AwesomeNodeAuth.logout();

Password management

await AwesomeNodeAuth.forgotPassword(email);
await AwesomeNodeAuth.resetPassword(token, newPassword);
await AwesomeNodeAuth.changePassword(currentPassword, newPassword);
await AwesomeNodeAuth.setPassword(newPassword); // OAuth accounts — no current password needed
await AwesomeNodeAuth.sendMagicLink(email);
await AwesomeNodeAuth.verifyMagicLink(token);

TOTP two-factor authentication

// Enrolment
const { secret, qrCode } = await AwesomeNodeAuth.setup2fa();
await AwesomeNodeAuth.verify2faSetup(code, secret);

// Login challenge (after login returns requires2fa: true)
await AwesomeNodeAuth.validate2fa(tempToken, totpCode);

SMS authentication

// SMS-only login
await AwesomeNodeAuth.sendSmsLogin(email);
await AwesomeNodeAuth.verifySmsLogin(userId, code);

// SMS as 2FA step
await AwesomeNodeAuth.validateSms(tempToken, code);

Email verification

await AwesomeNodeAuth.resendVerificationEmail();
await AwesomeNodeAuth.verifyEmail(token);

Email change

await AwesomeNodeAuth.requestEmailChange(newEmail);
await AwesomeNodeAuth.confirmEmailChange(token);

Account linking

await AwesomeNodeAuth.requestLinkingEmail(email, provider);
await AwesomeNodeAuth.verifyLinkingToken(token, provider);
await AwesomeNodeAuth.verifyConflictLinkingToken(token); // OAuth conflict resolution

const accounts = await AwesomeNodeAuth.getLinkedAccounts(); // → LinkedAccount[]
await AwesomeNodeAuth.unlinkAccount(provider, providerAccountId);

Account deletion

await AwesomeNodeAuth.deleteAccount();

Framework integration examples

Vanilla JS / HTML — no build step required

<script src="/auth/ui/assets/auth.js"></script>
<script>
// Configure once (optional)
AwesomeNodeAuth.init({ homeUrl: '/dashboard' });

document.getElementById('login-form').addEventListener('submit', async (e) => {
e.preventDefault();
const result = await AwesomeNodeAuth.login(
document.getElementById('email').value,
document.getElementById('password').value,
);
if (result.success) {
window.location.href = AwesomeNodeAuth.config.homeUrl;
} else {
showError(result.error);
}
});
</script>

React (without a build step)

<script src="/auth/ui/assets/auth.js"></script>
<script type="module">
// AwesomeNodeAuth is available globally — use it from any module
import { useState } from 'https://esm.sh/react';

export function useAuth() {
const [user, setUser] = useState(AwesomeNodeAuth.getUser());

async function login(email, password) {
const result = await AwesomeNodeAuth.login(email, password);
if (result.success) setUser(AwesomeNodeAuth.getUser());
return result;
}

return { user, login, logout: AwesomeNodeAuth.logout.bind(AwesomeNodeAuth) };
}
</script>

Vue 3 (CDN / no build)

<script src="/auth/ui/assets/auth.js"></script>
<script type="module">
import { createApp, ref } from 'https://esm.sh/vue';

createApp({
setup() {
const user = ref(AwesomeNodeAuth.getUser());

async function login(email, password) {
const result = await AwesomeNodeAuth.login(email, password);
if (result.success) user.value = AwesomeNodeAuth.getUser();
return result;
}

return { user, login };
},
}).mount('#app');
</script>

Next.js / SSR frameworks

Include auth.js in your layout and use the global in any client component:

<!-- app/layout.tsx or _app.tsx — add to <head> -->
<Script src="/auth/ui/assets/auth.js" strategy="beforeInteractive" />
// In a client component
'use client';

await AwesomeNodeAuth.guardPage(); // redirects if not authenticated
const user = AwesomeNodeAuth.getUser(); // user after the last checkSession

SPA with client-side routing (React Router, Vue Router, etc.)

Prevent full-page redirects by providing navigation callbacks via init():

AwesomeNodeAuth.init({
onSessionExpired: () => router.push('/login'),
onLogout: () => {
clearApplicationState();
router.push('/login');
},
});

SSR fast-path (window.__AUTH_CONFIG__)

When using buildUiRouter, the server injects a window.__AUTH_CONFIG__ script block into every HTML page before it is sent to the browser. auth.js reads this at startup and skips the /auth/ui/config fetch — eliminating an extra round-trip and preventing a flash of unstyled content.

This is handled automatically; no action is required.


Angular

Angular has a dedicated library (awesome-node-auth-angular) with Guards, Interceptors, and a typed AuthService — use that instead of auth.js for Angular projects.