From 137883aff56c9e847abb6445c89a76a27536fe26 Mon Sep 17 00:00:00 2001 From: Fedor Isakov Date: Fri, 30 Sep 2022 00:02:36 +0200 Subject: [PATCH] feat(samples): auth samples (#1444) --- README.md | 6 + samples/README.md | 108 ++++++++++++++++++ samples/authenticateExplicit.js | 73 ++++++++++++ samples/authenticateImplicitWithAdc.js | 60 ++++++++++ samples/idTokenFromImpersonatedCredentials.js | 80 +++++++++++++ samples/idTokenFromMetadataServer.js | 51 +++++++++ samples/idTokenFromServiceAccount.js | 60 ++++++++++ samples/test/auth.test.js | 76 ++++++++++++ samples/verifyGoogleIdToken.js | 69 +++++++++++ 9 files changed, 583 insertions(+) create mode 100644 samples/authenticateExplicit.js create mode 100644 samples/authenticateImplicitWithAdc.js create mode 100644 samples/idTokenFromImpersonatedCredentials.js create mode 100644 samples/idTokenFromMetadataServer.js create mode 100644 samples/idTokenFromServiceAccount.js create mode 100644 samples/test/auth.test.js create mode 100644 samples/verifyGoogleIdToken.js diff --git a/README.md b/README.md index 6cc36cd9..b6264233 100644 --- a/README.md +++ b/README.md @@ -1187,10 +1187,15 @@ Samples are in the [`samples/`](https://github.com/googleapis/google-auth-librar | Sample | Source Code | Try it | | --------------------------- | --------------------------------- | ------ | | Adc | [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/adc.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/adc.js,samples/README.md) | +| Authenticate Explicit | [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/authenticateExplicit.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/authenticateExplicit.js,samples/README.md) | +| Authenticate Implicit With Adc | [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/authenticateImplicitWithAdc.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/authenticateImplicitWithAdc.js,samples/README.md) | | Compute | [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/compute.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/compute.js,samples/README.md) | | Credentials | [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/credentials.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/credentials.js,samples/README.md) | | Downscopedclient | [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/downscopedclient.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/downscopedclient.js,samples/README.md) | | Headers | [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/headers.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/headers.js,samples/README.md) | +| Id Token From Impersonated Credentials | [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/idTokenFromImpersonatedCredentials.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/idTokenFromImpersonatedCredentials.js,samples/README.md) | +| Id Token From Metadata Server | [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/idTokenFromMetadataServer.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/idTokenFromMetadataServer.js,samples/README.md) | +| Id Token From Service Account | [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/idTokenFromServiceAccount.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/idTokenFromServiceAccount.js,samples/README.md) | | ID Tokens for Identity-Aware Proxy (IAP) | [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/idtokens-iap.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/idtokens-iap.js,samples/README.md) | | ID Tokens for Serverless | [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/idtokens-serverless.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/idtokens-serverless.js,samples/README.md) | | Jwt | [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/jwt.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/jwt.js,samples/README.md) | @@ -1199,6 +1204,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/google-auth-librar | Oauth2-code Verifier | [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/oauth2-codeVerifier.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/oauth2-codeVerifier.js,samples/README.md) | | Oauth2 | [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/oauth2.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/oauth2.js,samples/README.md) | | Sign Blob | [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/signBlob.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/signBlob.js,samples/README.md) | +| Verify Google Id Token | [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/verifyGoogleIdToken.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/verifyGoogleIdToken.js,samples/README.md) | | Verifying ID Tokens from Identity-Aware Proxy (IAP) | [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/verifyIdToken-iap.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/verifyIdToken-iap.js,samples/README.md) | | Verify Id Token | [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/verifyIdToken.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/verifyIdToken.js,samples/README.md) | diff --git a/samples/README.md b/samples/README.md index 123cd26c..cf16c381 100644 --- a/samples/README.md +++ b/samples/README.md @@ -13,10 +13,15 @@ This is Google's officially supported [node.js](http://nodejs.org/) client libra * [Before you begin](#before-you-begin) * [Samples](#samples) * [Adc](#adc) + * [Authenticate Explicit](#authenticate-explicit) + * [Authenticate Implicit With Adc](#authenticate-implicit-with-adc) * [Compute](#compute) * [Credentials](#credentials) * [Downscopedclient](#downscopedclient) * [Headers](#headers) + * [Id Token From Impersonated Credentials](#id-token-from-impersonated-credentials) + * [Id Token From Metadata Server](#id-token-from-metadata-server) + * [Id Token From Service Account](#id-token-from-service-account) * [ID Tokens for Identity-Aware Proxy (IAP)](#id-tokens-for-identity-aware-proxy-iap) * [ID Tokens for Serverless](#id-tokens-for-serverless) * [Jwt](#jwt) @@ -25,6 +30,7 @@ This is Google's officially supported [node.js](http://nodejs.org/) client libra * [Oauth2-code Verifier](#oauth2-code-verifier) * [Oauth2](#oauth2) * [Sign Blob](#sign-blob) + * [Verify Google Id Token](#verify-google-id-token) * [Verifying ID Tokens from Identity-Aware Proxy (IAP)](#verifying-id-tokens-from-identity-aware-proxy-iap) * [Verify Id Token](#verify-id-token) @@ -60,6 +66,40 @@ __Usage:__ +### Authenticate Explicit + +View the [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/authenticateExplicit.js). + +[![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/authenticateExplicit.js,samples/README.md) + +__Usage:__ + + +`node samples/authenticateExplicit.js` + + +----- + + + + +### Authenticate Implicit With Adc + +View the [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/authenticateImplicitWithAdc.js). + +[![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/authenticateImplicitWithAdc.js,samples/README.md) + +__Usage:__ + + +`node samples/authenticateImplicitWithAdc.js` + + +----- + + + + ### Compute View the [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/compute.js). @@ -128,6 +168,57 @@ __Usage:__ +### Id Token From Impersonated Credentials + +View the [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/idTokenFromImpersonatedCredentials.js). + +[![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/idTokenFromImpersonatedCredentials.js,samples/README.md) + +__Usage:__ + + +`node samples/idTokenFromImpersonatedCredentials.js` + + +----- + + + + +### Id Token From Metadata Server + +View the [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/idTokenFromMetadataServer.js). + +[![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/idTokenFromMetadataServer.js,samples/README.md) + +__Usage:__ + + +`node samples/idTokenFromMetadataServer.js` + + +----- + + + + +### Id Token From Service Account + +View the [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/idTokenFromServiceAccount.js). + +[![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/idTokenFromServiceAccount.js,samples/README.md) + +__Usage:__ + + +`node samples/idTokenFromServiceAccount.js` + + +----- + + + + ### ID Tokens for Identity-Aware Proxy (IAP) Requests an IAP-protected resource with an ID Token. @@ -268,6 +359,23 @@ __Usage:__ +### Verify Google Id Token + +View the [source code](https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/verifyGoogleIdToken.js). + +[![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-auth-library-nodejs&page=editor&open_in_editor=samples/verifyGoogleIdToken.js,samples/README.md) + +__Usage:__ + + +`node samples/verifyGoogleIdToken.js` + + +----- + + + + ### Verifying ID Tokens from Identity-Aware Proxy (IAP) Verifying the signed token from the header of an IAP-protected resource. diff --git a/samples/authenticateExplicit.js b/samples/authenticateExplicit.js new file mode 100644 index 00000000..99986433 --- /dev/null +++ b/samples/authenticateExplicit.js @@ -0,0 +1,73 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * Lists storage buckets by authenticating with ADC. + */ +function main() { + // [START auth_cloud_explicit_adc] + /** + * TODO(developer): + * 1. Set up ADC as described in https://cloud.google.com/docs/authentication/external/set-up-adc + * 2. Make sure you have the necessary permission to list storage buckets "storage.buckets.list" + */ + + const {GoogleAuth} = require('google-auth-library'); + const {Storage} = require('@google-cloud/storage'); + + async function authenticateExplicit() { + const googleAuth = new GoogleAuth({ + scopes: 'https://www.googleapis.com/auth/cloud-platform', + }); + + // Construct the Google credentials object which obtains the default configuration from your + // working environment. + // googleAuth.getApplicationDefault() will give you ComputeEngineCredentials + // if you are on a GCE (or other metadata server supported environments). + const {credential, projectId} = await googleAuth.getApplicationDefault(); + // If you are authenticating to a Cloud API, you can let the library include the default scope, + // https://www.googleapis.com/auth/cloud-platform, because IAM is used to provide fine-grained + // permissions for Cloud. + // If you need to provide a scope, specify it as follows: + // const googleAuth = new GoogleAuth({ scopes: scope }); + // For more information on scopes to use, + // see: https://developers.google.com/identity/protocols/oauth2/scopes + + const storageOptions = { + projectId, + authClient: credential, + }; + + // Construct the Storage client. + const storage = new Storage(storageOptions); + const [buckets] = await storage.getBuckets(); + console.log('Buckets:'); + + for (const bucket of buckets) { + console.log(`- ${bucket.name}`); + } + + console.log('Listed all storage buckets.'); + } + + authenticateExplicit(); + // [END auth_cloud_explicit_adc] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); + +main(...process.argv.slice(2)); diff --git a/samples/authenticateImplicitWithAdc.js b/samples/authenticateImplicitWithAdc.js new file mode 100644 index 00000000..1d8051d1 --- /dev/null +++ b/samples/authenticateImplicitWithAdc.js @@ -0,0 +1,60 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * Shows credentials auto-detections in the intercation with GCP libraries + * + * @param {string} projectId - Project ID or project number of the Cloud project you want to use. + */ +function main(projectId) { + // [START auth_cloud_implicit_adc] + /** + * TODO(developer): + * 1. Uncomment and replace these variables before running the sample. + * 2. Set up ADC as described in https://cloud.google.com/docs/authentication/external/set-up-adc + * 3. Make sure you have the necessary permission to list storage buckets "storage.buckets.list" + * (https://cloud.google.com/storage/docs/access-control/iam-permissions#bucket_permissions) + */ + // const projectId = 'YOUR_PROJECT_ID'; + + const {Storage} = require('@google-cloud/storage'); + + async function authenticateImplicitWithAdc() { + // This snippet demonstrates how to list buckets. + // NOTE: Replace the client created below with the client required for your application. + // Note that the credentials are not specified when constructing the client. + // The client library finds your credentials using ADC. + const storage = new Storage({ + projectId, + }); + const [buckets] = await storage.getBuckets(); + console.log('Buckets:'); + + for (const bucket of buckets) { + console.log(`- ${bucket.name}`); + } + + console.log('Listed all storage buckets.'); + } + + authenticateImplicitWithAdc(); + // [END auth_cloud_implicit_adc] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); + +main(...process.argv.slice(2)); diff --git a/samples/idTokenFromImpersonatedCredentials.js b/samples/idTokenFromImpersonatedCredentials.js new file mode 100644 index 00000000..84ea1d2a --- /dev/null +++ b/samples/idTokenFromImpersonatedCredentials.js @@ -0,0 +1,80 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * Uses a service account (SA1) to impersonate as another service account (SA2) and obtain id token for the impersonated account. + * To obtain token for SA2, SA1 should have the "roles/iam.serviceAccountTokenCreator" permission on SA2. + * + * @param {string} scope - The scope that you might need to request to access Google APIs, + * depending on the level of access you need. For this example, we use the cloud-wide scope + * and use IAM to narrow the permissions: https://cloud.google.com/docs/authentication#authorization_for_services. + * For more information, see: https://developers.google.com/identity/protocols/oauth2/scopes. + * @param {string} targetAudience - The service name for which the id token is requested. Service name refers to the + * logical identifier of an API service, such as "http://www.example.com". + * @param {string} impersonatedServiceAccount - The name of the privilege-bearing service account for whom + * the credential is created. + */ +function main(scope, targetAudience, impersonatedServiceAccount) { + // [START auth_cloud_idtoken_impersonated_credentials] + /** + * TODO(developer): + * 1. Uncomment and replace these variables before running the sample. + */ + // const scope = 'https://www.googleapis.com/auth/cloud-platform'; + // const targetAudience = 'http://www.example.com'; + // const impersonatedServiceAccount = 'name@project.service.gserviceaccount.com'; + + const {GoogleAuth, Impersonated} = require('google-auth-library'); + + async function getIdTokenFromImpersonatedCredentials() { + const googleAuth = new GoogleAuth(); + + // Construct the GoogleCredentials object which obtains the default configuration from your + // working environment. + const {credential} = await googleAuth.getApplicationDefault(); + + // delegates: The chained list of delegates required to grant the final accessToken. + // For more information, see: + // https://cloud.google.com/iam/docs/create-short-lived-credentials-direct#sa-credentials-permissions + // Delegate is NOT USED here. + const delegates = []; + + // Create the impersonated credential. + const impersonatedCredentials = new Impersonated({ + sourceClient: credential, + delegates, + targetPrincipal: impersonatedServiceAccount, + targetScopes: [scope], + lifetime: 300, + }); + + // Get the ID token. + // Once you've obtained the ID token, you can use it to make an authenticated call + // to the target audience. + await impersonatedCredentials.fetchIdToken(targetAudience, { + includeEmail: true, + }); + console.log('Generated ID token.'); + } + + getIdTokenFromImpersonatedCredentials(); + // [END auth_cloud_idtoken_impersonated_credentials] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); + +main(...process.argv.slice(2)); diff --git a/samples/idTokenFromMetadataServer.js b/samples/idTokenFromMetadataServer.js new file mode 100644 index 00000000..3454dcc3 --- /dev/null +++ b/samples/idTokenFromMetadataServer.js @@ -0,0 +1,51 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * Uses the Google Cloud metadata server environment to create an identity token + * and add it to the HTTP request as part of an Authorization header. + * + * @param {string} url - The url or target audience to obtain the ID token for. + */ +function main(url) { + // [START auth_cloud_idtoken_metadata_server] + /** + * TODO(developer): + * 1. Uncomment and replace these variables before running the sample. + */ + // const url = 'http://www.example.com'; + + const {GoogleAuth} = require('google-auth-library'); + + async function getIdTokenFromMetadataServer() { + const googleAuth = new GoogleAuth(); + const client = await googleAuth.getClient(); + + // Get the ID token. + // Once you've obtained the ID token, you can use it to make an authenticated call + // to the target audience. + await client.fetchIdToken(url); + console.log('Generated ID token.'); + } + + getIdTokenFromMetadataServer(); + // [END auth_cloud_idtoken_metadata_server] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); + +main(...process.argv.slice(2)); diff --git a/samples/idTokenFromServiceAccount.js b/samples/idTokenFromServiceAccount.js new file mode 100644 index 00000000..aa8e0224 --- /dev/null +++ b/samples/idTokenFromServiceAccount.js @@ -0,0 +1,60 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * Obtains the id token by providing the target audience using service account credentials. + * + * @param {string} jsonCredentialsPath - Path to the service account json credential file. + * and use IAM to narrow the permissions: https://cloud.google.com/docs/authentication#authorization_for_services + * @param {string} targetAudience - The url or target audience to obtain the ID token for. + */ +function main(targetAudience, jsonCredentialsPath) { + // [START auth_cloud_idtoken_service_account] + /** + * TODO(developer): + * 1. Uncomment and replace these variables before running the sample. + */ + // const jsonCredentialsPath = '/path/example'; + // const targetAudience = 'http://www.example.com'; + + // Using service account keys introduces risk; they are long-lived, and can be used by anyone + // that obtains the key. Proper rotation and storage reduce this risk but do not eliminate it. + // For these reasons, you should consider an alternative approach that + // does not use a service account key. Several alternatives to service account keys + // are described here: + // https://cloud.google.com/docs/authentication/external/set-up-adc + + const {auth} = require('google-auth-library'); + const jsonConfig = require(jsonCredentialsPath); + + async function getIdTokenFromServiceAccount() { + const client = auth.fromJSON(jsonConfig); + + // Get the ID token. + // Once you've obtained the ID token, use it to make an authenticated call + // to the target audience. + await client.fetchIdToken(targetAudience); + console.log('Generated ID token.'); + } + + getIdTokenFromServiceAccount(); + // [END auth_cloud_idtoken_service_account] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); + +main(...process.argv.slice(2)); diff --git a/samples/test/auth.test.js b/samples/test/auth.test.js new file mode 100644 index 00000000..6188dd2d --- /dev/null +++ b/samples/test/auth.test.js @@ -0,0 +1,76 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const assert = require('assert'); +const cp = require('child_process'); +const {auth} = require('google-auth-library'); +const {describe, it} = require('mocha'); + +const TARGET_AUDIENCE = 'iap.googleapis.com'; +const ZONE = 'us-central1-a'; + +const keyFile = process.env.GOOGLE_APPLICATION_CREDENTIALS; + +const execSync = (command, opts) => { + return cp.execSync(command, Object.assign({encoding: 'utf-8'}, opts)); +}; + +describe('auth samples', () => { + it('should authenticate explicitly', async () => { + const output = execSync('node authenticateExplicit'); + + assert.match(output, /Listed all storage buckets./); + }); + + it('should authenticate implicitly with adc', async () => { + const projectId = await auth.getProjectId(); + + const output = execSync( + `node authenticateImplicitWithAdc ${projectId} ${ZONE}` + ); + + assert.match(output, /Listed all storage buckets./); + }); + + it('should get id token from metadata server', async () => { + const output = execSync( + 'node idTokenFromMetadataServer https://www.google.com' + ); + + assert.match(output, /Generated ID token./); + }); + + it('should get id token from service account', async () => { + const output = execSync( + `node idTokenFromServiceAccount ${TARGET_AUDIENCE} ${keyFile}` + ); + + assert.match(output, /Generated ID token./); + }); + + it('should verify google id token', async () => { + const jsonConfig = require(keyFile); + const client = auth.fromJSON(jsonConfig); + + const idToken = await client.fetchIdToken(TARGET_AUDIENCE); + + const output = execSync( + `node verifyGoogleIdToken ${idToken} ${TARGET_AUDIENCE} https://www.googleapis.com/oauth2/v3/certs` + ); + + assert.match(output, /ID token verified./); + }); +}); diff --git a/samples/verifyGoogleIdToken.js b/samples/verifyGoogleIdToken.js new file mode 100644 index 00000000..c01e8ca3 --- /dev/null +++ b/samples/verifyGoogleIdToken.js @@ -0,0 +1,69 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * Verifies the obtained Google id token. This is done at the receiving end of the OIDC endpoint. + * The most common use case for verifying the ID token is when you are protecting + * your own APIs with IAP. Google services already verify credentials as a platform, + * so verifying ID tokens before making Google API calls is usually unnecessary. + * + * @param {string} idToken - The Google ID token to verify. + * and use IAM to narrow the permissions: https://cloud.google.com/docs/authentication#authorization_for_services + * @param {string} expectedAudience - The service name for which the id token is requested. Service name refers to the + * logical identifier of an API service, such as "iap.googleapis.com". + */ +function main(idToken, expectedAudience) { + // [START auth_cloud_verify_google_idtoken] + /** + * TODO(developer): + * 1. Uncomment and replace these variables before running the sample. + */ + // const idToken = 'id-token'; + // const targetAudience = 'pubsub.googleapis.com'; + + const {OAuth2Client} = require('google-auth-library'); + + async function verifyGoogleIdToken() { + const oAuth2Client = new OAuth2Client(); + + const result = await oAuth2Client.verifyIdToken({ + idToken, + expectedAudience, + }); + + // Verify that the token contains subject and email claims. + // Get the User id. + if (result.payload['sub']) { + console.log(`User id: ${result.payload['sub']}`); + } + + // Optionally, if "includeEmail" was set in the token options, check if the + // email was verified + if (result.payload['email_verified']) { + console.log(`Email verified: ${result.payload['email_verified']}`); + } + + console.log('ID token verified.'); + } + + verifyGoogleIdToken(); + // [END auth_cloud_verify_google_idtoken] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); + +main(...process.argv.slice(2));