Skip to content

Commit d1e8e4e

Browse files
committed
Move Claims type into custom_service_account
1 parent 17e1da7 commit d1e8e4e

File tree

3 files changed

+56
-66
lines changed

3 files changed

+56
-66
lines changed

src/custom_service_account.rs

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use std::path::{Path, PathBuf};
44
use std::sync::RwLock;
55

66
use async_trait::async_trait;
7+
use base64::{engine::general_purpose::URL_SAFE, Engine};
8+
use chrono::Utc;
79
use serde::{Deserialize, Serialize};
810
use tracing::{instrument, Level};
911

@@ -95,8 +97,6 @@ impl ServiceAccount for CustomServiceAccount {
9597

9698
#[instrument(level = Level::DEBUG)]
9799
async fn refresh_token(&self, client: &HyperClient, scopes: &[&str]) -> Result<Token, Error> {
98-
use crate::jwt::Claims;
99-
use crate::jwt::GRANT_TYPE;
100100
use hyper::header;
101101
use url::form_urlencoded;
102102

@@ -136,6 +136,57 @@ impl ServiceAccount for CustomServiceAccount {
136136
}
137137
}
138138

139+
/// Permissions requested for a JWT.
140+
/// See https://developers.google.com/identity/protocols/OAuth2ServiceAccount#authorizingrequests.
141+
#[derive(Serialize, Debug)]
142+
pub(crate) struct Claims<'a> {
143+
iss: &'a str,
144+
aud: &'a str,
145+
exp: i64,
146+
iat: i64,
147+
sub: Option<&'a str>,
148+
scope: String,
149+
}
150+
151+
impl<'a> Claims<'a> {
152+
pub(crate) fn new(
153+
key: &'a ApplicationCredentials,
154+
scopes: &[&str],
155+
sub: Option<&'a str>,
156+
) -> Self {
157+
let mut scope = String::with_capacity(16);
158+
for (i, s) in scopes.iter().enumerate() {
159+
if i != 0 {
160+
scope.push(' ');
161+
}
162+
163+
scope.push_str(s);
164+
}
165+
166+
let iat = Utc::now().timestamp();
167+
Claims {
168+
iss: &key.client_email,
169+
aud: &key.token_uri,
170+
exp: iat + 3600 - 5, // Max validity is 1h
171+
iat,
172+
sub,
173+
scope,
174+
}
175+
}
176+
177+
pub(crate) fn to_jwt(&self, signer: &Signer) -> Result<String, Error> {
178+
let mut jwt = String::new();
179+
URL_SAFE.encode_string(GOOGLE_RS256_HEAD, &mut jwt);
180+
jwt.push('.');
181+
URL_SAFE.encode_string(&serde_json::to_string(self).unwrap(), &mut jwt);
182+
183+
let signature = signer.sign(jwt.as_bytes())?;
184+
jwt.push('.');
185+
URL_SAFE.encode_string(&signature, &mut jwt);
186+
Ok(jwt)
187+
}
188+
}
189+
139190
#[derive(Serialize, Deserialize, Clone)]
140191
pub(crate) struct ApplicationCredentials {
141192
pub(crate) r#type: Option<String>,
@@ -168,5 +219,8 @@ impl fmt::Debug for ApplicationCredentials {
168219
}
169220
}
170221

222+
pub(crate) const GRANT_TYPE: &str = "urn:ietf:params:oauth:grant-type:jwt-bearer";
223+
const GOOGLE_RS256_HEAD: &str = r#"{"alg":"RS256","typ":"JWT"}"#;
224+
171225
/// How many times to attempt to fetch a token from the set credentials token endpoint.
172226
const RETRY_COUNT: u8 = 5;

src/jwt.rs

Lines changed: 0 additions & 63 deletions
This file was deleted.

src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ mod default_authorized_user;
9595
mod default_service_account;
9696
mod error;
9797
mod gcloud_authorized_user;
98-
mod jwt;
9998
mod types;
10099
mod util;
101100

0 commit comments

Comments
 (0)