Skip to content

Commit 2085f49

Browse files
authored
docs(auth): add idtoken samples (#3819)
Splitting work on #3762 that can already be merged.
1 parent 509556c commit 2085f49

File tree

6 files changed

+134
-0
lines changed

6 files changed

+134
-0
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

guide/samples/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ name = "getting_started"
3030
[dependencies]
3131
anyhow.workspace = true
3232
crc32c.workspace = true
33+
httptest.workspace = true
3334
futures.workspace = true
35+
reqwest.workspace = true
3436
google-cloud-aiplatform-v1 = { workspace = true, default-features = false, features = ["prediction-service"] }
3537
google-cloud-auth.workspace = true
3638
google-cloud-gax = { workspace = true, features = ["unstable-stream"] }
@@ -68,3 +70,6 @@ test-case.workspace = true
6870
run-integration-tests = []
6971
log-integration-tests = []
7072
run-large-downloads = []
73+
74+
[lints]
75+
workspace = true

guide/samples/src/authentication.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,7 @@
1515
pub mod adc;
1616
pub mod api_key;
1717
pub mod impersonation;
18+
#[cfg(google_cloud_unstable_id_token)]
19+
pub mod request_id_token;
20+
#[cfg(google_cloud_unstable_id_token)]
21+
pub mod verify_id_token;
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// [START rust_auth_request_id_token] ANCHOR: all
16+
// [START rust_auth_request_id_token_parameters] ANCHOR: request_id_token_parameters
17+
// # Parameters
18+
// * `audience`: The audience for the ID token.
19+
pub async fn sample(audience: &str) -> anyhow::Result<String> {
20+
// [END rust_auth_request_id_token_parameters] ANCHOR_END: request_id_token_parameters
21+
// [START rust_auth_request_id_token_use] ANCHOR: request_id_token_use
22+
use google_cloud_auth::credentials::idtoken::Builder;
23+
// [END rust_auth_request_id_token_use] ANCHOR_END: request_id_token_use
24+
25+
// [START rust_auth_request_id_token_credentials] ANCHOR: request_id_token_credentials
26+
let credentials = Builder::new(audience).build()?;
27+
// [END rust_auth_request_id_token_credentials] ANCHOR_END: request_id_token_credentials
28+
29+
// [START rust_auth_request_id_token_call] ANCHOR: request_id_token_call
30+
let id_token = credentials.id_token().await?;
31+
println!("ID Token: {id_token:?}");
32+
// [END rust_auth_request_id_token_call] ANCHOR_END: request_id_token_call
33+
Ok(id_token)
34+
}
35+
36+
// [START request_id_token_send] ANCHOR: request_id_token_send
37+
// # Parameters
38+
// * `target_url`: The receiving service target URL.
39+
// * `credentials`: The IDTokenCredentials to use for authentication.
40+
pub async fn api_call_with_id_token(
41+
target_url: &str,
42+
credentials: &google_cloud_auth::credentials::idtoken::IDTokenCredentials,
43+
) -> anyhow::Result<()> {
44+
use reqwest;
45+
46+
let id_token = credentials.id_token().await?;
47+
let client = reqwest::Client::new();
48+
client.get(target_url).bearer_auth(id_token).send().await?;
49+
50+
Ok(())
51+
}
52+
// [END request_id_token_send] ANCHOR_END: request_id_token_send
53+
// [END rust_auth_request_id_token] ANCHOR_END: all
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// [START rust_auth_verify_id_token] ANCHOR: all
16+
// [START rust_auth_id_verify_token_parameters] ANCHOR: verify_id_token_parameters
17+
// # Parameters
18+
// * `token`: The ID token string to verify.
19+
// * `audience`: The expected audience of the ID token.
20+
pub async fn sample(token: &str, audience: &str) -> anyhow::Result<()> {
21+
// [END rust_auth_id_verify_token_parameters] ANCHOR_END: verify_id_token_parameters
22+
// [START rust_auth_verify_id_token_use] ANCHOR: verify_id_token_use
23+
use google_cloud_auth::credentials::idtoken::verifier::Builder as IdTokenVerifierBuilder;
24+
// [END rust_auth_verify_id_token_use] ANCHOR_END: verify_id_token_use
25+
26+
// [START rust_auth_id_verify_token_verifier] ANCHOR: verify_id_token_verifier
27+
let verifier = IdTokenVerifierBuilder::new([audience]).build();
28+
// [END rust_auth_id_verify_token_verifier] ANCHOR_END: verify_id_token_verifier
29+
30+
// [START rust_auth_id_verify_token_verify_call] ANCHOR: verify_id_token_verify_call
31+
let claims = verifier.verify(token).await?;
32+
println!("Hello {}", claims["sub"]);
33+
// [END rust_auth_id_verify_token_verify_call] ANCHOR_END: verify_id_token_verify_call
34+
Ok(())
35+
}
36+
// [END rust_auth_id_verify_token] ANCHOR_END: all

guide/samples/tests/driver.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,40 @@ mod driver {
2424
Ok(())
2525
}
2626

27+
#[cfg(all(test, google_cloud_unstable_id_token))]
28+
#[tokio::test(flavor = "multi_thread")]
29+
async fn id_token() -> anyhow::Result<()> {
30+
use google_cloud_auth::credentials::idtoken::Builder;
31+
use httptest::{Expectation, Server, matchers::*, responders::*};
32+
33+
let audience = "https://my-service.a.run.app";
34+
let id_token =
35+
user_guide_samples::authentication::request_id_token::sample(audience).await?;
36+
user_guide_samples::authentication::verify_id_token::sample(&id_token, audience).await?;
37+
38+
let credentials = Builder::new(audience).build()?;
39+
let id_token = credentials.id_token().await?;
40+
41+
let server = Server::run();
42+
server.expect(
43+
Expectation::matching(all_of![
44+
request::method_path("GET", "/"),
45+
request::headers(contains(("authorization", format!("Bearer {}", id_token)))),
46+
])
47+
.respond_with(status_code(200)),
48+
);
49+
50+
let target_url = server.url("/").to_string();
51+
52+
user_guide_samples::authentication::request_id_token::api_call_with_id_token(
53+
&target_url,
54+
&credentials,
55+
)
56+
.await?;
57+
58+
Ok(())
59+
}
60+
2761
#[tokio::test(flavor = "multi_thread")]
2862
async fn endpoint() -> anyhow::Result<()> {
2963
let project_id = std::env::var("GOOGLE_CLOUD_PROJECT").unwrap();

0 commit comments

Comments
 (0)