service_authenticator/
types.rs1use crate::error::{AuthErrorOr, Error};
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5
6#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
9pub struct AccessToken {
10 value: String,
11 expires_at: Option<DateTime<Utc>>,
12}
13
14impl AccessToken {
15 pub fn as_str(&self) -> &str {
17 &self.value
18 }
19
20 pub fn expiration_time(&self) -> Option<DateTime<Utc>> {
22 self.expires_at
23 }
24
25 pub fn is_expired(&self) -> bool {
30 self
33 .expires_at
34 .map(|expiration_time| expiration_time - chrono::Duration::minutes(1) <= Utc::now())
35 .unwrap_or(false)
36 }
37}
38
39impl AsRef<str> for AccessToken {
40 fn as_ref(&self) -> &str {
41 self.as_str()
42 }
43}
44
45impl From<TokenInfo> for AccessToken {
46 fn from(value: TokenInfo) -> Self {
47 AccessToken {
48 value: value.access_token,
49 expires_at: value.expires_at,
50 }
51 }
52}
53
54#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
60pub(crate) struct TokenInfo {
61 pub(crate) access_token: String,
63 pub(crate) refresh_token: Option<String>,
65 pub(crate) expires_at: Option<DateTime<Utc>>,
67}
68
69impl TokenInfo {
70 pub(crate) fn from_json(json_data: &[u8]) -> Result<TokenInfo, Error> {
71 #[derive(Deserialize)]
72 struct RawToken {
73 access_token: String,
74 refresh_token: Option<String>,
75 token_type: String,
76 expires_in: Option<i64>,
77 }
78
79 let RawToken {
80 access_token,
81 refresh_token,
82 token_type,
83 expires_in,
84 } = serde_json::from_slice::<AuthErrorOr<RawToken>>(json_data)?.into_result()?;
85
86 if token_type.to_lowercase().as_str() != "bearer" {
87 use std::io;
88 return Err(
89 io::Error::new(
90 io::ErrorKind::InvalidData,
91 format!(
92 r#"unknown token type returned; expected "bearer" found {}"#,
93 token_type
94 ),
95 )
96 .into(),
97 );
98 }
99
100 let expires_at =
101 expires_in.map(|seconds_from_now| Utc::now() + chrono::Duration::seconds(seconds_from_now));
102
103 Ok(TokenInfo {
104 access_token,
105 refresh_token,
106 expires_at,
107 })
108 }
109 pub fn is_expired(&self) -> bool {
111 self
112 .expires_at
113 .map(|expiration_time| expiration_time - chrono::Duration::minutes(1) <= Utc::now())
114 .unwrap_or(false)
115 }
116}