Audit, Compliance & Webhooks
The SOC 2 / GDPR tail: an append-only audit trail with PII redaction, self-service session management, data export/erasure, field encryption, and signed outbound webhooks.
#Audit Logging
An AuditSink (in-memory or Postgres) receives structured, append-only events from every flow. Redaction runs before any sink sees an event, dropping or pseudonymizing PII while keeping events correlatable.
TS
import {
auth,
createNeonAuditSink,
createAuditRedactor
} from '@absolutejs/auth';
await auth<User>({
providersConfiguration: {},
audit: {
auditStore: createNeonAuditSink(process.env.DATABASE_URL),
getUserId: (user) => user.sub,
// PII redaction applied to every event before any sink sees it:
redact: createAuditRedactor({ hashFields: ['email'], redactIp: true }),
onAuditEvent: (event) => forwardToSiem(event) // optional extra sink
}
});
// auth() emits structured, append-only events from every flow: register, login,
// mfa_*, password_reset, sso_login, scim_provision, organization_created,
// role_assigned, webauthn_*, passwordless_login, token_revoked, and more.#Session Management
Let users list and revoke their own active sessions, and revoke all of a user's sessions on password reset. Requires an authSessionStore that can enumerate sessions.
TS
await auth<User>({
providersConfiguration: {},
authSessionStore, // a store that can enumerate sessions (Neon / Redis)
sessions: { getUserId: (user) => user.sub }
});
// Self-service session management:
GET /auth/sessions // list the caller's active sessions
DELETE /auth/sessions/:id // revoke one the caller owns
// listUserSessions / revokeUserSessions are also exported for password-reset
// "log out everywhere" flows.#GDPR Compliance
Right to accessSelf-service export route, delegated to your hooks.
Right to erasureSelf-service delete route — erasure also revokes the user's sessions and clears the cookie.
createSecretCipherBinds an AES-GCM key for encrypting sensitive fields at rest.
TS
import { auth, createSecretCipher } from '@absolutejs/auth';
await auth<User>({
providersConfiguration: {},
compliance: {
getUserId: (user) => user.sub,
exportUserData: ({ user }) => gatherEverything(user), // GDPR Art. 15
deleteUserData: ({ user }) => anonymizeOrDelete(user) // GDPR Art. 17
}
});
// Mounts GET /auth/account/export (right to access -> JSON download) and
// DELETE /auth/account (right to erasure: runs your hook, revokes every session
// the user holds, clears the cookie).
// Field encryption at rest, bound to an AES-GCM key (F2):
const cipher = createSecretCipher(process.env.FIELD_KEY);
const stored = await cipher.encrypt(refreshToken);
const plain = await cipher.decrypt(stored);#Signed Webhooks
Forward every auth event to your endpoints, HMAC-signed with the Standard Webhooks scheme (Svix-compatible).
Delivery is best-effort and per-endpoint isolated, so a dead endpoint never breaks the auth flow.
TS
import { auth, verifyWebhookSignature } from '@absolutejs/auth';
await auth<User>({
providersConfiguration: {},
// Configuring webhooks alone turns on event emission and forwards the whole
// audit taxonomy, HMAC-signed (Standard Webhooks scheme), to each endpoint:
webhooks: {
endpoints: [{ url: 'https://hooks.example.com/auth', secret: process.env.WHSEC }],
onDeliveryError: ({ endpoint, error }) => log(endpoint.url, error)
}
});
// Verify on the receiving end (Svix-compatible):
const ok = await verifyWebhookSignature({
headers: request.headers, // webhook-id / webhook-timestamp / webhook-signature
payload: await request.text(),
secret: process.env.WHSEC
});