2.7 KiB
Token match — @suaveplan/api-auth-bearer-static
(no submodules)
Purpose
findTokenIndex performs a constant-time lookup of a presented bearer
token against a fixed table, returning the matching entry's index or -1
if no entry matches. The function is the security boundary of the package:
every other code path in the resolver assumes the match is timing-safe so
an attacker cannot binary-search the token table by measuring response
latency.
The implementation walks every entry, calling constantTimeEqual from
@suaveplan/crypto-utils once per row. The match-tracking variable is
written only on the first match; subsequent matches are ignored. Crucially
the loop does not break on first match — exiting early would leak the
position of the matching token via wall-clock timing.
Features
- Wraps
@suaveplan/crypto-utilsconstantTimeEqualover UTF-8 byte views. - Iterates the full table for every call — no early exit, no short-circuit
on
presented === entry.token. - Returns the first matching index or
-1. - Handles
undefinedentries (defensive guard for sparse arrays).
Usage: Basic
import { findTokenIndex } from "@suaveplan/api-auth-bearer-static/constant-time";
const table = [
{ token: "T1" },
{ token: "T2" },
];
const index = findTokenIndex("T2", table);
// index === 1
Usage: Advanced
import { findTokenIndex } from "@suaveplan/api-auth-bearer-static/constant-time";
interface TokenEntry {
readonly token: string;
readonly principalId: string;
}
const table: ReadonlyArray<TokenEntry> = [
{ token: "service-cron", principalId: "p1" },
{ token: "service-admin", principalId: "p2" },
];
function lookup(presented: string): TokenEntry | null {
const idx = findTokenIndex(presented, table);
return idx === -1 ? null : (table[idx] ?? null);
}
API Reference
findTokenIndex(presented: string, table: ReadonlyArray<{ token: string }>): number— returns the index of the first entry whosetokenmatchespresented, or-1if no entry matches.
Implementation Notes
constantTimeEqual from @suaveplan/crypto-utils walks every byte of the
two Uint8Array views and accumulates differences into an integer via
bitwise OR; the function returns whether the accumulator stayed zero. The
length-mismatch fast path is documented as not secret (token lengths are
not secret in this adapter's threat model — the table is operator-supplied
config). The TextEncoder round-trip ensures we compare bytes, not
surrogate-pair code units; otherwise an attacker could compare a multi-
byte presented token against a single-byte entry and learn from the
length-mismatch shortcut whether their candidate had the right length.