Skip to main content
Version: 🚧 Canary

🔐 Authentication Utilities

The Nodeblocks SDK provides comprehensive authentication utilities for token management, validation, and security. These utilities handle bearer tokens, cookie-based authentication, and various token types for different use cases.


🎯 Overview

Authentication utilities provide secure token generation, validation, and management for both user and application authentication. They support multiple token types and security validation mechanisms.

For service-level configuration (authMode, checkIp, token sign options), see Authentication Service.

Key Features

  • Multiple Token Types: User access, app access, refresh, and one-time tokens
  • Security Validation: Fingerprint, IP, and user agent validation
  • Flexible Authentication: Bearer token and cookie-based authentication
  • Two-Layer Tokens: AES-256-CBC encryption envelope around a signed JWT

Token Format

Tokens use a two-layer format:

  1. Inner layer: A standard JWT signed with authSignSecret (via jsonwebtoken)
  2. Outer layer: AES-256-CBC encryption with a SHA-256-derived key from authEncSecret, stored as iv_hex:ciphertext_hex

Use encrypt / decrypt for the envelope and decryptAndVerifyJWT to decrypt and verify in one step.

Default Token Lifetimes

TokenDefault expiresIn
User access'15m'
Refresh'2d'
One-time'5m'
App accessnone (no default expiry in sign options)

🔑 Token Generation

generateUserAccessToken

Creates encrypted user access tokens with security validation metadata.

import { utils } from '@nodeblocks/backend-sdk';

const { generateUserAccessToken } = utils;

const token = generateUserAccessToken(
authSecrets,
{ expiresIn: '30m' }, // optional; default '15m'
identityId,
{
fingerprint: 'device-fingerprint',
ip: '192.168.1.1',
domain: 'example.com',
userAgent: 'Mozilla/5.0...'
}
);

Parameters:

  • authSecrets: Authentication secrets for encryption/signing
  • jwtSignOptions: Required SignOptions | undefined parameter from jsonwebtoken; pass undefined to use the default expiresIn: '15m'
  • identityId: Identity identifier
  • tokenVerification: Security context for validation

Notes:

  • Generated tokens always have stateful: false (not configurable via this function)

generateAppAccessToken

Creates encrypted app access tokens for service-to-service communication.

import { utils } from '@nodeblocks/backend-sdk';

const { generateAppAccessToken } = utils;

const token = generateAppAccessToken(authSecrets, 'app-service-id');

Parameters:

  • authSecrets: Authentication secrets
  • appId: Application identifier

generateRefreshToken

Creates encrypted refresh tokens for session management.

import { utils } from '@nodeblocks/backend-sdk';

const { generateRefreshToken } = utils;

const token = generateRefreshToken(
authSecrets,
'jwt-token-id',
identityId,
{
fingerprint: 'device-fingerprint',
ip: '192.168.1.1',
domain: 'example.com',
userAgent: 'Mozilla/5.0...'
},
{ expiresIn: '7d' } // optional; default '2d'
);

Parameters:

  • authSecrets: Authentication secrets
  • jti: JWT token ID for stateful refresh token tracking
  • identityId: Identity identifier
  • tokenVerification: Security context for validation
  • jwtSignOptions: Optional SignOptions (default expiresIn: '2d')

Notes:

  • Generated tokens always have stateful: true (hardcoded, not configurable via this function)

generateOnetimeToken

Creates one-time tokens for temporary access.

import { utils } from '@nodeblocks/backend-sdk';

const { generateOnetimeToken } = utils;

const token = generateOnetimeToken(
authSecrets,
{ identityId: 'id-123', action: 'password-reset' },
{
fingerprint: 'device-fingerprint',
ip: '192.168.1.1',
domain: 'example.com',
userAgent: 'Mozilla/5.0...'
},
{ expiresIn: '1h' } // optional; default '5m'
);

Parameters:

  • authSecrets: Authentication secrets
  • data: Payload to embed in the token (Record<string, unknown>)
  • tokenVerification: Security context for validation
  • jwtSignOptions: Optional SignOptions (default expiresIn: '5m')

Notes:

  • Generated tokens always have stateful: true (hardcoded, not configurable via this function)

🔍 Token Validation

getBearerTokenInfo

Extracts token information from request authorization header. Default authentication function for bearer tokens.

import { utils } from '@nodeblocks/backend-sdk';

const { getBearerTokenInfo } = utils;

const tokenInfo = await getBearerTokenInfo(payload);

Process:

  1. Extracts token from Authorization: Bearer <token> header
  2. Decrypts and verifies JWT signature
  3. Validates token type (user or app)
  4. Performs security checks for user tokens (app tokens skip security checks)
  5. Returns token information

IP binding: Controlled by payload.context.configuration.checkIp. When unset, IP checks default to enabled (checkIp ?? true).

Errors: Throws NodeblocksError(401) when the token is missing, invalid, not an access token, or fails security checks (user tokens). App access tokens skip security checks and return AppAccessTokenInfo.

getCookieTokenInfo

Extracts token information from cookies. Authentication function for cookie-based tokens when authMode is 'cookie'.

import { utils } from '@nodeblocks/backend-sdk';

const { getCookieTokenInfo } = utils;

const tokenInfo = await getCookieTokenInfo(payload);

Use cases:

  • Web applications with cookie-based authentication (cookies.accessToken)
  • Server-side session management with cookie-parser

Note: Cookie mode differs from bearer mode by token transport only. Security checks (fingerprint, IP, user agent) use the same logic as getBearerTokenInfo, including configuration.checkIp ?? true.

Errors: Throws NodeblocksError(401) when cookies.accessToken is missing, invalid, not an access token, or fails security checks (user tokens). App access tokens skip security checks and return AppAccessTokenInfo.

defaultRefreshTokenBodyAuth

Default authentication function for refresh tokens fetched from the request body. It always extracts the token; when decryptToken is true, it decrypts, validates, and performs security checks.

import { utils } from '@nodeblocks/backend-sdk';

const { defaultRefreshTokenBodyAuth } = utils;

const { token, tokenInfo } = await defaultRefreshTokenBodyAuth(
authSecrets,
request,
true, // decryptToken
logger
);

Parameters:

  • authSecrets: Authentication secrets for token decryption
  • request: HTTP request object containing the refresh token
  • decryptToken: Whether to decrypt and validate the token (default: false)
  • logger: Optional logger for security check logging

Process:

  1. Extracts refresh token from request.body.refreshToken
  2. Retrieves token verification context (fingerprint, IP, user agent)
  3. Validates token format and presence
  4. Decrypts and verifies JWT signature (if decryptToken is true)
  5. Validates token type is refresh token
  6. Performs security checks with IP validation enabled
  7. Returns token and token information

defaultRefreshTokenCookieAuth

Default authentication function for refresh tokens fetched from cookies. It always extracts the token; when decryptToken is true, it decrypts, validates, and performs security checks. In that mode it returns both token and tokenInfo.

import { utils } from '@nodeblocks/backend-sdk';

const { defaultRefreshTokenCookieAuth } = utils;

const { token, tokenInfo } = await defaultRefreshTokenCookieAuth(
authSecrets,
request,
true, // decryptToken
logger
);

Parameters:

  • authSecrets: Authentication secrets for token decryption
  • request: HTTP request object containing the refresh token in cookies
  • decryptToken: Whether to decrypt and validate the token (default: false)
  • logger: Optional logger for security check logging

Process:

  1. Extracts refresh token from request.cookies.refreshToken
  2. Retrieves token verification context (fingerprint, IP, user agent)
  3. Validates token format and presence
  4. Decrypts and verifies JWT signature (if decryptToken is true)
  5. Validates token type is refresh token
  6. Performs security checks with IP validation enabled (checkIp: true)
  7. Returns token and token information (when decryptToken is true)

Key Differences from Body Auth:

  • Source: Reads from cookies instead of request body

resolveRefreshTokenFromRequest

Resolves a refresh token from cookie and/or request body. When both sources are present, they must refer to the same token.

import { utils } from '@nodeblocks/backend-sdk';

const { resolveRefreshTokenFromRequest } = utils;

const result = await resolveRefreshTokenFromRequest(authSecrets, request, logger);

if (result.isOk() && result.value) {
const { token, tokenInfo } = result.value;
}

Parameters:

  • authSecrets: Authentication secrets for token decryption
  • request: HTTP request object
  • logger: Optional logger for security check logging

Returns:

  • Result<{ token: string; tokenInfo: RefreshTokenInfo } | undefined, NodeblocksError>
  • Returns ok(undefined) when no valid refresh token is found
  • Returns err(...) with 401 when cookie and body tokens do not match

🛡️ Security Functions

tokenPassesSecurityCheck

Validates token security context.

import { utils } from '@nodeblocks/backend-sdk';

const { tokenPassesSecurityCheck } = utils;

const isValid = tokenPassesSecurityCheck(
tokenInfo,
{
fingerprint: 'device-fingerprint',
ip: '192.168.1.1',
userAgent: 'Mozilla/5.0...'
},
logger,
{ checkIp: true }
);

Validation logic:

  1. Fingerprint must match — if it does not, the check fails immediately
  2. If checkIp is disabled, the check passes (fingerprint already matched)
  3. If checkIp is enabled and IP matches, the check passes
  4. If checkIp is enabled and IP does not match, the check passes only when user agent matches; otherwise it fails

Parameters:

  • tokenInfo: User access or refresh token info
  • tokenVerification: Current request context (domain, fingerprint, ip, userAgent)
  • logger: Optional logger
  • options.checkIp: Whether to perform IP binding checks (default: true)

decryptAndVerifyJWT

Decrypts the AES envelope and verifies the inner JWT signature.

import { utils } from '@nodeblocks/backend-sdk';

const { decryptAndVerifyJWT } = utils;

const tokenInfo = decryptAndVerifyJWT(authSecrets, encryptedToken);

Errors: Throws NodeblocksError with status 401 when the token is empty, malformed, invalid, or expired. Does not perform fingerprint/IP/user-agent checks — callers (e.g. authenticators) must run tokenPassesSecurityCheck separately for user tokens.


🔧 Helper Functions

getBearerToken

Extracts bearer token from request headers.

import { utils } from '@nodeblocks/backend-sdk';

const { getBearerToken } = utils;

const token = getBearerToken(request.headers);
// Returns: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Errors: Returns undefined when the Authorization header is absent. Throws NodeblocksError with status 422 when the header is present but not a string or not in Bearer <token> format.

getFingerprint

Extracts device fingerprint from headers.

import { utils } from '@nodeblocks/backend-sdk';

const { getFingerprint } = utils;

const fingerprint = getFingerprint(request.headers, 'x-nb-fingerprint');

Errors: Throws NodeblocksError with status 422 when the header is present but not a string.

getUserAgent

Extracts user agent from request headers.

import { utils } from '@nodeblocks/backend-sdk';

const { getUserAgent } = utils;

const userAgent = getUserAgent(request.headers);

getRequestInfo

Extracts request metadata for token validation.

import { utils } from '@nodeblocks/backend-sdk';

const { getRequestInfo } = utils;

const requestInfo = getRequestInfo(request);
// Returns: { host, ip, method, path, url }

getExpiresIn

Normalizes token expiration time values. Converts various input formats to a standardized expiration time format.

import { utils } from '@nodeblocks/backend-sdk';

const { getExpiresIn } = utils;

const expiresIn = getExpiresIn('24h'); // Returns: '24h'
const expiresIn2 = getExpiresIn(3600000); // Returns: 3600000
const expiresIn3 = getExpiresIn(); // Returns: '48h' (default)

Parameters:

  • expirationTime: Optional expiration time as string or number

Returns:

  • number | string: Normalized expiration time (default: '48h')

Behavior:

  • If expirationTime is null or undefined: returns default '48h'
  • If expirationTime is a valid number: returns the number
  • If expirationTime is a non-numeric string: returns the string as-is
  • If expirationTime is a numeric string: converts it to a number

getExpirationDate

Calculates the absolute expiration date based on a duration string or milliseconds.

import { utils } from '@nodeblocks/backend-sdk';

const { getExpirationDate } = utils;

const expirationDate = getExpirationDate('7d'); // Returns: Date object 7 days from now
const expirationDate2 = getExpirationDate(3600000); // Returns: Date object 1 hour from now
const expirationDate3 = getExpirationDate(); // Returns: Date object 2 days from now (default)

Parameters:

  • expiresIn: Duration string (e.g., '7d', '24h', '30m') or milliseconds (default: '2d')

Returns:

  • Date: Absolute expiration date and time

Supported Duration Formats:

  • '7d' - 7 days
  • '24h' - 24 hours
  • '30m' - 30 minutes
  • '60s' - 60 seconds
  • Numeric values in milliseconds

deriveCookieMaxAge

Converts a token's expiresIn value into milliseconds for Express cookie maxAge options.

import { utils } from '@nodeblocks/backend-sdk';

const { deriveCookieMaxAge } = utils;

const maxAge = deriveCookieMaxAge('15m'); // Returns: 900000 (ms)
const maxAge2 = deriveCookieMaxAge(3600); // Returns: 3600000 (3600 seconds → ms)

Parameters:

  • expiresIn: Duration string (parsed via ms()) or a numeric value in seconds (matching jsonwebtoken convention)

Returns:

  • number: Duration in milliseconds

Note: Unlike getExpirationDate, bare numeric values here are treated as seconds, not milliseconds.

isAccessToken

Checks if a token is an access token (user or app) and can be used as a simple type guard.

import { utils } from '@nodeblocks/backend-sdk';

const { isAccessToken } = utils;

if (isAccessToken(tokenInfo)) {
// tokenInfo is AccessTokenInfo (accessType: 'user' | 'app')
}

Parameters:

  • tokenInfo: Token information object to check

Returns:

  • boolean: true if the token is an access token, otherwise false

isUserAccessToken

Checks if a token is specifically a user access token.

import { utils } from '@nodeblocks/backend-sdk';

const { isUserAccessToken } = utils;

if (isUserAccessToken(tokenInfo)) {
// tokenInfo is UserAccessTokenInfo
console.log(tokenInfo.identityId);
}

Parameters:

  • tokenInfo: Token information object to check

Returns:

  • boolean: true if the token is a user access token, otherwise false

isAppAccessToken

Checks if a token is specifically an app access token.

import { utils } from '@nodeblocks/backend-sdk';

const { isAppAccessToken } = utils;

if (isAppAccessToken(tokenInfo)) {
// tokenInfo is AppAccessTokenInfo
console.log(tokenInfo.appId);
}

Parameters:

  • tokenInfo: Token information object to check

Returns:

  • boolean: true if the token is an app access token, otherwise false

isRefreshToken

Checks if a token is a refresh token.

import { utils } from '@nodeblocks/backend-sdk';

const { isRefreshToken } = utils;

if (isRefreshToken(tokenInfo)) {
// tokenInfo is RefreshTokenInfo
console.log(tokenInfo.jti);
}

Parameters:

  • tokenInfo: Token information object to check

Returns:

  • boolean: true if the token is a refresh token, otherwise false

isOnetimeToken

Checks if a token is a one-time token.

import { utils } from '@nodeblocks/backend-sdk';

const { isOnetimeToken } = utils;

if (isOnetimeToken(tokenInfo)) {
// tokenInfo is OnetimeTokenInfo
console.log(tokenInfo.data);
}

Parameters:

  • tokenInfo: Token information object to check

Returns:

  • boolean: true if the token is a one-time token, otherwise false

isValidAppAccessToken

Checks that an app access token has an appId present.

import { utils } from '@nodeblocks/backend-sdk';

const { isValidAppAccessToken } = utils;

if (isValidAppAccessToken(tokenInfo)) {
// tokenInfo is AppAccessTokenInfo with appId present
}

Parameters:

  • tokenInfo: Token information object to check

Returns:

  • boolean: true if token is an app access token with appId present, otherwise false

isValidUserAccessToken

Checks that a user access token has an identityId present.

import { utils } from '@nodeblocks/backend-sdk';

const { isValidUserAccessToken } = utils;

if (isValidUserAccessToken(tokenInfo)) {
// tokenInfo is UserAccessTokenInfo with identityId present
}

Parameters:

  • tokenInfo: Token information object to check

Returns:

  • boolean: true if token is a user access token with identityId present, otherwise false

retrieveTokenVerification

Create token verification metadata from an Express Request.

import { utils } from '@nodeblocks/backend-sdk';

const { retrieveTokenVerification } = utils;

const verification = retrieveTokenVerification(request);
// { domain, fingerprint, ip, userAgent }

validateAuthSecrets

Validate required auth secrets and throw if missing or too short.

import { utils } from '@nodeblocks/backend-sdk';

const { validateAuthSecrets } = utils;

validateAuthSecrets(authSecrets); // throws on invalid configuration
validateAuthSecrets(authSecrets, 24); // optional minimum length (default: 18)

Errors: Throws NodeblocksError with status 500 when secrets are missing or shorter than the minimum length.

generateMailBody

Interpolate a URL and options into an email template.

import { utils } from '@nodeblocks/backend-sdk';

const { generateMailBody } = utils;

const body = generateMailBody(
'Click here: ${url}',
'https://example.com/reset?token=${token}',
{ token: 'abc' }
);

authSecretsValidationErrorMessage

Return a human-readable error for invalid auth secrets (temporary helper).

import { utils } from '@nodeblocks/backend-sdk';

const { authSecretsValidationErrorMessage } = utils;

const msg = authSecretsValidationErrorMessage(authSecrets);
if (msg) throw new Error(msg);

// Optional minimum length (default: 18)
const msg2 = authSecretsValidationErrorMessage(authSecrets, 24);

🔐 Encryption Functions

encrypt

Encrypts a string using AES-256-CBC. Returns iv_hex:ciphertext_hex.

import { utils } from '@nodeblocks/backend-sdk';

const { encrypt } = utils;

const encrypted = encrypt(authSecrets.authEncSecret, 'sensitive-data');

decrypt

Decrypts an AES-256-CBC envelope (iv_hex:ciphertext_hex).

import { utils } from '@nodeblocks/backend-sdk';

const { decrypt } = utils;

const decrypted = decrypt(authSecrets.authEncSecret, encryptedData);

Errors: Throws NodeblocksError with status 401 when the input is empty, malformed, or invalid.


🔑 Password Functions

hash

Hashes passwords using bcrypt with cost factor 10.

import { utils } from '@nodeblocks/backend-sdk';

const { hash } = utils;

const hashedPassword = await hash('user-password');

Implementation: Uses bcrypt with 10 salt rounds (bcryptHash(s, 10)).

compareHash

Compares password with hash.

import { utils } from '@nodeblocks/backend-sdk';

const { compareHash } = utils;

const isValid = await compareHash('user-password', hashedPassword);

📊 Token Types

Token interfaces are exported from the types namespace (source: src/types/authentication.ts), not from utils:

import { types } from '@nodeblocks/backend-sdk';

type UserAccessTokenInfo = types.UserAccessTokenInfo;
type AppAccessTokenInfo = types.AppAccessTokenInfo;
type RefreshTokenInfo = types.RefreshTokenInfo;
type OnetimeTokenInfo = types.OnetimeTokenInfo;

User Access Token

interface UserAccessTokenInfo {
accessType: 'user';
identityId: string;
type: 'access';
stateful: boolean;
fingerprint?: string;
ip?: string;
domain?: string;
target?: string;
userAgent?: string;
}

App Access Token

interface AppAccessTokenInfo {
accessType: 'app';
appId: string;
type: 'access';
}

Refresh Token

interface RefreshTokenInfo {
type: 'refresh';
jti: string;
identityId: string;
stateful: true;
fingerprint?: string;
ip?: string;
domain?: string;
userAgent?: string;
}

One-time Token

interface OnetimeTokenInfo {
type: 'onetime';
data: Record<string, unknown>;
stateful: true;
fingerprint?: string;
ip?: string;
domain?: string;
target?: string;
userAgent?: string;
}