google_auth 0.2.1

get google default credentials
Documentation
use crate::credentials::Credentials;
use anyhow::Result;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize, Debug, Clone)]
pub(crate) struct TokenValue {
    access_token: String,
    expires_in: i64,
    scope: Option<String>,
    token_type: String,
    id_token: Option<String>,
}

#[derive(Clone, Debug)]
pub(crate) struct Token {
    token_value: TokenValue,
    expiry: DateTime<Utc>,
}

impl Token {
    pub fn new(token_value: TokenValue) -> Self {
        let expiry = Self::get_expiry(token_value.expires_in);
        Self {
            token_value,
            expiry,
        }
    }
    fn is_expired(&self) -> bool {
        let now = Utc::now();
        self.expiry <= now
    }
    fn get_expiry(expires_in: i64) -> DateTime<Utc> {
        let duration = chrono::Duration::seconds((expires_in as f64 * 0.75) as i64);
        Utc::now() + duration
    }
    fn get_access_token(&self) -> String {
        format!("Bearer {}", self.token_value.access_token)
    }
}

#[derive(Deserialize, Serialize, Debug)]
struct VerifyResponse {
    azp: String,
    aud: String,
    sub: Option<String>,
    scope: String,
    exp: String,
    expires_in: String,
    email: Option<String>,
    email_verified: Option<String>,
    access_type: String,
}

#[derive(Clone, Debug)]
pub struct TokenManager {
    credentials: Credentials,
    current_token: Token,
}

impl TokenManager {
    pub async fn new(scopes: &[&str]) -> Result<Self> {
        let cred = Credentials::new(scopes).await?;
        let token = cred.token().await?;
        Ok(Self {
            credentials: cred,
            current_token: token,
        })
    }
    pub async fn token(&mut self) -> Result<String> {
        if self.current_token.is_expired() {
            self.current_token = self.credentials.token().await?;
        }
        Ok(self.current_token.get_access_token())
    }
}