beep_auth/domain/models/
claims.rs

1use serde::{Deserialize, Serialize};
2
3use crate::domain::models::Token;
4
5#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
6pub struct Role(pub String);
7
8#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
9pub struct Scope(pub String);
10
11#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
12pub struct Subject(pub String);
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct Claims {
16    pub sub: Subject,
17    pub iss: String,
18    pub aud: Option<String>,
19    pub exp: Option<i64>,
20
21    pub email: Option<String>,
22    pub email_verified: bool,
23    pub name: Option<String>,
24    pub preferred_username: String,
25    pub given_name: Option<String>,
26    pub family_name: Option<String>,
27    pub scope: String,
28    pub client_id: Option<String>,
29
30    #[serde(flatten)]
31    pub extra: serde_json::Map<String, serde_json::Value>,
32}
33
34#[derive(Debug, Deserialize, Serialize)]
35pub struct Jwt {
36    pub claims: Claims,
37    pub token: Token,
38}
39
40#[cfg(test)]
41mod tests {
42    use crate::domain::models::claims::{Claims, Role, Scope, Subject};
43
44    #[test]
45    fn test_subject_deserialize_from_json() {
46        let json = r#""user-123""#;
47        let subject: Subject = serde_json::from_str(json).unwrap();
48
49        assert_eq!(subject.0, "user-123");
50    }
51
52    #[test]
53    fn test_role_deserialize_from_json() {
54        let json = r#""admin""#;
55        let role: Role = serde_json::from_str(json).unwrap();
56        assert_eq!(role.0, "admin");
57    }
58
59    #[test]
60    fn test_scope_deserialize_from_json() {
61        let json = r#""read:users""#;
62        let scope: Scope = serde_json::from_str(json).unwrap();
63        assert_eq!(scope.0, "read:users");
64    }
65
66    #[test]
67    fn test_claims_deserialize_basic() {
68        let json = r#"{
69            "exp": 1761117956,
70            "iat": 1761117896,
71            "jti": "onrtro:2a23cb92-7519-c83a-00c6-b144299db155",
72            "iss": "http://localhost:8000/realms/master",
73            "aud": "account",
74            "sub": "14434cba-8f32-49bb-a39e-8378a7cddea3",
75            "typ": "Bearer",
76            "azp": "api",
77            "sid": "f6b50ef6-2e62-6015-e52c-097085e2a018",
78            "acr": "1",
79            "allowed-origins": [
80              "/*"
81            ],
82            "realm_access": {
83              "roles": [
84                "default-roles-master",
85                "offline_access",
86                "uma_authorization"
87              ]
88            },
89            "resource_access": {
90              "account": {
91                "roles": [
92                  "manage-account",
93                  "manage-account-links",
94                  "view-profile"
95                ]
96              }
97            },
98            "scope": "profile email",
99            "email_verified": true,
100            "name": "Nathael Bonnal",
101            "preferred_username": "nathael",
102            "given_name": "Nathael",
103            "family_name": "Bonnal",
104            "email": "nathael@bonnal.cloud"
105        }"#;
106
107        let claims: Claims = serde_json::from_str(json).unwrap();
108
109        assert_eq!(claims.sub.0, "14434cba-8f32-49bb-a39e-8378a7cddea3");
110        assert_eq!(claims.iss, "http://localhost:8000/realms/master");
111        assert_eq!(claims.aud.unwrap(), "account");
112        assert_eq!(claims.exp.unwrap(), 1761117956);
113    }
114
115    #[test]
116    fn test_claims_with_extra_fields() {
117        let json = r#"{
118            "sub": "user-456",
119            "iss": "https://auth.beep.com",
120            "exp": 1735689600,
121            "email": null,
122            "scope": "openid connect",
123            "preferred_username": "johndoe",
124            "email_verified": true,
125            "name": "John Doe",
126            "custom_field": "custom_value",
127            "nested": {
128                "data": "test"
129            }
130        }"#;
131
132        let claims: Claims = serde_json::from_str(json).unwrap();
133
134        assert_eq!(claims.sub.0, "user-456");
135        assert_eq!(claims.email, None);
136
137        assert_eq!(
138            claims.extra.get("custom_field").unwrap().as_str().unwrap(),
139            "custom_value"
140        );
141        assert!(claims.extra.contains_key("nested"));
142    }
143}