gcloud_auth/token_source/
authorized_user_token_source.rs

1use async_trait::async_trait;
2
3use crate::credentials;
4use crate::error::Error;
5use crate::misc::{UnwrapOrEmpty, EMPTY};
6use crate::token::{Token, TOKEN_URL};
7use crate::token_source::TokenSource;
8use crate::token_source::{default_http_client, InternalToken};
9
10#[allow(dead_code)]
11#[derive(Debug)]
12pub struct UserAccountTokenSource {
13    client_id: String,
14    client_secret: String,
15    token_url: String,
16    redirect_url: String,
17    refresh_token: String,
18
19    client: reqwest::Client,
20}
21
22impl UserAccountTokenSource {
23    pub(crate) fn new(cred: &credentials::CredentialsFile) -> Result<UserAccountTokenSource, Error> {
24        if cred.refresh_token.is_none() {
25            return Err(Error::RefreshTokenIsRequired);
26        }
27
28        let ts = UserAccountTokenSource {
29            client_id: cred.client_id.unwrap_or_empty(),
30            client_secret: cred.client_secret.unwrap_or_empty(),
31            token_url: match &cred.token_uri {
32                None => TOKEN_URL.to_string(),
33                Some(s) => s.to_string(),
34            },
35            redirect_url: EMPTY.to_string(),
36            refresh_token: cred.refresh_token.unwrap_or_empty(),
37            client: default_http_client(),
38        };
39        Ok(ts)
40    }
41}
42
43#[derive(serde::Serialize)]
44struct RequestBody<'a> {
45    pub client_id: &'a str,
46    pub client_secret: &'a str,
47    pub grant_type: &'a str,
48    pub refresh_token: &'a str,
49}
50
51#[async_trait]
52impl TokenSource for UserAccountTokenSource {
53    async fn token(&self) -> Result<Token, Error> {
54        let data = RequestBody {
55            client_id: &self.client_id,
56            client_secret: &self.client_secret,
57            grant_type: "refresh_token",
58            refresh_token: &self.refresh_token,
59        };
60
61        let it = self
62            .client
63            .post(self.token_url.to_string())
64            .json(&data)
65            .send()
66            .await?
67            .json::<InternalToken>()
68            .await?;
69
70        return Ok(it.to_token(time::OffsetDateTime::now_utc()));
71    }
72}