@chrono-os/service-auth
v0.1.0
Published
Núcleo neutro de validação de service-token (gate de write-back dashboard → backend), framework-agnóstico. Comparação timing-safe via node:crypto, zero deps de runtime.
Downloads
67
Maintainers
Readme
@chrono-os/service-auth
Núcleo neutro de validação de service-token — o gate usado no write-back do Admin Unificado (dashboard → backend). Framework-agnóstico: serve igual pra Fastify e NestJS. Comparação em tempo ~constante (timing-safe) via node:crypto, zero dependências de runtime e zero dependência de framework.
Install
Pacote público no npmjs.org — sem necessidade de .npmrc ou token.
yarn add @chrono-os/service-authAPI
import {
checkServiceToken,
secureCompare,
SERVICE_TOKEN_HEADER,
type ServiceAuthResult,
} from "@chrono-os/service-auth";SERVICE_TOKEN_HEADER
'x-service-token' — header padrão onde o token trafega (dashboard → backend).
ServiceAuthResult
type ServiceAuthResult = "valid" | "invalid" | "absent";'absent'— service-auth desligado (sem token esperado configurado) ou header ausente na request.'invalid'— header presente mas não bate (logar/recusar).'valid'— bate.
checkServiceToken(provided, expected): ServiceAuthResult
Valida o valor cru do header (string | string[] | undefined) contra o token esperado (string | undefined). Se provided for array (header repetido), usa o primeiro elemento.
secureCompare(a, b): boolean
Comparação de dois valores em tempo ~constante. Faz sha256 dos dois lados antes do timingSafeEqual pra normalizar o comprimento (não lança com tamanhos diferentes) e não vazar o tamanho do token esperado.
Uso num backend
Ler o header da request, validar contra o token esperado (de uma env var) e tratar os três resultados:
import { checkServiceToken, SERVICE_TOKEN_HEADER } from "@chrono-os/service-auth";
const expected = process.env.SERVICE_TOKEN; // pode ser undefined (gate desligado)
// `request.headers[SERVICE_TOKEN_HEADER]` é string | string[] | undefined
const result = checkServiceToken(request.headers[SERVICE_TOKEN_HEADER], expected);
switch (result) {
case "valid":
// segue com o write-back
break;
case "invalid":
// header presente mas errado → 401/403 + log de tentativa
break;
case "absent":
// sem token esperado (gate off) ou sem header → política do app
break;
}O mesmo vale num guard/interceptor NestJS: leia request.headers['x-service-token'] e chame checkServiceToken.
Nota de segurança
A comparação é timing-safe: usa crypto.timingSafeEqual sobre o hash sha256 de cada lado, evitando ataques de timing que comparam caractere a caractere. Nunca compare tokens com ===. O hash prévio também impede que o tamanho do token esperado vaze pela duração da comparação.
Licença
MIT
