modkit_auth/standard_claims.rs
1//! Standard JWT claim names as defined in RFC 7519.
2//!
3//! This module provides type-safe constants for standard JWT claim names,
4//! reducing the risk of typos and providing a central place for claim name definitions.
5//!
6//! # References
7//! - [RFC 7519 - JSON Web Token (JWT)](https://datatracker.ietf.org/doc/html/rfc7519)
8//! - [IANA JWT Claims Registry](https://www.iana.org/assignments/jwt/jwt.xhtml)
9
10/// Standard JWT claim names as defined in RFC 7519 and OIDC specifications.
11///
12/// This struct provides constants for standard claim names used in JWT tokens.
13/// Using these constants instead of string literals helps prevent typos and
14/// provides a single source of truth for claim names.
15///
16/// # Example
17/// ```
18/// use modkit_auth::StandardClaim;
19/// use serde_json::json;
20///
21/// let claims = json!({
22/// "sub": "user-123",
23/// "iss": "https://auth.example.com"
24/// });
25///
26/// let subject = claims.get(StandardClaim::SUB);
27/// let issuer = claims.get(StandardClaim::ISS);
28/// ```
29pub struct StandardClaim;
30
31impl StandardClaim {
32 // =========================================================================
33 // RFC 7519 Registered Claims (Section 4.1)
34 // =========================================================================
35
36 /// Issuer claim - identifies the principal that issued the JWT.
37 ///
38 /// The "iss" (issuer) claim identifies the principal that issued the JWT.
39 /// The processing of this claim is generally application specific.
40 ///
41 /// See: <https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1>
42 pub const ISS: &'static str = "iss";
43
44 /// Subject claim - identifies the principal that is the subject of the JWT.
45 ///
46 /// The "sub" (subject) claim identifies the principal that is the subject
47 /// of the JWT. The claims in a JWT are normally statements about the subject.
48 ///
49 /// See: <https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.2>
50 pub const SUB: &'static str = "sub";
51
52 /// Audience claim - identifies the recipients that the JWT is intended for.
53 ///
54 /// The "aud" (audience) claim identifies the recipients that the JWT is
55 /// intended for. Each principal intended to process the JWT MUST identify
56 /// itself with a value in the audience claim.
57 ///
58 /// See: <https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3>
59 pub const AUD: &'static str = "aud";
60
61 /// Expiration Time claim - identifies the expiration time of the JWT.
62 ///
63 /// The "exp" (expiration time) claim identifies the expiration time on
64 /// or after which the JWT MUST NOT be accepted for processing.
65 ///
66 /// See: <https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4>
67 pub const EXP: &'static str = "exp";
68
69 /// Not Before claim - identifies the time before which the JWT must not be accepted.
70 ///
71 /// The "nbf" (not before) claim identifies the time before which the JWT
72 /// MUST NOT be accepted for processing.
73 ///
74 /// See: <https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5>
75 pub const NBF: &'static str = "nbf";
76
77 /// Issued At claim - identifies the time at which the JWT was issued.
78 ///
79 /// The "iat" (issued at) claim identifies the time at which the JWT was issued.
80 /// This claim can be used to determine the age of the JWT.
81 ///
82 /// See: <https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6>
83 pub const IAT: &'static str = "iat";
84
85 /// JWT ID claim - provides a unique identifier for the JWT.
86 ///
87 /// The "jti" (JWT ID) claim provides a unique identifier for the JWT.
88 /// The identifier value MUST be assigned in a manner that ensures that
89 /// there is a negligible probability that the same value will be
90 /// accidentally assigned to a different data object.
91 ///
92 /// See: <https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.7>
93 pub const JTI: &'static str = "jti";
94
95 // =========================================================================
96 // OpenID Connect Claims
97 // =========================================================================
98
99 /// Authorized party claim - the party to which the ID Token was issued.
100 ///
101 /// The "azp" (authorized party) claim identifies the party to which the
102 /// ID Token was issued. If present, it MUST contain the OAuth 2.0 Client ID
103 /// of this party.
104 ///
105 /// See: <https://openid.net/specs/openid-connect-core-1_0.html#IDToken>
106 pub const AZP: &'static str = "azp";
107
108 /// Returns a slice containing all standard JWT claim names (RFC 7519).
109 ///
110 /// This is useful for filtering out standard claims when collecting
111 /// extra/custom claims from a token.
112 #[must_use]
113 pub const fn all_registered() -> &'static [&'static str] {
114 &[
115 Self::ISS,
116 Self::SUB,
117 Self::AUD,
118 Self::EXP,
119 Self::NBF,
120 Self::IAT,
121 Self::JTI,
122 Self::AZP,
123 ]
124 }
125
126 /// Checks if the given claim name is a standard registered claim.
127 #[must_use]
128 pub fn is_registered(name: &str) -> bool {
129 Self::all_registered().contains(&name)
130 }
131}
132
133#[cfg(test)]
134#[cfg_attr(coverage_nightly, coverage(off))]
135mod tests {
136 use super::*;
137
138 #[test]
139 fn test_claim_constants() {
140 assert_eq!(StandardClaim::ISS, "iss");
141 assert_eq!(StandardClaim::SUB, "sub");
142 assert_eq!(StandardClaim::AUD, "aud");
143 assert_eq!(StandardClaim::EXP, "exp");
144 assert_eq!(StandardClaim::NBF, "nbf");
145 assert_eq!(StandardClaim::IAT, "iat");
146 assert_eq!(StandardClaim::JTI, "jti");
147 assert_eq!(StandardClaim::AZP, "azp");
148 }
149
150 #[test]
151 fn test_all_registered() {
152 let all = StandardClaim::all_registered();
153 assert_eq!(all.len(), 8);
154 assert!(all.contains(&"iss"));
155 assert!(all.contains(&"sub"));
156 assert!(all.contains(&"aud"));
157 assert!(all.contains(&"exp"));
158 assert!(all.contains(&"nbf"));
159 assert!(all.contains(&"iat"));
160 assert!(all.contains(&"jti"));
161 assert!(all.contains(&"azp"));
162 }
163
164 #[test]
165 fn test_is_registered() {
166 assert!(StandardClaim::is_registered("iss"));
167 assert!(StandardClaim::is_registered("sub"));
168 assert!(StandardClaim::is_registered("azp"));
169 assert!(!StandardClaim::is_registered("custom_claim"));
170 assert!(!StandardClaim::is_registered("tenant_id"));
171 assert!(!StandardClaim::is_registered("roles"));
172 }
173}