|
|
5 months ago | |
|---|---|---|
| .. | ||
| README.md | 5 months ago | |
| audit.ts | 5 months ago | |
| consts.ts | 5 months ago | |
| contracts.ts | 5 months ago | |
| cookies.ts | 5 months ago | |
| csrf.ts | 5 months ago | |
| errors.ts | 5 months ago | |
| events.ts | 5 months ago | |
| guards.ts | 5 months ago | |
| helpers.ts | 5 months ago | |
| ids.ts | 5 months ago | |
| index.ts | 5 months ago | |
| jwt.ts | 5 months ago | |
| mfa.ts | 5 months ago | |
| normalize.ts | 5 months ago | |
| oauth.ts | 5 months ago | |
| testkit.ts | 5 months ago | |
| tokens.ts | 5 months ago | |
| types.ts | 5 months ago | |
| webauthn.ts | 5 months ago | |
README.md
libs/auth
$libs/auth es el lenguaje común de autenticación. No tiene Svelte, no tiene
rutas de framework y no conoce bases de datos. Define los nombres, tipos,
errores y contratos que comparten $svrs/auth y $auth.
Qué Exporta
consts.ts constantes públicas
types.ts tipos de dominio
contracts.ts puertos/adapters
errors.ts errores tipados y guards
csrf.ts issue/verify CSRF
tokens.ts random/base64/hash helpers
normalize.ts normalización de identifiers
ids.ts branded ids
events.ts payloads de eventos
helpers.ts snapshots/cache tags/request meta
oauth.ts helpers OAuth
mfa.ts helpers MFA
webauthn.ts contratos WebAuthn
testkit.ts constantes/helpers de test
Constantes
No uses strings hardcodeados en app code. Importa constantes:
import {
AUTH_ROUTE_PATHS,
AUTH_HEADER_NAMES,
AUTH_COOKIE_NAMES,
AUTH_ERR_CREDENTIAL_INVALID,
AUTH_EVENT_NAMES,
AUTH_LOG_CATEGORIES
} from '$libs/auth';
Ejemplos:
AUTH_ROUTE_PATHS.SIGN_IN_PASSWORD;
AUTH_HEADER_NAMES.CSRF;
AUTH_ERR_CREDENTIAL_INVALID; // 'auth::credential_invalid'
AUTH_EVENT_NAMES.SIGN_IN_SUCCEEDED;
AUTH_LOG_CATEGORIES.CSRF;
Tipos Clave
Identidad mínima:
interface AuthActorRef {
tenantId: AuthTenantId;
actorId: AuthActorId;
}
Snapshot de sesión:
interface AuthSessionSnapshot {
status: AuthSessionStatus;
actorRef?: AuthActorRef;
sessionId?: AuthSessionId;
deviceId?: AuthDeviceId;
aal: AuthAssuranceLevel;
amr: readonly AuthAuthenticationMethod[];
authTime?: number;
expiresAt?: number;
refreshedAt?: number;
}
Vista segura para SSR/cliente:
interface AuthCurrentView {
session: AuthSessionSnapshot;
actor?: AuthPublicActor;
}
Esa vista es lo que se serializa a SvelteKit. No contiene secretos.
AAL y AMR
aal describe nivel de garantía:
AUTH_AAL.ANONYMOUS;
AUTH_AAL.SINGLE_FACTOR;
AUTH_AAL.MULTI_FACTOR;
AUTH_AAL.PHISHING_RESISTANT;
amr describe métodos usados:
AUTH_AMR.PASSWORD;
AUTH_AMR.TOTP;
AUTH_AMR.WEBAUTHN;
AUTH_AMR.PASSKEY;
auth calcula estos valores; perm decide si bastan para una acción.
Errores
Todos los errores propios extienden AuthError:
import { codeToLangPath, isAuthError } from '$libs/auth';
try {
await run();
} catch (error) {
if (isAuthError(error)) {
error.code; // 'auth::credential_invalid'
codeToLangPath(error.code); // 'auth.credential_invalid'
error.meta.data; // contexto opcional adjuntado
error.cause; // root cause si lo hay
}
}
Usa code para lógica y codeToLangPath(code) para derivar la clave i18n.
No dependas de error.message (es texto dev-facing).
CSRF
Uso directo:
const issued = await issueAuthCsrf({
crypto,
clock,
tenantId,
config: {
signingKey,
ttlMs: AUTH_DEFAULTS.CSRF_TTL_MS
}
});
await verifyAuthCsrf({
crypto,
clock,
tenantId,
token: issued.token,
cookie: issued.cookie.value,
config: { signingKey }
});
El token está ligado a tenant y expiración. La cookie contiene el valor firmado que el server compara con el header.
Contratos de Adapters
contracts.ts define puertos. Los más importantes:
AuthStoreAdapter;
AuthActorAdapter;
AuthSessPort;
AuthCachePort;
AuthLogrPort;
AuthClockPort;
AuthCryptoPort;
AuthPasswordHasher;
AuthMailerAdapter;
La intención es que auth no dependa de Prisma, Drizzle, Redis, SvelteKit,
Argon2, proveedores externos ni SDKs concretos.
Normalización de Identifiers
Para password/email login se normaliza antes de hashear:
const normalized = normalizeAuthIdentifier(' Person@Example.com ');
const hash = await hashPasswordIdentifier({
crypto,
tenantId,
identifier: normalized.normalized
});
El hash incluye tenant para no mezclar identidades entre tenants.
Branded IDs
Los IDs son strings con marca de tipo:
AuthTenantId;
AuthActorId;
AuthSessionId;
AuthDeviceId;
AuthFlowId;
AuthCredentialId;
Esto evita pasar accidentalmente un sessionId donde se esperaba un
actorId.
Eventos
Los nombres salen de AUTH_EVENT_NAMES. Los payloads están tipados en
events.ts:
AuthEventPayloadMap[typeof AUTH_EVENT_NAMES.SIGN_IN_SUCCEEDED];
Esto permite que Auth.on(...) sea type-safe.
Qué No Va Aquí
- No hay estado.
- No hay Svelte.
- No hay fetch.
- No hay cookies de framework.
- No hay DB.
- No hay logger concreto.
- No hay dependencias externas.
Si un helper necesita runtime o I/O, probablemente pertenece a $svrs/auth o
a un adapter.