From 08062cdbc54ef33df1b3b4dbdc2f9189afa49742 Mon Sep 17 00:00:00 2001 From: Roland Rodriguez Date: Wed, 27 May 2026 20:18:38 -0500 Subject: [PATCH] fix(audit): attach jti to AuthTokenRevoked event metadata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit paseto.rs and jwt.rs both emit AuthTokenRevoked when a revoked token is presented, but only set source.subject — the JTI of the revoked token, which is the natural correlation key for SIEM rules, retroactive search ("show every request that presented this token"), and revocation-list audit, was in scope at the emission site but dropped before the event was constructed. log_auth(kind, severity, source) is the convenience wrapper that doesn't accept metadata. Switch the two emission sites to build the AuditEvent explicitly with AuditEvent::new(...).with_source(source) .with_metadata(json!({"jti": jti})) and call logger.log(event) directly. No API widening; matches the pattern already used by AuditAccountNotification. Closes #18. AuthTokenInvalid enrichment (kid/iss/sub from the decode error) is a separate, more invasive change tracked under #16 / future work. --- acton-service/src/middleware/jwt.rs | 15 ++++++++------- acton-service/src/middleware/paseto.rs | 15 ++++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/acton-service/src/middleware/jwt.rs b/acton-service/src/middleware/jwt.rs index ca60c4c..cbd7688 100644 --- a/acton-service/src/middleware/jwt.rs +++ b/acton-service/src/middleware/jwt.rs @@ -243,13 +243,14 @@ impl JwtAuth { if logger.config().audit_auth_events { let mut source = audit_source.clone(); source.subject = Some(claims.sub.clone()); - logger - .log_auth( - crate::audit::event::AuditEventKind::AuthTokenRevoked, - crate::audit::event::AuditSeverity::Warning, - source, - ) - .await; + let event = crate::audit::event::AuditEvent::new( + crate::audit::event::AuditEventKind::AuthTokenRevoked, + crate::audit::event::AuditSeverity::Warning, + logger.service_name().to_string(), + ) + .with_source(source) + .with_metadata(serde_json::json!({ "jti": jti })); + logger.log(event).await; } } return Err(Error::Unauthorized("Token has been revoked".to_string())); diff --git a/acton-service/src/middleware/paseto.rs b/acton-service/src/middleware/paseto.rs index 838b0c2..5a578f0 100644 --- a/acton-service/src/middleware/paseto.rs +++ b/acton-service/src/middleware/paseto.rs @@ -256,13 +256,14 @@ impl PasetoAuth { if logger.config().audit_auth_events { let mut source = audit_source.clone(); source.subject = Some(claims.sub.clone()); - logger - .log_auth( - crate::audit::event::AuditEventKind::AuthTokenRevoked, - crate::audit::event::AuditSeverity::Warning, - source, - ) - .await; + let event = crate::audit::event::AuditEvent::new( + crate::audit::event::AuditEventKind::AuthTokenRevoked, + crate::audit::event::AuditSeverity::Warning, + logger.service_name().to_string(), + ) + .with_source(source) + .with_metadata(serde_json::json!({ "jti": jti })); + logger.log(event).await; } } return Err(Error::Unauthorized("Token has been revoked".to_string()));