Utilities

Complete reference for server utility functions covering token metadata, session caching, server-to-server requests, HMAC signing, cookie management, OAuth helpers, image validation, sanitization, and general utilities.

All utilities are exported from auth-h3client/v1 and auth-h3client/v2. When using the Nuxt module, they are auto-imported inside the server/ directory.


Configuration access

configuration(config)

Validates the provided configuration object against the internal Zod schema, freezes it with Object.freeze, and stores it as the module-level singleton. Must be called exactly once at startup before any middleware or handler runs. Throws a formatted validation error if the schema check fails.

import { configuration } from 'auth-h3client/v2'

configuration({
  server: { auth_location: 'https://iam.example.com' },
  logLevel: 'info',
  // ...
})

Parameters

ParameterTypeDescription
configConfigurationThe full configuration object. Validated against a Zod schema before being frozen

getConfiguration()

Returns the active Configuration object that was passed to configuration(...) at startup. The object is frozen, so its values cannot be mutated at runtime. Throws if called before configuration(...) has run.

import { getConfiguration } from 'auth-h3client/v2'

const { server, enableFireWallBans } = getConfiguration()

Use this inside custom handlers or middleware when you need direct access to configuration values such as the IAM server address, HMAC settings, or feature flags.


Token and session

getAccessTokenMetaData(event)

Reads the __Secure-a access token from the request cookies, checks the local LRU metadata cache, and returns expiry and rotation state without calling the IAM service. Falls back to a rotation call if the cache misses.

const meta = await getAccessTokenMetaData(event)
// meta.msUntilExp: ms until expiry
// meta.shouldRotate: true when threshold is reached
// meta.authorized: false when token is invalid

getCachedUserData(event, cookies, token, storage, cacheOptions?)

Calls the IAM /secret/data endpoint and caches the result using a SHA-256 hash of the session identifiers as the key. Returns cached data on subsequent calls within the TTL.

const result = await getCachedUserData(event, cookies, token, storage)

if (result.type === 'SUCCESS') {
  const { userId, roles } = result.data
}
// result.type === 'ERROR' with reason: 'UNAUTHORIZED' | 'MFA' | 'RATE_LIMIT' | 'SERVER_ERROR' | ...

Called automatically by defineAuthenticatedEventHandler and defineOptionalAuthenticationEvent.


getOperationalConfig(event)

Fetches and caches shared settings from the IAM service: domain and accessTokenTTL. The result is cached for the lifetime of the process.


applyRotationResult(event, result, domain, accessTokenTTL)

Writes the cookies from a token rotation result to the response. Handles the both, access-only, and refresh-only rotation types.


getAuthStatusHandler

A pre-built defineAuthenticatedEventHandler that returns the current session data from event.context.authorizedData. In manual H3 and Nitro setups, a common route is GET /auth/users/authStatus. Under the Nuxt module, the same handler is registered automatically at authStatusUrl, whose default value is /api/auth/users/authStatus. The handler is also exported for direct use in custom setups.

import { getAuthStatusHandler } from 'auth-h3client/v2'

router.get('/auth/users/authStatus', getAuthStatusHandler)

Responses

StatusMeaning
200Returns the authorized user data
400User ID invalid after conversion
401Not authenticated

askForMfaFlow(event, log, reason, random, accessToken?)

Requests a step-up MFA email from the IAM service for an authenticated user. random must be a Buffer whose hex representation is 254 to 500 characters, reason must be 100 characters or shorter, and the request is deduplicated per canary_id + reason. Returns { ok: true, data: 'Please check your email...' } on success, or a structured error (INVALID_CREDENTIALS, MFA_REQUIRED, FORBIDDEN, RATE_LIMIT, HASH, REASON, AUTH_REJECTED, AUTH_SERVER_ERROR, UNEXPECTED_ERROR) on failure. Never throws. When accessToken is omitted, the token is read from the __Secure-a cookie. See Custom MFA Flow for the complete pattern.


Server-to-server

serviceToService(keepAlive, endpoint, method, event, body, cookies?, data?, token?, apiToken?)

Makes an authenticated request from the gateway to the IAM service. Applies HMAC signing headers when enableHmac is true, forwards cookies and bearer tokens when provided, can forward an API token as X-API-KEY, and uses the configured Undici agent for connection pooling and optional mTLS.

ParameterTypeDescription
keepAlivebooleanWhether to keep the connection alive
endpointstringIAM service path, e.g. /auth/login
methodstringHTTP method
eventH3EventCurrent request event for header extraction
bodybooleanWhether to include the request body
cookiesCookies[]Cookies to forward to the IAM service
dataobjectRequest body data when body is true
tokenstringAccess token to include as Authorization: Bearer
apiTokenstringAPI token to include as X-API-KEY

defineAuthenticatePublicApi uses the apiToken parameter to forward the incoming X-API-KEY header to IAM /api/public/verify without converting it into session cookies or a bearer token.


clientHeaders(event)

Extracts headers from the incoming request to forward to the IAM service.


signature(method, path)

Generates HMAC-SHA256 signature headers for a request to the IAM service.

Returns: { 'X-Client-Id', 'X-Timestamp', 'X-Request-Id', 'X-Signature' }

const headers = signature('POST', '/auth/login')

getAuthAgent(botDetector, ssl?)

Creates an Undici Agent configured with optional mTLS certificates and connection pool settings. When botDetector is true, the agent uses a high-concurrency pool tuned for polling.


Cookies

makeCookie(event, name, value, options)

Sets an HTTP cookie on the response with typed options.


createSignedValue(raw, ttlMs, keyword)

Creates a signed cookie string in the format base64(value).base64(keyword).expiry.hmac. The keyword binds the signature to a specific context.


verifySignedValue(cookie, keyword)

Parses and verifies a signed cookie. Returns { valid: boolean, payload: { value, exp } | null }.


toB64(data) / fromB64(b64)

Base64url encoding and decoding utilities.


isSameBuffer(a, b)

Timing-safe HMAC comparison of two strings. Use for any secret or signature comparison to prevent timing side-channel attacks.


OAuth helpers

makePkcePair()

Generates a PKCE verifier and challenge pair. Returns { verifier: string, challenge: string }.


discoverOidc(issuer, log)

Fetches the OIDC discovery document from {issuer}/.well-known/openid-configuration. Returns the parsed metadata object including authorization_endpoint, token_endpoint, and jwks_uri.


verifyOAuthToken(idToken, jwksUri, issuer, clientId)

Verifies an OIDC ID token signature against the provider's JWKS endpoint. Returns the decoded OidcIdTokenPayload on success.


atHashCheck(atHash, accessToken, idToken)

Verifies the at_hash claim in an OIDC ID token against the access token. Returns true if the hash matches.


safeObjectMerge(target, src, opts?, extraReserved?)

Merges src into target while protecting reserved fields from being overridden. Reserved fields include sub, email, iss, aud, iat, exp, and all JWT claims. Use this when merging OAuth user info with existing user data.


getSafeUrl(urlString)

Parses and validates a redirect URL string. Returns a URL object if valid, or false if the input is not a valid URL.


safeRedirect(event, url)

Validates a redirect URL with getSafeUrl and redirects the response. Throws HTTP 400 if the URL is not valid.


Validation and sanitization

sanitizeInputString(input)

Runs the full HTML sanitization pipeline on a string: unicode normalization, iterative URI and entity decoding, pattern detection, sanitize-html pass, and entity encoding. Returns { vall: string, results: { htmlFound: boolean, tags? } }.

See IAM XSS Protection for the full pipeline description.


makeSafeString(opts)

Returns a Zod string schema that validates length and an optional regex constraint, then applies sanitizeInputString as a transform. Use this in Zod schemas for any user-supplied string fields.

const schema = z.object({
  name: makeSafeString({ min: 1, max: 100 }),
  bio: makeSafeString({ min: 0, max: 500, pattern: /^[\w\s]+$/ })
})

validateZodSchema(schema, data, log)

Parses data against a Zod schema. Returns the parsed data on success or { valid: false, errors: Record<string, string> } on failure.


validateUserPassword(password)

Returns true if the password meets the minimum policy: 12+ characters with at least one uppercase letter, one lowercase letter, one digit, and one special character.


sanitizeBaseName(input, max)

Strips unsafe characters from a filename and truncates to max characters. Use before deriving a storage key from a user-supplied filename.


Image upload

validateImage(data, filename)

Validates a Buffer against the imageUploader configuration limits, detects the MIME type from magic bytes, converts to WebP via sharp, and returns { ok: true, body, key, mime } or { ok: false, date, reason }. See Image Upload for full details.


General utilities

MiniCache<T>

In-memory TTL cache with a configurable capacity and sweep interval.

const cache = new MiniCache<string>(1000, 60_000) // 1000 entries, sweep every minute

cache.set('key', 'value', 5 * 60 * 1000) // 5-minute TTL
const val = cache.get('key')  // null if expired
cache.del('key')
cache.clear()

lockAsyncAction(key, fn, ttl?)

Deduplicates async operations by key. If a call with the same key is already in progress, the second caller waits for the first result. Results are cached briefly (default 5 seconds) to handle concurrent requests that arrive after completion.

const data = await lockAsyncAction(`user:${userId}`, async () => {
  return await fetchExpensiveData(userId)
})

getLogger()

Returns the pino logger instance used by the module. Use it to write structured log entries from custom handlers.


parseResponseContentType(log, response)

Reads and parses an HTTP Response body as JSON or text depending on the Content-Type header.


getBaseUrl(cfg)

Builds the base URL for the IAM service from the server.auth_location configuration. Returns a URL object.


findStringsInObject(input, visited?, searchTerms)

Recursively searches an object for a key-value pair. Returns the matching value string or null.


banIp(ip)

Executes sudo ufw insert 1 deny from <ip> to any to block an IP at the firewall level. Only available on Linux with UFW installed.


checkForBots(cookies, event, method, log, enableFireWallBans, canary?)

Low-level helper that calls the IAM /check endpoint with an explicit signed cookie and visitor context. Throws HTTP 403 when the IAM service flags the visitor, and HTTP 502 when the IAM service is unreachable. On success, sets the __Host-dr_i_n cookie on the response and stores the tracking result in event.context.trackingResult. Used internally by botDetectorMiddleware. See Bot Detection for the full usage pattern.


TypeScript types

The following types are exported from auth-h3client/v1 and auth-h3client/v2 (and re-exported from auth-h3client/client for browser use).

ServerResponse

The shape of event.context.authorizedData set by defineAuthenticatedEventHandler and defineOptionalAuthenticationEvent.

interface ServerResponse {
  authorized: boolean
  userId?: string
  roles?: string[] | string
  ipAddress: string
  userAgent: string
  date: string
  reason?: string
  error?: string
  message?: string
}

LimitedMetaData

The shape returned by the IAM service after a successful code verification and token rotation.

interface LimitedMetaData {
  authorized: true
  userId: number | string
  visitorId: number | string
  roles: string[] | 'No roles added with this token.'
  ipAddress: string
  userAgent: string
  date: string
  accessToken: string
  accessIat: string
}
defineMfaCodeVerifierHandler destructures accessToken and accessIat from the response and applies them to the response cookies via token rotation. The value set on event.context.limitedMetaData inside your handler does not include these two fields.

API token wrapper types

The API token wrappers export a small set of helper types inferred from the shared Zod schemas. Use them when you want your custom handlers to mirror the same action names and request bodies as the built-in wrappers.

type Privilege = 'custom' | 'demo' | 'restricted' | 'protected' | 'full'

type ParamsTypes = {
  action:
    | 'new-token'
    | 'revoke'
    | 'metadata'
    | 'rotate'
    | 'ip-restriction-update'
    | 'privilege-update'
    | 'list-metadata'
}

type NewTokens = {
  name: string
  ipv4?: string[]
  prefix: string
  expires?: number
}

type NewIpRestriction = {
  ipv4?: string[]
  tokenId: number
}

type TokenId = {
  tokenId: number
}

These types are exported from auth-h3client/v1 and auth-h3client/v2 via the API token wrapper module.

API token response types

The package also exports the response and metadata types used by getApiListsController, defineAuthenticatePublicApi, and defineApiManagementHandler.

interface TokenMeta {
  name?: string
  tokenId?: number
  userId?: number
  createdAt?: string
  expiresAt?: string
  lastUsed?: string
  usageCount?: number
  providedPrivilege?: 'custom' | 'demo' | 'restricted' | 'protected' | 'full'
}

interface SingleTokenMeta {
  tokenMeta: TokenMeta
  counts: {
    totalInvalidTokens: number
    totalValidTokens: number
    total: number
  }
}

interface TokenList {
  id: number
  name: string
  created_at: string
  expires_at: string
  restricted_to_ip_address: string[] | null
  public_identifier: string
  last_used: string
  usage_count: number
  privilege_type: 'demo' | 'restricted' | 'protected' | 'full' | 'custom'
}

interface AllValidTokensList {
  total: number
  totalInvalidTokens: number
  totalValidTokens: number
  tokenList?: TokenList[]
}

interface CreationSuccess {
  rawApiKey: string | undefined
  expiresAt: Date | null
}

interface ApiTokenRotationSuccess {
  msg: string
  newRawToken: string | undefined
  newExpiry: Date | null
}

interface VerifySuccessResponse {
  name: string
  tokenId: number
  userId: number
  createdAt: string
  expiresAt: string
  lastUsed: string
  usageCount: number
  providedPrivilege: 'custom' | 'demo' | 'restricted' | 'protected' | 'full'
}

type ActionManagerResult =
  | Results<string | { msg: string; invalidedTokenId: number; userId: number }>
  | Results<ApiTokenRotationSuccess>
  | Results<SingleTokenMeta>
  | Results<CreationSuccess>
  | Results<{ msg: string }>

getApiListsController uses AllValidTokensList, but removes public_identifier before it returns the payload. defineApiManagementHandler uses the full token list response so it can resolve tokenId to publicIdentifier before sending the action to IAM.

Results<T>

The standard response envelope returned by executeRequest and used as the return type of askForMfaFlow and other utilities.

type Results<T = unknown> =
  | { ok: true;  data: T;      date: string }
  | { ok: false; reason: string; date: string }

UtilsResponse<T>

Extends Results<T> with an optional error code and rate-limit retry value. Returned by utilities that proxy IAM service responses.

type UtilsResponse<T> = Results<T> & {
  code?: AppCode
  retryAfter?: string | null
}

AppCode

Union of structured error code strings used in thrown errors and UtilsResponse.code.

type AppCode =
  | 'AUTH_REQUIRED'
  | 'SERVER_ERROR'
  | 'TEMPERING'
  | 'FORBIDDEN'
  | 'AUTH_SERVER_ERROR'
  | 'AUTH_CLIENT_ERROR'
  | 'MISSING_BODY'
  | 'INVALID_CREDENTIALS'
  | 'INVALID_CONTENT_TYPE'
  | 'NOT_FOUND'
  | (string & {})   // open for module-specific codes

VerificationLinkSchema

Inferred type for the magic link query parameters validated by defineVerifiedMagicLinkGetHandler and defineMfaCodeVerifierHandler.

type VerificationLinkSchema = {
  visitor: number
  token: string
  random: string   // 254–500 characters
  reason: string   // max 100 characters
}
Logo