beep_auth/domain/models/
claims.rs1use 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}