gcloud_sdk/token_source/
auth_token_generator.rs

1use std::sync::Arc;
2
3use chrono::prelude::*;
4use tokio::sync::RwLock;
5
6use crate::token_source::*;
7use tracing::*;
8
9pub struct GoogleAuthTokenGenerator {
10    token_source: BoxSource,
11    cached_token: Arc<RwLock<Option<Token>>>,
12}
13
14impl GoogleAuthTokenGenerator {
15    pub async fn new(
16        token_source_type: TokenSourceType,
17        token_scopes: Vec<String>,
18    ) -> crate::error::Result<GoogleAuthTokenGenerator> {
19        let token_source: BoxSource = create_source(token_source_type, token_scopes).await?;
20
21        Ok(GoogleAuthTokenGenerator {
22            token_source,
23            cached_token: Arc::new(RwLock::new(None)),
24        })
25    }
26
27    pub async fn clear_cache(&self) {
28        let mut write_state = self.cached_token.write().await;
29        *write_state = None;
30    }
31
32    pub async fn create_token(&self) -> crate::error::Result<Token> {
33        let existing_token: Option<Token> = {
34            let read_state = self.cached_token.read().await;
35            read_state.clone()
36        };
37
38        let now = Utc::now();
39
40        match existing_token {
41            // Give a bit more time for network call
42            Some(token) if token.expiry.gt(&now.add(chrono::Duration::seconds(15))) => Ok(token),
43            _ => {
44                let new_token = {
45                    let mut write_token = self.cached_token.write().await;
46
47                    match write_token.as_ref() {
48                        Some(updated_token) if updated_token.expiry.gt(&now) => {
49                            updated_token.clone()
50                        }
51                        _ => {
52                            let new_token = self.token_source.token().await?;
53                            *write_token = Some(new_token.clone());
54                            debug!(
55                                "Created a new Google OAuth token. Type: {}. Expiring: {}.",
56                                new_token.token_type, new_token.expiry,
57                            );
58                            new_token
59                        }
60                    }
61                };
62                Ok(new_token)
63            }
64        }
65    }
66}