Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/auth/src/credentials/idtoken.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

//! Obtain [OIDC ID Tokens].
//! Obtain, use, and verify [OIDC ID Tokens].
//!
//! `IDTokenCredentials` obtain OIDC ID tokens, which are commonly
//! used for [service to service authentication]. For example, when the
Expand Down Expand Up @@ -70,7 +70,7 @@
//! # Ok(())
//! }
//! ```
//!
//! [Verifier]: https://docs.rs/google-cloud-auth/latest/google_cloud_auth/credentials/idtoken/struct.Verifier.html
//! [OIDC ID Tokens]: https://cloud.google.com/docs/authentication/token-types#identity-tokens
//! [Service to Service Authentication]: https://cloud.google.com/run/docs/authenticating/service-to-service

Expand All @@ -79,7 +79,7 @@ use crate::credentials::{AdcContents, CredentialsError, extract_credential_type,
use crate::token::Token;
use crate::{BuildResult, Result};
use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD};
pub use serde_json::{Map, Value};
use serde_json::Value;
use std::collections::HashMap;
use std::future::Future;
use std::sync::Arc;
Expand Down
68 changes: 66 additions & 2 deletions src/auth/src/credentials/idtoken/impersonated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
//! "source_credentials": source_credentials,
//! });
//!
//! let audience = "https://example.com"
//! let audience = "https://my-service.a.run.app";
//! let credentials = idtoken::impersonated::Builder::new(audience, impersonated_credential)
//! .build()?;
//! let id_token = credentials.id_token().await?;
Expand All @@ -59,7 +59,7 @@
//! ```
//!
//! [Impersonated service accounts]: https://cloud.google.com/docs/authentication/use-service-account-impersonation
//! [ID tokens]: https://cloud.google.com/docs/authentication/token-types#identity-tokens
//! [OIDC ID tokens]: https://cloud.google.com/docs/authentication/token-types#identity-tokens
//! [User Account]: https://cloud.google.com/docs/authentication#user-accounts
//! [Service Account]: https://cloud.google.com/iam/docs/service-account-overview
//! [Service Account Token Creator Role]: https://cloud.google.com/docs/authentication/use-service-account-impersonation#required-roles
Expand Down Expand Up @@ -89,6 +89,25 @@ use serde_json::Value;
use std::sync::Arc;

/// A builder for constructing Impersonated Service Account [IDTokenCredentials] instance.
///
/// # Example
/// ```
/// # use google_cloud_auth::credentials::idtoken;
/// # tokio_test::block_on(async {
/// let impersonated_credential = serde_json::json!({
/// "type": "impersonated_service_account",
/// "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/test-principal:generateAccessToken",
/// "source_credentials": {
/// "type": "authorized_user",
/// "client_id": "test-client-id",
/// "client_secret": "test-client-secret",
/// "refresh_token": "test-refresh-token"
/// }
/// });
///
/// let audience = "https://my-service.a.run.app";
/// let credentials = idtoken::impersonated::Builder::new(impersonated_credential).build();
/// # });
pub struct Builder {
source: BuilderSource,
delegates: Option<Vec<String>>,
Expand Down Expand Up @@ -117,6 +136,23 @@ impl Builder {

/// Creates a new builder with a source [Credentials] object, target principal and audience.
/// Target principal is the email of the service account to impersonate.
///
/// # Example
/// ```
/// # use google_cloud_auth::credentials::idtoken;
/// # use google_cloud_auth::credentials::user_account;
/// # use serde_json::json;
/// #
/// # tokio_test::block_on(async {
/// let source_credentials = user_account::Builder::new(json!({ /* add details here */ })).build()?;
///
/// let audience = "https://my-service.a.run.app";
/// let credentials = idtoken::impersonated::Builder::from_source_credentials(audience, "test-principal", source_credentials)
/// .build();
/// # Ok::<(), anyhow::Error>(())
/// # });
/// // Now you can use credentials.id_token().await to fetch the token.
/// ```
pub fn from_source_credentials<SA: Into<String>, SP: Into<String>>(
target_audience: SA,
target_principal: SP,
Expand Down Expand Up @@ -144,12 +180,40 @@ impl Builder {
}

/// Should include email claims in the ID Token.
///
/// # Example
///
/// ```
/// # use google_cloud_auth::credentials::idtoken;
/// # use serde_json::json;
/// let impersonated_credential = json!({ /* add details here */ });
///
/// let audience = "https://my-service.a.run.app";
/// let credentials = idtoken::impersonated::Builder::new(audience, impersonated_credential)
/// .with_include_email()
/// .build();
/// // Now you can use credentials.id_token().await to fetch the token.
/// ```
pub fn with_include_email(mut self) -> Self {
self.include_email = Some(true);
self
}

/// Sets the chain of delegates.
///
/// # Example
///
/// ```
/// # use google_cloud_auth::credentials::idtoken;
/// # use serde_json::json;
/// let impersonated_credential = json!({ /* add details here */ });
///
/// let audience = "https://my-service.a.run.app";
/// let credentials = idtoken::impersonated::Builder::new(audience, impersonated_credential)
/// .with_delegates(vec!["[email protected]", "[email protected]"])
/// .build();
/// // Now you can use credentials.id_token().await to fetch the token.
/// ```
pub fn with_delegates<I, S>(mut self, delegates: I) -> Self
where
I: IntoIterator<Item = S>,
Expand Down
39 changes: 37 additions & 2 deletions src/auth/src/credentials/idtoken/mds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
//! # use google_cloud_auth::credentials::idtoken;
//! # use reqwest;
//! # tokio_test::block_on(async {
//! let audience = "https://example.com";
//! let audience = "https://my-service.a.run.app";
//! let credentials = idtoken::mds::Builder::new(audience)
//! .build()?;
//! let id_token = credentials.id_token().await?;
Expand All @@ -56,11 +56,12 @@
//! ```
//!
//! [Application Default Credentials]: https://cloud.google.com/docs/authentication/application-default-credentials
//! [ID tokens]: https://cloud.google.com/docs/authentication/token-types#identity-tokens
//! [OIDC ID Tokens]: https://cloud.google.com/docs/authentication/token-types#identity-tokens
//! [Cloud Run]: https://cloud.google.com/run
//! [default service account]: https://cloud.google.com/iam/docs/service-account-types#default
//! [gce-link]: https://cloud.google.com/products/compute
//! [gke-link]: https://cloud.google.com/kubernetes-engine
//! [Service to Service Authentication]: https://cloud.google.com/run/docs/authenticating/service-to-service
//! [Metadata Service]: https://cloud.google.com/compute/docs/metadata/overview

use crate::Result;
Expand Down Expand Up @@ -155,6 +156,17 @@ impl Builder {
///
/// A trailing slash is significant, so specify the base URL without a trailing
/// slash. If not set, the credentials use `http://metadata.google.internal`.
///
/// # Example
///
/// ```
/// # use google_cloud_auth::credentials::idtoken;
/// let audience = "https://my-service.a.run.app";
/// let credentials = idtoken::mds::Builder::new(audience)
/// .with_endpoint("http://169.254.169.254")
/// .build();
/// // Now you can use credentials.id_token().await to fetch the token.
/// ```
pub fn with_endpoint<S: Into<String>>(mut self, endpoint: S) -> Self {
self.endpoint = Some(endpoint.into());
self
Expand All @@ -167,6 +179,17 @@ impl Builder {
/// from the payload. The default value is `standard`.
///
/// [format]: https://cloud.google.com/compute/docs/instances/verifying-instance-identity#token_format
///
/// # Example
///
/// ```
/// # use google_cloud_auth::credentials::idtoken;
/// let audience = "https://my-service.a.run.app";
/// let credentials = idtoken::mds::Builder::new(audience)
/// .with_format(idtoken::mds::Format::Full)
/// .build();
/// // Now you can use credentials.id_token().await to fetch the token.
/// ```
pub fn with_format(mut self, format: Format) -> Self {
self.format = Some(format);
self
Expand All @@ -178,6 +201,18 @@ impl Builder {
/// The default value is `false`. Has no effect unless format is `full`.
///
/// [license codes]: https://cloud.google.com/compute/docs/reference/rest/v1/images/get#body.Image.FIELDS.license_code
///
/// # Example
///
/// ```
/// # use google_cloud_auth::credentials::idtoken;
/// let audience = "https://my-service.a.run.app";
/// let credentials = idtoken::mds::Builder::new(audience)
/// .with_format(idtoken::mds::Format::Full) // licenses only works with format = Full
/// .with_licenses(true)
/// .build();
/// // Now you can use credentials.id_token().await to fetch the token.
/// ```
pub fn with_licenses(mut self, licenses: bool) -> Self {
self.licenses = if licenses {
Some("TRUE".to_string())
Expand Down
7 changes: 4 additions & 3 deletions src/auth/src/credentials/idtoken/service_account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,17 @@
//! # Example: Creating Service Account sourced credentials with target audience and sending ID Tokens.
//! ```
//! # use google_cloud_auth::credentials::idtoken;
//! # use serde_json::json;
//! # use reqwest;
//! # tokio_test::block_on(async {
//! let service_account_key = serde_json::json!({
//! let service_account_key = json!({
//! "client_email": "test-client-email",
//! "private_key_id": "test-private-key-id",
//! "private_key": "<YOUR_PKCS8_PEM_KEY_HERE>",
//! "project_id": "test-project-id",
//! "universe_domain": "test-universe-domain",
//! });
//! let audience = "https://example.com";
//! let audience = "https://my-service.a.run.app";
//! let credentials: Credentials = idtoken::service_account::Builder::new(audience, service_account_key)
//! .build()?;
//! let id_token = credentials.id_token().await?;
Expand All @@ -55,7 +56,7 @@
//! ```
//!
//! [Best practices for using service accounts]: https://cloud.google.com/iam/docs/best-practices-service-accounts#choose-when-to-use
//! [ID tokens]: https://cloud.google.com/docs/authentication/token-types#identity-tokens
//! [OIDC ID Tokens]: https://cloud.google.com/docs/authentication/token-types#identity-tokens
//! [create a service account key]: https://cloud.google.com/iam/docs/keys-create-delete#creating
//! [Service Accounts]: https://cloud.google.com/iam/docs/service-account-overview
//! [service account key]: https://cloud.google.com/iam/docs/keys-create-delete#creating
Expand Down
31 changes: 29 additions & 2 deletions src/auth/src/credentials/idtoken/user_account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@
//!
//! ```
//! # use google_cloud_auth::credentials::idtoken;
//! # use serde_json::json;
//! # use reqwest;
//! # tokio_test::block_on(async {
//! let authorized_user = serde_json::json!({
//! let authorized_user = json!({
//! "client_id": "YOUR_CLIENT_ID.apps.googleusercontent.com", // Replace with your actual Client ID
//! "client_secret": "YOUR_CLIENT_SECRET", // Replace with your actual Client Secret - LOAD SECURELY!
//! "refresh_token": "YOUR_REFRESH_TOKEN", // Replace with the user's refresh token - LOAD SECURELY!
Expand All @@ -51,7 +52,7 @@
//! # });
//! ```
//!
//! [ID tokens]: https://cloud.google.com/docs/authentication/token-types#identity-tokens
//! [OIDC ID Tokens]: https://cloud.google.com/docs/authentication/token-types#identity-tokens
//! [user account]: https://cloud.google.com/docs/authentication#user-accounts
//! [Service to Service Authentication]: https://cloud.google.com/run/docs/authenticating/service-to-service

Expand Down Expand Up @@ -88,6 +89,20 @@ where
}

/// A builder for [`IDTokenCredentials`] instances backed by user account credentials.
///
/// # Example
/// ```
/// # use google_cloud_auth::credentials::idtoken;
/// # tokio_test::block_on(async {
/// let authorized_user = json!({
/// "client_id": "YOUR_CLIENT_ID.apps.googleusercontent.com",
/// "client_secret": "YOUR_CLIENT_SECRET",
/// "refresh_token": "YOUR_REFRESH_TOKEN",
/// "type": "authorized_user",
/// });
/// let credentials = idtoken::user_account::Builder::new(authorized_user).build();
/// })
/// ```
pub struct Builder {
authorized_user: Value,
token_uri: Option<String>,
Expand All @@ -112,6 +127,18 @@ impl Builder {
///
/// Any value provided here overrides a `token_uri` value from the input `authorized_user` JSON.
/// Defaults to `https://oauth2.googleapis.com/token` if not specified here or in the `authorized_user` JSON.
///
/// # Example
///
/// ```
/// # use google_cloud_auth::credentials::idtoken;
/// # use serde_json::json;
/// let authorized_user = json!({ /* add details here */ });
/// let credentials = idtoken::user_account::Builder::new(authorized_user)
/// .with_token_uri("https://oauth2.example.com/token")
/// .build();
/// // Now you can use credentials.id_token().await to fetch the token.
/// ```
pub fn with_token_uri<S: Into<String>>(mut self, token_uri: S) -> Self {
self.token_uri = Some(token_uri.into());
self
Expand Down
8 changes: 5 additions & 3 deletions src/auth/src/credentials/idtoken/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@

use crate::credentials::internal::jwk_client::JwkClient;
use jsonwebtoken::Validation;
pub use serde_json::{Map, Value};
/// Represents the claims in an ID token.
pub use serde_json::Map;
/// Represents a claim value in an ID token.
pub use serde_json::Value;
use std::time::Duration;

/// Builder is used construct a [Verifier] of id tokens.
Expand Down Expand Up @@ -124,7 +127,7 @@ impl Builder {
self
}

/// Verifies the ID token and returns the claims.
/// Returns a [Verifier] instance with the configured settings.
pub fn build(self) -> Verifier {
Verifier {
jwk_client: JwkClient::new(),
Expand All @@ -143,7 +146,6 @@ impl Builder {
/// ```
/// # use google_cloud_auth::credentials::idtoken::verifier::Builder;
/// # use std::time::Duration;
///
/// async fn verify_id_token(token: &str) {
/// let verifier = Builder::new(["https://my-service.a.run.app"]).build();
///
Expand Down
Loading