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

Support audience #99

Closed
aviramha opened this issue Jan 27, 2024 · 4 comments · Fixed by #119
Closed

Support audience #99

aviramha opened this issue Jan 27, 2024 · 4 comments · Fixed by #119

Comments

@aviramha
Copy link

When invoking Cloud Run endpoints, token needs to have audience of the endpoint url.

@djc
Copy link
Owner

djc commented Jan 29, 2024

I'm happy to review a PR for this. Would this be applicable across authentication methods, or only for custom service accounts? If the latter, see discussion in #92.

@djc
Copy link
Owner

djc commented Apr 9, 2024

#106 should provide a clear pattern for this if you're still interested.

@dacozai
Copy link
Contributor

dacozai commented Oct 14, 2024

Hi @djc,
I’d love to give it a try, but I want to clarify one thing:
Q: Should I modify only the custom service account?
Since Cloud Run uses a service account as suggested, does that mean I should modify it in custom_service_account.rs?

Design Review

If so, based on what you suggested #106, I will modify below

pub struct CustomServiceAccount {
    ...
    audience: Option<String>,
}

impl CustomServiceAccount {
    ...
    /// Set the `Audience` to impersonate a user
    pub fn with_audience(mut self, audience: String) -> Self {
        self.audience = Some(audience);
        self
    }

    fn new(credentials: ServiceAccountKey, client: HttpClient) -> Result<Self, Error> {
        debug!(project = ?credentials.project_id, email = credentials.client_email, "found credentials");
        Ok(Self {
            ...
            audience: None,
        })
    }

    async fn fetch_token(&self, scopes: &[&str]) -> Result<Arc<Token>, Error> {
        let jwt =
            Claims::new(&self.credentials, scopes, self.subject.as_deref(), self.audience.as_deref()).to_jwt(&self.signer)?;
        ...
    }
}

impl<'a> Claims<'a> {
    pub(crate) fn new(key: &'a ServiceAccountKey, scopes: &[&str], sub: Option<&'a str>, aud: Option<&'a str>) -> Self {
        ...
        let aud = if let Some(aud_str) = aud {
            aud_str
        } else {
            &key.token_uri
        };
        Claims {
            iss: &key.client_email,
            aud,
            exp: iat + 3600 - 5, // Max validity is 1h
            iat,
            sub,
            scope,
        }
    }

    ...
}

@djc
Copy link
Owner

djc commented Oct 14, 2024

I think doing CustomServiceAccount only is probably a good start if it fulfills your use case. Happy to review your PR!

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 a pull request may close this issue.

3 participants