inth_oauth2_async/token/
bearer.rs

1use serde_json::Value;
2
3use crate::client::response::{FromResponse, ParseError};
4use crate::token::{Token, Lifetime};
5
6/// The bearer token type.
7///
8/// See [RFC 6750](http://tools.ietf.org/html/rfc6750).
9#[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}