gcloud_auth/token_source/
authorized_user_token_source.rs1use 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}