Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return the latest token instead of panicking, even if it's expired #1

Merged
merged 1 commit into from
Aug 20, 2020
Merged

Conversation

d0x2f
Copy link
Contributor

@d0x2f d0x2f commented Aug 20, 2020

When running in cloudrun, the metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token endpoint will cache an access token until it's 60s from expiry. This project also considers a token to be expired 60 seconds before the real expiry.

This causes an issue in that there is a short period of time between the lib considering the token to be expired and the cloud run endpoint returning a new one. During this time the library panics with Token obtained with refresh or failed before. This happens consistently every 30 minutes in my project.

This pull request changes two things:

  1. Don't consider the token to be expired until 30 seconds before true expiry - This allows ample time for the cloudrun endpoint to generate a new token.
  2. Return the token even if it's considered expired instead of panicking - On top of preventing a panic, this also allows library users to handle an expired (or close to expired) token however they wish.

PS: Thanks for the super handy lib 👍

@d0x2f d0x2f changed the title Return the latest token instead of panicing, even if it's expired Return the latest token instead of panicking, even if it's expired Aug 20, 2020
Copy link
Collaborator

@hrvolapeter hrvolapeter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @d0x2f for the contribution. I wasn't even sure if anyone except me is using this 🙂

The change with timeout makes perfect sense.

@@ -22,7 +22,8 @@ impl AuthenticationManager {
pub async fn get_token(&self, scopes: &[&str]) -> Result<Token, GCPAuthError> {
let mut sa = self.service_account.lock().await;
let mut token = sa.get_token(scopes);
if token.is_none() {

if token.is_none() || token.clone().unwrap().has_expired() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current code is just refactor as it keeps the same functionality (returning library error after refresh returned invalid token)

@hrvolapeter
Copy link
Collaborator

I'll merge you current changes as they don't change handling of the expired token, except the timeout.

To the second point the current behaviour (even after your PR) is that after token refresh failure the library returns GCPAuthError error not panic, if I'm wrong and you see potential panic somewhere please correct me. If you still want to implement the change I think we can return error with token here https://github.com/hrvolapeter/gcp_auth/blob/master/src/authentication_manager.rs#L30 but my thinking was that token is anyway invalid so it doesn't really make sense to return it

@hrvolapeter hrvolapeter merged commit fbbf613 into djc:master Aug 20, 2020
@d0x2f
Copy link
Contributor Author

d0x2f commented Aug 21, 2020

Thank you for merging!

let mut token = sa.get_token(scopes);

if token.is_none() || token.clone().unwrap().has_expired() {
    sa.refresh_token(&self.client, scopes).await?;
    token = sa.get_token(scopes);
}

Ok(token.expect("Token obtained with refresh or failed before"))

Regarding point 2, previously if the token was considered expired the token.expect("Token obtained with refresh or failed before") line would trigger a panic.
Now though, the only case in which get_token returns None is if a CustomServiceAccount hasn't yet requested a token, but after a successful call to refresh_token we can safely expect it not to be None.

@hrvolapeter
Copy link
Collaborator

Oh sorry, I totally missed that. I've got confused with anyhow! which would return string error but you're right that this code panics. I'll check later and refactor it to also return GCPAuthError

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants