inth_oauth2_async/token/
bearer.rs1use serde_json::Value;
2
3use crate::client::response::{FromResponse, ParseError};
4use crate::token::{Token, Lifetime};
5
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
10pub struct Bearer<L: Lifetime> {
11 access_token: String,
12 scope: Option<String>,
13 id_token: Option<String>,
14 lifetime: L,
15}
16
17impl<L: Lifetime> Token<L> for Bearer<L> {
18 fn access_token(&self) -> &str {
19 &self.access_token
20 }
21 fn scope(&self) -> Option<&str> {
22 self.scope.as_ref().map(|s| &s[..])
23 }
24 fn id_token(&self) -> Option<&str> {
25 self.id_token.as_ref().map(|s| &s[..])
26 }
27 fn lifetime(&self) -> &L {
28 &self.lifetime
29 }
30}
31
32impl<L: Lifetime> Bearer<L> {
33 fn from_response_and_lifetime(json: &Value, lifetime: L) -> Result<Self, ParseError> {
34 let obj = json.as_object().ok_or(ParseError::ExpectedType("object"))?;
35
36 let token_type = obj.get("token_type")
37 .and_then(Value::as_str)
38 .ok_or(ParseError::ExpectedFieldType("token_type", "string"))?;
39 if token_type != "Bearer" && token_type != "bearer" {
40 return Err(ParseError::ExpectedFieldValue("token_type", "Bearer"));
41 }
42
43 let access_token = obj.get("access_token")
44 .and_then(Value::as_str)
45 .ok_or(ParseError::ExpectedFieldType("access_token", "string"))?;
46 let scope = obj.get("scope").and_then(Value::as_str);
47 let id_token = obj.get("id_token").and_then(Value::as_str);
48
49 Ok(Bearer {
50 access_token: access_token.into(),
51 scope: scope.map(Into::into),
52 id_token: id_token.map(Into::into),
53 lifetime,
54 })
55 }
56}
57
58impl<L: Lifetime> FromResponse for Bearer<L> {
59 fn from_response(json: &Value) -> Result<Self, ParseError> {
60 let lifetime = FromResponse::from_response(json)?;
61 Bearer::from_response_and_lifetime(json, lifetime)
62 }
63
64 fn from_response_inherit(json: &Value, prev: &Self) -> Result<Self, ParseError> {
65 let lifetime = FromResponse::from_response_inherit(json, &prev.lifetime)?;
66 Bearer::from_response_and_lifetime(json, lifetime)
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73 use crate::token::{Bearer, Refresh, Static};
74 use std::time::{Duration, SystemTime};
75
76 #[test]
77 fn from_response_with_invalid_token_type() {
78 let json = r#"{"token_type":"MAC","access_token":"aaaaaaaa"}"#.parse().unwrap();
79 assert_eq!(
80 ParseError::ExpectedFieldValue("token_type", "Bearer"),
81 Bearer::<Static>::from_response(&json).unwrap_err()
82 );
83 }
84
85 #[test]
86 fn from_response_capital_b() {
87 let json = r#"{"token_type":"Bearer","access_token":"aaaaaaaa"}"#.parse().unwrap();
88 assert_eq!(
89 Bearer {
90 access_token: String::from("aaaaaaaa"),
91 scope: None,
92 id_token: None,
93 lifetime: Static,
94 },
95 Bearer::<Static>::from_response(&json).unwrap()
96 );
97 }
98
99 #[test]
100 fn from_response_little_b() {
101 let json = r#"{"token_type":"bearer","access_token":"aaaaaaaa"}"#.parse().unwrap();
102 assert_eq!(
103 Bearer {
104 access_token: String::from("aaaaaaaa"),
105 scope: None,
106 id_token: None,
107 lifetime: Static,
108 },
109 Bearer::<Static>::from_response(&json).unwrap()
110 );
111 }
112
113 #[test]
114 fn from_response_with_scope() {
115 let json = r#"{"token_type":"Bearer","access_token":"aaaaaaaa","scope":"foo"}"#
116 .parse()
117 .unwrap();
118 assert_eq!(
119 Bearer {
120 access_token: String::from("aaaaaaaa"),
121 scope: Some(String::from("foo")),
122 id_token: None,
123 lifetime: Static,
124 },
125 Bearer::<Static>::from_response(&json).unwrap()
126 );
127 }
128
129 #[test]
130 fn from_response_refresh() {
131 let json = r#"
132 {
133 "token_type":"Bearer",
134 "access_token":"aaaaaaaa",
135 "expires_in":3600,
136 "refresh_token":"bbbbbbbb"
137 }
138 "#.parse().unwrap();
139 let bearer = Bearer::<Refresh>::from_response(&json).unwrap();
140 assert_eq!("aaaaaaaa", bearer.access_token);
141 assert_eq!(None, bearer.scope);
142 let refresh = bearer.lifetime;
143 assert_eq!("bbbbbbbb", refresh.refresh_token());
144 assert!(refresh.expires() > SystemTime::now());
145 assert!(refresh.expires() <= SystemTime::now() + Duration::from_secs(3600));
146 }
147
148 #[test]
149 fn from_response_refresh_idtoken() {
150 let json = r#"
151 {
152 "token_type":"Bearer",
153 "access_token":"aaaaaaaa",
154 "expires_in":3600,
155 "refresh_token":"bbbbbbbb",
156 "id_token":"zzzzzzzzz"
157 }
158 "#.parse().unwrap();
159 let bearer = Bearer::<Refresh>::from_response(&json).unwrap();
160 assert_eq!("aaaaaaaa", bearer.access_token);
161 assert_eq!(None, bearer.scope);
162 let refresh = bearer.lifetime;
163 assert_eq!("bbbbbbbb", refresh.refresh_token());
164 assert!(refresh.expires() > SystemTime::now());
165 assert!(refresh.expires() <= SystemTime::now() + Duration::from_secs(3600));
166 assert_eq!(Some("zzzzzzzzz".to_owned()), bearer.id_token);
167 }
168
169 #[test]
170 fn from_response_inherit_refresh() {
171 let json = r#"
172 {
173 "token_type":"Bearer",
174 "access_token":"aaaaaaaa",
175 "expires_in":3600,
176 "refresh_token":"bbbbbbbb"
177 }
178 "#.parse().unwrap();
179 let prev = Bearer::<Refresh>::from_response(&json).unwrap();
180
181 let json = r#"
182 {
183 "token_type":"Bearer",
184 "access_token":"cccccccc",
185 "expires_in":3600
186 }
187 "#.parse().unwrap();
188 let bearer = Bearer::<Refresh>::from_response_inherit(&json, &prev).unwrap();
189 assert_eq!("cccccccc", bearer.access_token);
190 assert_eq!(None, bearer.scope);
191 let refresh = bearer.lifetime;
192 assert_eq!("bbbbbbbb", refresh.refresh_token());
193 assert!(refresh.expires() > SystemTime::now());
194 assert!(refresh.expires() <= SystemTime::now() + Duration::from_secs(3600));
195 }
196}