Now.js Framework Documentation

Now.js Framework Documentation

SecurityManager

EN 04 Sep 2026 01:40

SecurityManager

Overview

SecurityManager is the security management system in Now.js Framework. It supports CSRF, JWT, Rate Limiting, and Content Security Policy.

When to use:

  • Need to prevent CSRF attacks
  • Need to manage JWT tokens
  • Need rate limiting
  • Need input sanitization
  • Need CSP management

Why use it:

  • ✅ CSRF protection (token-based)
  • ✅ JWT management (validate, refresh)
  • ✅ Rate limiting (per endpoint)
  • ✅ Input sanitization (XSS prevention)
  • ✅ Content Security Policy
  • ✅ HTTP interceptors
  • ✅ Form protection

Basic Usage

Initialization

await SecurityManager.init({
  csrf: {
    enabled: true,
    tokenName: '_token',
    headerName: 'X-CSRF-Token'
  },
  jwt: {
    enabled: true,
    storageName: 'auth_token',
    autoRefresh: true
  },
  rateLimit: {
    enabled: true,
    globalLimit: 100,
    windowMs: 15 * 60 * 1000 // 15 minutes
  }
});

CSRF Protection

Auto-inject in Forms

<form action="/api/submit" method="POST">
  <!-- CSRF token will be injected automatically -->
  <input type="text" name="email">
  <button type="submit">Submit</button>
</form>

Get CSRF Token

const token = SecurityManager.getCSRFToken();
console.log(token); // 'abc123...'

Manual CSRF in Requests

// SecurityManager will auto-inject in ApiService
await ApiService.post('/api/data', {
  name: 'John'
});
// Request will have X-CSRF-Token header automatically

Refresh CSRF Token

await SecurityManager.refreshCSRFToken();

JWT Management

Get JWT Token

const token = SecurityManager.getJWTToken();

Validate Token

const isValid = SecurityManager.validateJWTToken(token);
if (!isValid) {
  // Token expired or invalid
  redirectToLogin();
}

Refresh Token

await SecurityManager.refreshJWTToken();

Clear Token (Logout)

SecurityManager.clearJWTToken();

Auto-refresh Token

SecurityManager.init({
  jwt: {
    enabled: true,
    autoRefresh: true,
    refreshThreshold: 5 * 60 * 1000 // Refresh 5 mins before expiry
  }
});

Rate Limiting

Check Rate Limit

const result = SecurityManager.checkRateLimit('/api/login');

if (!result.allowed) {
  console.log(`Rate limited. Retry after ${result.retryAfter}ms`);
}

Per-Endpoint Limits

SecurityManager.init({
  rateLimit: {
    enabled: true,
    globalLimit: 100,
    perEndpoint: {
      '/api/login': { limit: 5, windowMs: 60000 },    // 5 per minute
      '/api/register': { limit: 3, windowMs: 60000 }, // 3 per minute
      '/api/upload': { limit: 10, windowMs: 300000 }  // 10 per 5 minutes
    }
  }
});

Input Sanitization

Sanitize Input

// Prevent XSS
const safeInput = SecurityManager.sanitizeInput(userInput);
// '<script>alert("xss")</script>' => '&lt;script&gt;alert("xss")&lt;/script&gt;'

Sanitize Object

const safeData = SecurityManager.sanitizeRequestData({
  name: '<script>alert("xss")</script>',
  email: 'user@example.com'
});
// { name: '&lt;script&gt;...', email: 'user@example.com' }

Content Security Policy

CSP Configuration

SecurityManager.init({
  csp: {
    enabled: true,
    directives: {
      'default-src': ["'self'"],
      'script-src': ["'self'", "'unsafe-inline'"],
      'style-src': ["'self'", "'unsafe-inline'"],
      'img-src': ["'self'", "data:", "https:"],
      'connect-src': ["'self'"],
      'frame-src': ["'none'"],
      'object-src': ["'none'"]
    }
  }
});

CSP Violation Reporting

SecurityManager.init({
  csp: {
    enabled: true,
    reportUri: '/api/csp-report'
  }
});

// Listen for violations
EventManager.on('csp:violation', (violation) => {
  console.log('CSP Violation:', violation);
});

Configuration

await SecurityManager.init({
  // CSRF
  csrf: {
    enabled: true,
    tokenName: '_token',
    headerName: 'X-CSRF-Token',
    cookieName: 'XSRF-TOKEN',
    tokenUrl: '/api/auth/csrf-token',
    autoRefresh: true,
    refreshInterval: 30 * 60 * 1000 // 30 minutes
  },

  // JWT
  jwt: {
    enabled: true,
    cookieName: 'auth_token',
    refreshCookieName: 'refresh_token',
    storageKey: 'auth_jwt',              // see the note below
    autoRefresh: true,
    refreshBeforeExpiry: 5 * 60 * 1000,  // 5 minutes
    refreshEndpoint: 'api/auth/refresh',
    validateSignature: true,
    algorithm: 'HS256',
    issuer: window.location.hostname,
    audience: window.location.hostname
  },

  // Rate Limiting
  rateLimit: {
    enabled: true,
    storage: 'memory',
    globalLimit: 100,
    windowMs: 15 * 60 * 1000,
    perEndpoint: {}
  },

  // CSP
  csp: {
    enabled: false,
    directives: {}
  }
});

jwt.storageKey must not collide with AuthManager's token.storageKey.
The default is 'auth_jwt', and it holds a JWT string. AuthManager
stores the user profile (a JSON object) under 'auth_user'. Both used to
default to 'auth_user': initJWT() then read the profile, failed to
validate it as a JWT, and clearJWTToken() deleted it on every page load — so
the cached profile never survived and the app could not start while offline.
If your app writes a JWT to 'auth_user' itself, move it to 'auth_jwt'
(or set storageKey to a third key of your own) when upgrading. In the usual
setup the real tokens are httpOnly cookies, so this key is rarely used at all.

API Reference

CSRF Methods

SecurityManager.getCSRFToken()

Get current CSRF token

Returns: string|null

SecurityManager.refreshCSRFToken()

Refresh CSRF token from server

Returns: Promise<string>

SecurityManager.injectCSRFIntoForm(form, token?)

Inject CSRF token into form

Parameter Type Description
form HTMLFormElement Form element

JWT Methods

SecurityManager.getJWTToken()

Get JWT token

Returns: string|null

SecurityManager.validateJWTToken(token)

Validate JWT token

Parameter Type Description
token string JWT token

Returns: boolean

SecurityManager.refreshJWTToken()

Refresh JWT token

Returns: Promise<string>

SecurityManager.clearJWTToken()

Clear JWT token (logout)

Rate Limit Methods

SecurityManager.checkRateLimit(endpoint, identifier?)

Check rate limit

Parameter Type Description
endpoint string API endpoint
identifier string User identifier (optional)

Returns: Object:

{
  allowed: boolean,
  remaining: number,
  resetTime: number,
  retryAfter: number
}

Sanitization Methods

SecurityManager.sanitizeInput(value)

Sanitize input string

Parameter Type Description
value string Input value

Returns: string - Sanitized value

SecurityManager.sanitizeRequestData(data)

Sanitize object/array recursively

Parameter Type Description
data object/array Data to sanitize

Returns: object/array - Sanitized data

Data Attributes

Attribute Description
data-csrf On a <form>: set false or disabled to skip CSRF injection for it

Events

Event When Triggered Detail
security:initialized init() completed {csrf, jwt}
csrf:refreshed A new CSRF token was obtained {token}
csrf:retry CSRF rejected (419), giving callers a chance to resend {token}
jwt:refreshed A new JWT was obtained {token}
jwt:cleared The stored JWT was dropped none
csp:violation The browser reported a CSP violation {directive, uri, source, line, timestamp} (sent directly, not wrapped)
security:error A security error occurred {message, error}
security:destroyed destroy() completed none

Real-World Examples

Protected API Calls

// SecurityManager will auto-inject headers
async function saveProfile(data) {
  try {
    // CSRF and JWT headers will be added automatically
    await ApiService.put('/api/profile', data);
    NotificationManager.success('Saved');
  } catch (error) {
    if (error.status === 419) {
      // CSRF token expired
      await SecurityManager.refreshCSRFToken();
      // Retry
      return saveProfile(data);
    }
    throw error;
  }
}

Login with Rate Limiting

async function login(email, password) {
  // Check rate limit
  const limit = SecurityManager.checkRateLimit('/api/login');
  if (!limit.allowed) {
    throw new Error(`Try again in ${Math.ceil(limit.retryAfter / 1000)} seconds`);
  }

  const response = await ApiService.post('/api/login', {
    email: SecurityManager.sanitizeInput(email),
    password
  });

  return response;
}

Form with CSRF Protection

<form id="contact-form" action="/api/contact" method="POST" data-security>
  <input type="text" name="name" required>
  <input type="email" name="email" required>
  <textarea name="message" required></textarea>
  <button type="submit">Send Message</button>
</form>

<script>
// SecurityManager will:
// 1. Inject CSRF token
// 2. Sanitize inputs
// 3. Check rate limit
// ... automatically
</script>

Common Pitfalls

⚠️ 1. Enable CSRF for Production

// ❌ CSRF disabled in production
SecurityManager.init({ csrf: { enabled: false } });

// ✅ Enable CSRF
SecurityManager.init({ csrf: { enabled: true } });

⚠️ 2. JWT Token in Memory

// ❌ Don't store JWT in localStorage for sensitive data
jwt: { storageType: 'localStorage' }

// ✅ Use memory or httpOnly cookie
jwt: { storageType: 'memory' }

⚠️ 3. Sanitize User Input

// ❌ Using user input directly
element.innerHTML = userInput;

// ✅ Sanitize first
element.innerHTML = SecurityManager.sanitizeInput(userInput);

// Or use textContent
element.textContent = userInput;