use crate::claims::Claims;
use crate::error::Result;
use crate::signer::{Algorithm, JwtSigner};
const TOKEN_ENDPOINT: &str = "https://oauth2.googleapis.com/token";
pub struct GoogleServiceAccountJwt {
email: String,
pem_bytes: Vec<u8>,
scope: Option<String>,
}
impl GoogleServiceAccountJwt {
pub fn new(email: impl Into<String>, pem_bytes: impl Into<Vec<u8>>) -> Self {
Self {
email: email.into(),
pem_bytes: pem_bytes.into(),
scope: None,
}
}
pub fn scope(mut self, scope: impl Into<String>) -> Self {
self.scope = Some(scope.into());
self
}
pub async fn generate(&self) -> Result<String> {
let now = now_unix_secs();
let mut claims = Claims {
iss: Some(self.email.clone()),
aud: Some(TOKEN_ENDPOINT.into()),
iat: Some(now),
exp: Some(now + 3600),
..Default::default()
};
if let Some(scope) = &self.scope {
claims
.extra
.insert("scope".into(), serde_json::Value::String(scope.clone()));
}
let signer = JwtSigner::new(Algorithm::Rs256, &self.pem_bytes).await?;
signer.sign(&claims).await
}
}
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
fn now_unix_secs() -> u64 {
(js_sys::Date::now() / 1000.0) as u64
}
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
fn now_unix_secs() -> u64 {
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.expect("system clock before UNIX epoch")
.as_secs()
}