Now.js Framework Documentation
AuthManager
AuthManager
Overview
AuthManager is the authentication management system in Now.js Framework. It supports JWT, session, and OAuth flows.
When to use:
- Need login/logout
- Need JWT authentication
- Need role-based access control
- Need auto token refresh
Why use it:
- ✅ Multiple auth strategies (JWT, session)
- ✅ Automatic token refresh
- ✅ Rate limiting
- ✅ Permission/role checking
- ✅ HTTP interceptors
- ✅ Security integration
Basic Usage
Initialization
await AuthManager.init({
enabled: true,
type: 'jwt-httponly',
endpoints: {
login: '/api/auth/login',
logout: '/api/auth/logout',
refresh: '/api/auth/refresh',
user: '/api/auth/user'
}
});Login
try {
await AuthManager.login({
email: 'user@example.com',
password: 'password123'
});
console.log('Logged in as:', AuthManager.getUser());
} catch (error) {
console.error('Login failed:', error.message);
}Logout
await AuthManager.logout();Configuration
AuthManager.init({
enabled: true,
// Auth type: 'jwt', 'jwt-httponly', 'session'
type: 'jwt-httponly',
autoInit: true,
endpoints: {
login: '/api/auth/login',
logout: '/api/auth/logout',
refresh: '/api/auth/refresh',
user: '/api/auth/user'
},
token: {
// Storage: 'localStorage', 'sessionStorage', 'cookie'
storage: 'cookie',
key: 'auth_token',
refreshKey: 'refresh_token',
expiresKey: 'token_expires'
},
autoRefresh: {
enabled: true,
beforeExpiry: 60 // seconds before expiry
},
redirect: {
afterLogin: '/',
afterLogout: '/login',
onUnauthorized: '/login'
},
rateLimit: {
enabled: true,
maxAttempts: 5,
lockDuration: 300000 // 5 minutes
}
});API Reference
AuthManager.login(credentials, options)
Login user
| Parameter | Type | Description |
|---|---|---|
credentials |
object | {email, password} or custom |
options.redirect |
boolean | Redirect after login |
Returns: Promise<Object> - User data
const user = await AuthManager.login({
email: 'user@example.com',
password: 'password123'
});AuthManager.logout(callServer?, options?)
Logout user
| Parameter | Type | Description |
|---|---|---|
callServer |
boolean | Call logout endpoint (default: true) |
options.redirect |
boolean | Redirect after logout |
await AuthManager.logout();AuthManager.isAuthenticated()
Check authentication status
Returns: boolean
if (AuthManager.isAuthenticated()) {
showProfileMenu();
}AuthManager.getUser()
Get current user data
Returns: Object|null
const user = AuthManager.getUser();
console.log(user.name, user.email);AuthManager.hasRole(role)
Check role
| Parameter | Type | Description |
|---|---|---|
role |
string | Role name |
Returns: boolean
if (AuthManager.hasRole('admin')) {
showAdminPanel();
}AuthManager.hasPermission(permission)
Check permission
| Parameter | Type | Description |
|---|---|---|
permission |
string | Permission name |
Returns: boolean
if (AuthManager.hasPermission('users.edit')) {
showEditButton();
}AuthManager.refreshToken()
Refresh access token
Returns: Promise<boolean>
AuthManager.checkAuthStatus()
Ask the verify endpoint who the current user is, update the session state, and
cache the user profile in local storage for display.
Returns: Promise<Object> — {authenticated, user}, plus offline: true
when the answer came from cache, or error when it failed.
Offline behaviour: a rejection by the server (401/403) clears the session as
before. A server that could not be reached does not: the cached profile is
restored and the result carries offline: true, so a dropped connection no
longer throws the user back to the login page — which would make an
offline-capable app unusable.
const status = await AuthManager.checkAuthStatus();
if (status.authenticated && status.offline) {
// Working from the cached profile; show a "no connection" badge
}Trade-off: if the session is revoked server-side while the device is
offline, the UI keeps showing the user as signed in until it is back online.
Nothing can be read or written in that state, because every API call is still
authorised by the server as usual — only the screen is stale. The next
successful verify clears the session.
AuthManager.isUnreachable(response)
Tell "the server could not be reached" apart from "the server said no".
simpleFetch returns status 0 when the fetch itself fails (offline, DNS
failure and the like) and 408 on timeout; a genuine rejection always carries
its own HTTP status. navigator.onLine === false also counts as unreachable.
| Parameter | Type | Description |
|---|---|---|
response |
Object | Result of simpleFetch |
Returns: boolean
AuthManager.restoreCachedUser()
Return the cached user profile and mark the session authenticated again.
Used only when the server could not be reached — never to skip a real
verification. Returns null when there is no usable cached profile, in which
case the caller must fall back to clearing the session.
Returns: Object|null
AuthManager.requireAuth()
Redirect if not authenticated
// Route guard
AuthManager.requireAuth();AuthManager.requireGuest()
Redirect if authenticated
// Login page guard
AuthManager.requireGuest();Events
| Event | When Triggered | Detail |
|---|---|---|
auth:initialized |
init() completed | {authenticated, user} |
auth:login |
Login succeeded | {user, timestamp} |
auth:logout |
Logout succeeded | {timestamp} |
auth:restored |
Impersonation ended, original admin restored | {user, timestamp} |
auth:token_refreshed |
Session refreshed successfully | {user, token, timestamp} |
auth:social_login_start |
Social login started | {provider} |
auth:error |
An auth error occurred | {message, error, timestamp} |
EventManager.on('auth:login', (data) => {
console.log('User logged in:', data.user);
});
EventManager.on('auth:logout', () => {
// Clear app state
StateManager.reset();
});Real-World Examples
Login Form
<form id="login-form">
<input type="email" name="email" required>
<input type="password" name="password" required>
<button type="submit">Login</button>
</form>
<script>
document.getElementById('login-form').onsubmit = async (e) => {
e.preventDefault();
const form = e.target;
try {
await AuthManager.login({
email: form.email.value,
password: form.password.value
});
// Redirect to intended or dashboard
RedirectManager.afterLogin();
} catch (error) {
NotificationManager.error(error.message);
}
};
</script>Protected Route
// Router middleware
RouterManager.beforeEach((to, from, next) => {
const isProtected = to.meta?.requiresAuth;
if (isProtected && !AuthManager.isAuthenticated()) {
AuthManager.saveIntendedUrl(to.path);
AuthManager.requireAuth();
return;
}
next();
});Role-Based UI
<nav>
<a href="/" data-show-if="authenticated">Dashboard</a>
<template data-if="hasRole('admin')">
<a href="/admin">Admin Panel</a>
</template>
<a href="/login" data-hide-if="authenticated">Login</a>
<a href="#" onclick="AuthManager.logout()" data-show-if="authenticated">Logout</a>
</nav>API Request with Auth
// AuthManager auto-attaches token to requests
const response = await ApiService.get('/api/protected-resource');
// Handle auth errors
EventManager.on('auth:error', () => {
AuthManager.requireAuth();
});Common Pitfalls
⚠️ 1. Init Before Use
// ❌ Calling before init
AuthManager.login({...});
// ✅ Init first
await AuthManager.init({ enabled: true });
await AuthManager.login({...});⚠️ 2. Check Auth Status
// ❌ Assuming authenticated without check
showProtectedContent();
// ✅ Check first
if (AuthManager.isAuthenticated()) {
showProtectedContent();
}Related Documentation
- SecurityManager - Security
- RedirectManager - Redirects