From 7c248be15376288a170b23d4056d1ac3102530a6 Mon Sep 17 00:00:00 2001 From: ave Date: Thu, 4 Jun 2026 16:37:15 +0000 Subject: [PATCH] fix(auth): emit uppercase "JWT" typ in service-auth header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RFC 7519 §5.1 recommends the uppercase "JWT" typ for compatibility with legacy implementations, and it matches the reference @atproto/pds. Parsing already lowercases, so existing lowercase "jwt" tokens still verify. --- crates/tranquil-auth/src/types.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/crates/tranquil-auth/src/types.rs b/crates/tranquil-auth/src/types.rs index 996fc72..cbd99b8 100644 --- a/crates/tranquil-auth/src/types.rs +++ b/crates/tranquil-auth/src/types.rs @@ -15,7 +15,8 @@ impl TokenType { match self { Self::Access => "at+jwt", Self::Refresh => "refresh+jwt", - Self::Service => "jwt", + // RFC 7519 §5.1 recommends the uppercase "JWT". + Self::Service => "JWT", } } } @@ -290,6 +291,17 @@ mod tests { assert!(TokenType::from_str("bearer").is_err()); } + #[test] + fn service_token_header_serializes_typ_as_uppercase_jwt() { + // RFC 7519 §5.1 recommends the JWT `typ` header value be uppercase "JWT". + let header = Header { + alg: SigningAlgorithm::ES256K, + typ: TokenType::Service, + }; + let json = serde_json::to_string(&header).expect("serialize header"); + assert!(json.contains(r#""typ":"JWT""#), "got {json}"); + } + #[test] fn signing_algorithm_case_insensitive() { assert_eq!(