Auth Service — Event Schemas
Status: populated Owner: Platform Engineering + Security Last updated: 2026-04-19
Change log
- v1.2 (2026-04-19) — Added SSO / multi-IdP events:
auth.idp.configured.v1,auth.idp.disabled.v1,auth.idp.removed.v1,auth.external_identity.linked.v1,auth.external_identity.unlinked.v1,auth.sso.session.started.v1,auth.sso.session.failed.v1.auth.user.logged_in.v1.methodwidened to include provider ids.
1. Produced
| Subject | Stream | Retention |
|---|---|---|
auth.user.registered.v1 | AUTH_EVENTS | 30d |
auth.user.logged_in.v1 | AUTH_EVENTS | 7d |
auth.user.locked.v1 | AUTH_EVENTS | 30d |
auth.user.erased.v1 | AUTH_EVENTS | 365d (audit) |
auth.api_key.issued.v1 | AUTH_EVENTS | 30d |
auth.api_key.revoked.v1 | AUTH_EVENTS | 30d |
auth.api_key.rotated.v1 | AUTH_EVENTS | 30d |
auth.jwks.rotated.v1 | AUTH_EVENTS | 90d |
auth.role.assigned.v1 | AUTH_EVENTS | 30d |
auth.idp.configured.v1 | AUTH_EVENTS | 365d (audit) |
auth.idp.disabled.v1 | AUTH_EVENTS | 365d (audit) |
auth.idp.removed.v1 | AUTH_EVENTS | 365d (audit) |
auth.external_identity.linked.v1 | AUTH_EVENTS | 90d |
auth.external_identity.unlinked.v1 | AUTH_EVENTS | 90d |
auth.sso.session.started.v1 | AUTH_EVENTS | 30d |
auth.sso.session.failed.v1 | AUTH_EVENTS | 90d (security) |
2. Schemas (examples)
auth.user.logged_in.v1
interface UserLoggedIn {
schemaVersion: '1';
userId: string;
accountId: string;
tenantId: string;
providerId: string; // 'keycloak' | 'tenant-oidc:<tid>' | 'tenant-saml:<tid>' | 'firebase-legacy' | 'native' | 'api_key'
method: 'password' | 'oidc' | 'saml' | 'firebase' | 'api_key';
mfa: boolean;
ip: string; // hashed in downstream
userAgent: string;
at: string;
}
auth.idp.configured.v1
interface IdpConfigured {
schemaVersion: '1';
providerId: string;
tenantId: string;
kind: 'oidc' | 'saml' | 'firebase';
discoveryUrl?: string;
metadataRef?: string;
keycloakIdpAlias?: string;
isDefault: boolean;
configuredBy: string; // userId
at: string;
}
auth.external_identity.linked.v1
interface ExternalIdentityLinked {
schemaVersion: '1';
userId: string;
tenantId: string;
providerId: string;
externalSubjectHash: string; // sha256 of external sub; raw sub never emitted
at: string;
}
auth.sso.session.failed.v1
interface SsoSessionFailed {
schemaVersion: '1';
providerId: string;
tenantId: string;
reason: 'signature_invalid' | 'issuer_mismatch' | 'reserved_domain' | 'claims_incomplete' | 'replay' | 'other';
ip: string; // hashed downstream
userAgent: string;
traceId: string;
at: string;
}
auth.api_key.issued.v1
interface ApiKeyIssued {
schemaVersion: '1';
keyId: string;
accountId: string;
tenantId: string;
scopes: string[];
createdBy: string; // userId
expiresAt?: string;
at: string;
// NOTE: never include the raw key
}
auth.jwks.rotated.v1
interface JwksRotated {
schemaVersion: '1';
previousKid: string;
newActiveKid: string;
retiringKid: string;
at: string;
}
3. Consumed
| Subject | Producer | Purpose |
|---|---|---|
tenant.erased.v1 (if tenant-service exists later) | tenant-service | Cascade user / account erasure |
4. PII
email,userId,ipare PII. Downstream consumers must not persist unmasked.iphashed in analytics.- No passwords, password hashes, or raw API keys in any event.
5. Outbox pattern
User / account / api-key changes use transactional outbox: write event row to auth.outbox in same PG transaction as aggregate change; publisher relay publishes to NATS with retry + ACK.