├── .compodocrc ├── .eslintignore ├── .eslintrc.json ├── .gitattributes ├── .github ├── .OwlBot.lock.yaml ├── .OwlBot.yaml ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ ├── documentation_request.yml │ ├── feature_request.yml │ ├── processs_request.md │ ├── questions.md │ └── support_request.md ├── PULL_REQUEST_TEMPLATE.md ├── auto-approve.yml ├── auto-label.yaml ├── generated-files-bot.yml ├── release-please.yml ├── release-trigger.yml ├── scripts │ ├── close-invalid-link.cjs │ ├── close-unresponsive.cjs │ ├── fixtures │ │ ├── invalidIssueBody.txt │ │ ├── validIssueBody.txt │ │ └── validIssueBodyDifferentLinkLocation.txt │ ├── package.json │ ├── remove-response-label.cjs │ └── tests │ │ ├── close-invalid-link.test.cjs │ │ └── close-or-remove-response-label.test.cjs ├── sync-repo-settings.yaml └── workflows │ ├── ci.yaml │ ├── issues-no-repro.yaml │ └── response.yaml ├── .gitignore ├── .jsdoc.js ├── .kokoro ├── .gitattributes ├── browser-test.sh ├── common.cfg ├── continuous │ ├── node14 │ │ ├── common.cfg │ │ ├── lint.cfg │ │ ├── samples-test.cfg │ │ ├── system-test.cfg │ │ └── test.cfg │ └── node18 │ │ ├── common.cfg │ │ ├── lint.cfg │ │ ├── samples-test.cfg │ │ ├── system-test.cfg │ │ └── test.cfg ├── docs.sh ├── lint.sh ├── populate-secrets.sh ├── presubmit │ ├── node14 │ │ ├── common.cfg │ │ ├── samples-test.cfg │ │ ├── system-test.cfg │ │ └── test.cfg │ ├── node18 │ │ ├── common.cfg │ │ ├── samples-test.cfg │ │ ├── system-test.cfg │ │ └── test.cfg │ └── windows │ │ ├── common.cfg │ │ └── test.cfg ├── publish.sh ├── release │ ├── common.cfg │ ├── docs-devsite.cfg │ ├── docs-devsite.sh │ ├── docs.cfg │ ├── docs.sh │ └── publish.cfg ├── samples-test.sh ├── system-test.sh ├── test.bat ├── test.sh ├── trampoline.sh └── trampoline_v2.sh ├── .mocharc.js ├── .nycrc ├── .prettierignore ├── .prettierrc.js ├── .readme-partials.yaml ├── .repo-metadata.json ├── .trampolinerc ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── browser-test ├── fixtures │ └── keys.ts ├── test.crypto.ts └── test.oauth2.ts ├── karma.conf.js ├── linkinator.config.json ├── owlbot.py ├── package.json ├── renovate.json ├── samples ├── .eslintrc.yml ├── README.md ├── adc.js ├── authenticateAPIKey.js ├── authenticateExplicit.js ├── authenticateImplicitWithAdc.js ├── compute.js ├── credentials.js ├── downscopedclient.js ├── headers.js ├── idTokenFromImpersonatedCredentials.js ├── idTokenFromMetadataServer.js ├── idTokenFromServiceAccount.js ├── idtokens-iap.js ├── idtokens-serverless.js ├── jwt.js ├── keepalive.js ├── keyfile.js ├── oauth2-codeVerifier.js ├── oauth2.js ├── package.json ├── puppeteer │ ├── .eslintrc.yml │ ├── oauth2-test.js │ └── package.json ├── scripts │ ├── downscoping-with-cab-setup.js │ └── externalclient-setup.js ├── signBlob.js ├── signBlobImpersonated.js ├── test │ ├── auth.test.js │ ├── downscoping-with-cab.test.js │ ├── externalclient.test.js │ └── jwt.test.js ├── verifyGoogleIdToken.js ├── verifyIdToken-iap.js └── verifyIdToken.js ├── src ├── auth │ ├── authclient.ts │ ├── awsclient.ts │ ├── awsrequestsigner.ts │ ├── baseexternalclient.ts │ ├── computeclient.ts │ ├── credentials.ts │ ├── defaultawssecuritycredentialssupplier.ts │ ├── downscopedclient.ts │ ├── envDetect.ts │ ├── executable-response.ts │ ├── externalAccountAuthorizedUserClient.ts │ ├── externalclient.ts │ ├── filesubjecttokensupplier.ts │ ├── googleauth.ts │ ├── iam.ts │ ├── identitypoolclient.ts │ ├── idtokenclient.ts │ ├── impersonated.ts │ ├── jwtaccess.ts │ ├── jwtclient.ts │ ├── loginticket.ts │ ├── oauth2client.ts │ ├── oauth2common.ts │ ├── passthrough.ts │ ├── pluggable-auth-client.ts │ ├── pluggable-auth-handler.ts │ ├── refreshclient.ts │ ├── stscredentials.ts │ └── urlsubjecttokensupplier.ts ├── crypto │ ├── browser │ │ └── crypto.ts │ ├── crypto.ts │ ├── node │ │ └── crypto.ts │ └── shared.ts ├── index.ts ├── shared.cts └── util.ts ├── system-test ├── fixtures │ └── kitchen │ │ ├── package.json │ │ ├── src │ │ └── index.ts │ │ ├── tsconfig.json │ │ └── webpack.config.js └── test.kitchen.ts ├── test ├── externalclienthelper.ts ├── fixtures │ ├── aws-security-credentials-fake.json │ ├── badlink │ ├── config-no-quota │ │ └── .config │ │ │ └── gcloud │ │ │ └── application_default_credentials.json │ ├── config-with-quota │ │ └── .config │ │ │ └── gcloud │ │ │ └── application_default_credentials.json │ ├── ecdsapublickeys.json │ ├── empty.json │ ├── emptylink │ ├── external-account-authorized-user-cred.json │ ├── external-account-cred.json │ ├── external-subject-token.json │ ├── external-subject-token.txt │ ├── fake-ecdsa-private.pem │ ├── fake-ecdsa-public.pem │ ├── goodlink │ ├── impersonated_application_default_credentials.json │ ├── key.p12 │ ├── oauthcertspem.json │ ├── private.json │ ├── private.pem │ ├── private2.json │ ├── public.pem │ ├── refresh.json │ ├── service-account-with-quota.json │ └── wellKnown.json ├── test.authclient.ts ├── test.awsclient.ts ├── test.awsrequestsigner.ts ├── test.baseexternalclient.ts ├── test.compute.ts ├── test.crypto.ts ├── test.downscopedclient.ts ├── test.executableresponse.ts ├── test.externalaccountauthorizeduserclient.ts ├── test.externalclient.ts ├── test.googleauth.ts ├── test.iam.ts ├── test.identitypoolclient.ts ├── test.idtokenclient.ts ├── test.impersonated.ts ├── test.index.ts ├── test.jwt.ts ├── test.jwtaccess.ts ├── test.loginticket.ts ├── test.oauth2.ts ├── test.oauth2common.ts ├── test.passthroughclient.ts ├── test.pluggableauthclient.ts ├── test.pluggableauthhandler.ts ├── test.refresh.ts ├── test.stscredentials.ts └── test.util.ts ├── tsconfig.json ├── webpack-tests.config.js └── webpack.config.js /.compodocrc: -------------------------------------------------------------------------------- 1 | --- 2 | tsconfig: ./tsconfig.json 3 | output: ./docs 4 | theme: material 5 | hideGenerator: true 6 | disablePrivate: true 7 | disableProtected: true 8 | disableInternal: true 9 | disableCoverage: true 10 | disableGraph: true 11 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | **/coverage 3 | test/fixtures 4 | build/ 5 | docs/ 6 | protos/ 7 | samples/generated/ 8 | system-test/**/fixtures 9 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/gts" 3 | } 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.ts text eol=lf 2 | *.js text eol=lf 3 | protos/* linguist-generated 4 | **/api-extractor.json linguist-language=JSON-with-Comments 5 | -------------------------------------------------------------------------------- /.github/.OwlBot.lock.yaml: -------------------------------------------------------------------------------- 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 | # http://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 | docker: 15 | image: gcr.io/cloud-devrel-public-resources/owlbot-nodejs:latest 16 | digest: sha256:c7e4968cfc97a204a4b2381f3ecb55cabc40c4cccf88b1ef8bef0d976be87fee 17 | # created: 2025-04-08T17:33:08.498793944Z 18 | -------------------------------------------------------------------------------- /.github/.OwlBot.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 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 | # http://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 | docker: 15 | image: gcr.io/cloud-devrel-public-resources/owlbot-nodejs:latest 16 | 17 | 18 | begin-after-commit-hash: 397c0bfd367a2427104f988d5329bc117caafd95 19 | 20 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Code owners file. 2 | # This file controls who is tagged for review for any given pull request. 3 | # 4 | # For syntax help see: 5 | # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax 6 | 7 | 8 | # Unless specified, the jsteam is the default owner for nodejs repositories. 9 | * @googleapis/nodejs-auth @googleapis/jsteam -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | contact_links: 2 | - name: Google Cloud Support 3 | url: https://cloud.google.com/support/ 4 | about: If you have a support contract with Google, please use the Google Cloud Support portal. 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation_request.yml: -------------------------------------------------------------------------------- 1 | name: Documentation Requests 2 | description: Requests for more information 3 | body: 4 | - type: markdown 5 | attributes: 6 | value: > 7 | Please use this issue type to log documentation requests against the library itself. 8 | These requests should involve documentation on Github (`.md` files), and should relate to the library 9 | itself. If you have questions or documentation requests for an API, please 10 | reach out to the API tracker itself. 11 | 12 | Please submit an issue to the API team, either by submitting an 13 | issue in its issue tracker https://cloud.google.com/support/docs/issue-trackers), or by 14 | submitting an issue in its linked tracker in the .repo-metadata.json 15 | file in the API under packages/* ([example]()). 16 | You can also submit a request to documentation on cloud.google.com itself with the "Send Feedback" 17 | on the bottom of the page. 18 | 19 | 20 | Please note that documentation requests and questions for specific APIs 21 | will be closed. 22 | - type: checkboxes 23 | attributes: 24 | label: Please make sure you have searched for information in the following 25 | guides. 26 | options: 27 | - label: "Search the issues already opened: 28 | https://github.com/GoogleCloudPlatform/google-cloud-node/issues" 29 | required: true 30 | - label: "Check our Troubleshooting guide: 31 | https://googlecloudplatform.github.io/google-cloud-node/#/docs/guid\ 32 | es/troubleshooting" 33 | required: true 34 | - label: "Check our FAQ: 35 | https://googlecloudplatform.github.io/google-cloud-node/#/docs/guid\ 36 | es/faq" 37 | required: true 38 | - label: "Check our libraries HOW-TO: 39 | https://github.com/googleapis/gax-nodejs/blob/main/client-libraries\ 40 | .md" 41 | required: true 42 | - label: "Check out our authentication guide: 43 | https://github.com/googleapis/google-auth-library-nodejs" 44 | required: true 45 | - label: "Check out handwritten samples for many of our APIs: 46 | https://github.com/GoogleCloudPlatform/nodejs-docs-samples" 47 | required: true 48 | - type: textarea 49 | attributes: 50 | label: > 51 | Documentation Request 52 | validations: 53 | required: true 54 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature Request 2 | description: Suggest an idea for this library 3 | labels: 4 | - feature request 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: > 9 | **PLEASE READ**: If you have a support contract with Google, please 10 | create an issue in the [support 11 | console](https://cloud.google.com/support/) instead of filing on GitHub. 12 | This will ensure a timely response. Otherwise, please make sure to 13 | follow the steps below. 14 | - type: textarea 15 | attributes: 16 | label: > 17 | A screenshot that you have tested with "Try this API". 18 | description: > 19 | As our client libraries are mostly autogenerated, we kindly request 20 | that you test whether your feature request is with the client library, or with the 21 | API itself. To do so, please search for your API 22 | here: https://developers.google.com/apis-explorer and attempt to 23 | reproduce the issue in the given method. Please include a screenshot of 24 | the response in "Try this API". This response should NOT match the current 25 | behavior you are experiencing. If the behavior is the same, it means 26 | that you are likely requesting a feature for the API itself. In that 27 | case, please submit an issue to the API team, either by submitting an 28 | issue in its issue tracker https://cloud.google.com/support/docs/issue-trackers, or by 29 | submitting an issue in its linked tracker in the .repo-metadata.json 30 | file in the API under packages/* ([example]()) 31 | 32 | Example of library specific issues would be: retry strategies, authentication questions, or issues with typings. 33 | Examples of API issues would include: expanding method parameter types, adding functionality to an API. 34 | validations: 35 | required: true 36 | - type: textarea 37 | attributes: 38 | label: > 39 | What would you like to see in the library? 40 | description: > 41 | Screenshots can be provided in the issue body below. 42 | placeholder: | 43 | 1. Set up authentication like so 44 | 2. Run the program like so 45 | 3. X would be nice to happen 46 | 47 | - type: textarea 48 | attributes: 49 | label: Describe alternatives you've considered 50 | 51 | - type: textarea 52 | attributes: 53 | label: Additional context/notes -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/processs_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Process Request 3 | about: Submit a process request to the library. Process requests are any requests related to library infrastructure, for example CI/CD, publishing, releasing, broken links. 4 | --- 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/questions.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: If you have a question, please use Discussions 4 | 5 | --- 6 | 7 | If you have a general question that goes beyond the library itself, we encourage you to use [Discussions](https://github.com//discussions) 8 | to engage with fellow community members! 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/support_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Support request 3 | about: If you have a support contract with Google, please create an issue in the Google Cloud Support console. 4 | 5 | --- 6 | 7 | **PLEASE READ**: If you have a support contract with Google, please create an issue in the [support console](https://cloud.google.com/support/) instead of filing on GitHub. This will ensure a timely response. 8 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | > Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: 2 | 3 | ## Description 4 | 5 | > Please provide a detailed description for the change. 6 | > As much as possible, please try to keep changes separate by purpose. For example, try not to make a one-line bug fix in a feature request, or add an irrelevant README change to a bug fix. 7 | 8 | ## Impact 9 | 10 | > What's the impact of this change? 11 | 12 | ## Testing 13 | 14 | > Have you added unit and integration tests if necessary? 15 | > Were any tests changed? Are any breaking changes necessary? 16 | 17 | ## Additional Information 18 | 19 | > Any additional details that we should be aware of? 20 | 21 | ## Checklist 22 | 23 | - [ ] Make sure to open an issue as a [bug/issue](https://github.com/googleapis/google-auth-library-nodejs/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea 24 | - [ ] Ensure the tests and linter pass 25 | - [ ] Code coverage does not decrease 26 | - [ ] Appropriate docs were updated 27 | - [ ] Appropriate comments were added, particularly in complex areas or places that require background 28 | - [ ] No new warnings or issues will be generated from this change 29 | 30 | Fixes #issue_number_goes_here 🦕 31 | -------------------------------------------------------------------------------- /.github/auto-approve.yml: -------------------------------------------------------------------------------- 1 | processes: 2 | - "NodeDependency" -------------------------------------------------------------------------------- /.github/auto-label.yaml: -------------------------------------------------------------------------------- 1 | requestsize: 2 | enabled: true 3 | -------------------------------------------------------------------------------- /.github/generated-files-bot.yml: -------------------------------------------------------------------------------- 1 | generatedFiles: 2 | - path: '.kokoro/**' 3 | message: '`.kokoro` files are templated and should be updated in [`synthtool`](https://github.com/googleapis/synthtool)' 4 | - path: '.github/CODEOWNERS' 5 | message: 'CODEOWNERS should instead be modified via the `codeowner_team` property in .repo-metadata.json' 6 | - path: '.github/workflows/ci.yaml' 7 | message: '`.github/workflows/ci.yaml` (GitHub Actions) should be updated in [`synthtool`](https://github.com/googleapis/synthtool)' 8 | - path: '.github/generated-files-bot.+(yml|yaml)' 9 | message: '`.github/generated-files-bot.(yml|yaml)` should be updated in [`synthtool`](https://github.com/googleapis/synthtool)' 10 | - path: 'README.md' 11 | message: '`README.md` is managed by [`synthtool`](https://github.com/googleapis/synthtool). However, a partials file can be used to update the README, e.g.: https://github.com/googleapis/nodejs-storage/blob/main/.readme-partials.yaml' 12 | - path: 'samples/README.md' 13 | message: '`samples/README.md` is managed by [`synthtool`](https://github.com/googleapis/synthtool). However, a partials file can be used to update the README, e.g.: https://github.com/googleapis/nodejs-storage/blob/main/.readme-partials.yaml' 14 | ignoreAuthors: 15 | - 'gcf-owl-bot[bot]' 16 | - 'yoshi-automation' 17 | -------------------------------------------------------------------------------- /.github/release-please.yml: -------------------------------------------------------------------------------- 1 | handleGHRelease: true 2 | releaseType: node 3 | -------------------------------------------------------------------------------- /.github/release-trigger.yml: -------------------------------------------------------------------------------- 1 | enabled: true 2 | multiScmName: google-auth-library-nodejs -------------------------------------------------------------------------------- /.github/scripts/close-invalid-link.cjs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | // http://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 | const fs = require('fs'); 16 | const yaml = require('js-yaml'); 17 | const path = require('path'); 18 | const TEMPLATE_FILE_PATH = path.resolve(__dirname, '../ISSUE_TEMPLATE/bug_report.yml') 19 | 20 | async function closeIssue(github, owner, repo, number) { 21 | await github.rest.issues.createComment({ 22 | owner: owner, 23 | repo: repo, 24 | issue_number: number, 25 | body: "Issue was opened with an invalid reproduction link. Please make sure the repository is a valid, publicly-accessible github repository, and make sure the url is complete (example: https://github.com/googleapis/google-cloud-node)" 26 | }); 27 | await github.rest.issues.update({ 28 | owner: owner, 29 | repo: repo, 30 | issue_number: number, 31 | state: "closed" 32 | }); 33 | } 34 | module.exports = async ({ github, context }) => { 35 | const owner = context.repo.owner; 36 | const repo = context.repo.repo; 37 | const number = context.issue.number; 38 | 39 | const issue = await github.rest.issues.get({ 40 | owner: owner, 41 | repo: repo, 42 | issue_number: number, 43 | }); 44 | 45 | const yamlData = fs.readFileSync(TEMPLATE_FILE_PATH, 'utf8'); 46 | const obj = yaml.load(yamlData); 47 | const linkMatchingText = (obj.body.find(x => {return x.type === 'input' && x.validations.required === true && x.attributes.label.includes('link')})).attributes.label; 48 | const isBugTemplate = issue.data.body.includes(linkMatchingText); 49 | 50 | if (isBugTemplate) { 51 | console.log(`Issue ${number} is a bug template`) 52 | try { 53 | const text = issue.data.body; 54 | const match = text.indexOf(linkMatchingText); 55 | if (match !== -1) { 56 | const nextLineIndex = text.indexOf('http', match); 57 | if (nextLineIndex == -1) { 58 | await closeIssue(github, owner, repo, number); 59 | return; 60 | } 61 | const link = text.substring(nextLineIndex, text.indexOf('\n', nextLineIndex)); 62 | console.log(`Issue ${number} contains this link: ${link}`); 63 | const isValidLink = (await fetch(link)).ok; 64 | console.log(`Issue ${number} has a ${isValidLink ? "valid" : "invalid"} link`) 65 | if (!isValidLink) { 66 | await closeIssue(github, owner, repo, number); 67 | } 68 | } 69 | } catch (err) { 70 | await closeIssue(github, owner, repo, number); 71 | } 72 | } 73 | }; -------------------------------------------------------------------------------- /.github/scripts/close-unresponsive.cjs: -------------------------------------------------------------------------------- 1 | /// Copyright 2024 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 | // http://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 | function labeledEvent(data) { 16 | return data.event === "labeled" && data.label.name === "needs more info"; 17 | } 18 | 19 | const numberOfDaysLimit = 15; 20 | const close_message = `This has been closed since a request for information has \ 21 | not been answered for ${numberOfDaysLimit} days. It can be reopened when the \ 22 | requested information is provided.`; 23 | 24 | module.exports = async ({ github, context }) => { 25 | const owner = context.repo.owner; 26 | const repo = context.repo.repo; 27 | 28 | const issues = await github.rest.issues.listForRepo({ 29 | owner: owner, 30 | repo: repo, 31 | labels: "needs more info", 32 | }); 33 | const numbers = issues.data.map((e) => e.number); 34 | 35 | for (const number of numbers) { 36 | const events = await github.paginate( 37 | github.rest.issues.listEventsForTimeline, 38 | { 39 | owner: owner, 40 | repo: repo, 41 | issue_number: number, 42 | }, 43 | (response) => response.data.filter(labeledEvent) 44 | ); 45 | 46 | const latest_response_label = events[events.length - 1]; 47 | 48 | const created_at = new Date(latest_response_label.created_at); 49 | const now = new Date(); 50 | const diff = now - created_at; 51 | const diffDays = diff / (1000 * 60 * 60 * 24); 52 | 53 | if (diffDays > numberOfDaysLimit) { 54 | await github.rest.issues.update({ 55 | owner: owner, 56 | repo: repo, 57 | issue_number: number, 58 | state: "closed", 59 | }); 60 | 61 | await github.rest.issues.createComment({ 62 | owner: owner, 63 | repo: repo, 64 | issue_number: number, 65 | body: close_message, 66 | }); 67 | } 68 | } 69 | }; -------------------------------------------------------------------------------- /.github/scripts/fixtures/invalidIssueBody.txt: -------------------------------------------------------------------------------- 1 | ### Please make sure you have searched for information in the following guides. 2 | 3 | - [X] Search the issues already opened: https://github.com/GoogleCloudPlatform/google-cloud-node/issues 4 | - [X] Search StackOverflow: http://stackoverflow.com/questions/tagged/google-cloud-platform+node.js 5 | - [X] Check our Troubleshooting guide: https://googlecloudplatform.github.io/google-cloud-node/#/docs/guides/troubleshooting 6 | - [X] Check our FAQ: https://googlecloudplatform.github.io/google-cloud-node/#/docs/guides/faq 7 | - [X] Check our libraries HOW-TO: https://github.com/googleapis/gax-nodejs/blob/main/client-libraries.md 8 | - [X] Check out our authentication guide: https://github.com/googleapis/google-auth-library-nodejs 9 | - [X] Check out handwritten samples for many of our APIs: https://github.com/GoogleCloudPlatform/nodejs-docs-samples 10 | 11 | ### A screenshot that you have tested with "Try this API". 12 | 13 | 14 | N/A 15 | 16 | ### Link to the code that reproduces this issue. A link to a **public** Github Repository or gist with a minimal reproduction. 17 | 18 | not-a-link 19 | 20 | ### A step-by-step description of how to reproduce the issue, based on the linked reproduction. 21 | 22 | 23 | Change MY_PROJECT to your project name, add credentials if needed and run. 24 | 25 | ### A clear and concise description of what the bug is, and what you expected to happen. 26 | 27 | The application crashes with the following exception (which there is no way to catch). It should just emit error, and allow graceful handling. 28 | TypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string or an instance of Buffer or Uint8Array. Received an instance of Object 29 | at _write (node:internal/streams/writable:474:13) 30 | at Writable.write (node:internal/streams/writable:502:10) 31 | at Duplexify._write (/project/node_modules/duplexify/index.js:212:22) 32 | at doWrite (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:390:139) 33 | at writeOrBuffer (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:381:5) 34 | at Writable.write (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:302:11) 35 | at Pumpify. (/project/node_modules/@google-cloud/speech/build/src/helpers.js:79:27) 36 | at Object.onceWrapper (node:events:633:26) 37 | at Pumpify.emit (node:events:518:28) 38 | at obj. [as _write] (/project/node_modules/stubs/index.js:28:22) 39 | at doWrite (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:390:139) 40 | at writeOrBuffer (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:381:5) 41 | at Writable.write (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:302:11) 42 | at PassThrough.ondata (node:internal/streams/readable:1007:22) 43 | at PassThrough.emit (node:events:518:28) 44 | at addChunk (node:internal/streams/readable:559:12) { 45 | code: 'ERR_INVALID_ARG_TYPE' 46 | 47 | 48 | ### A clear and concise description WHY you expect this behavior, i.e., was it a recent change, there is documentation that points to this behavior, etc. ** 49 | 50 | No library should crash an application this way. -------------------------------------------------------------------------------- /.github/scripts/fixtures/validIssueBody.txt: -------------------------------------------------------------------------------- 1 | ### Please make sure you have searched for information in the following guides. 2 | 3 | - [X] Search the issues already opened: https://github.com/GoogleCloudPlatform/google-cloud-node/issues 4 | - [X] Search StackOverflow: http://stackoverflow.com/questions/tagged/google-cloud-platform+node.js 5 | - [X] Check our Troubleshooting guide: https://googlecloudplatform.github.io/google-cloud-node/#/docs/guides/troubleshooting 6 | - [X] Check our FAQ: https://googlecloudplatform.github.io/google-cloud-node/#/docs/guides/faq 7 | - [X] Check our libraries HOW-TO: https://github.com/googleapis/gax-nodejs/blob/main/client-libraries.md 8 | - [X] Check out our authentication guide: https://github.com/googleapis/google-auth-library-nodejs 9 | - [X] Check out handwritten samples for many of our APIs: https://github.com/GoogleCloudPlatform/nodejs-docs-samples 10 | 11 | ### A screenshot that you have tested with "Try this API". 12 | 13 | 14 | N/A 15 | 16 | ### Link to the code that reproduces this issue. A link to a **public** Github Repository or gist with a minimal reproduction. 17 | 18 | https://gist.github.com/orgads/13cbf44c91923da27d8772b5f10489c9 19 | 20 | ### A step-by-step description of how to reproduce the issue, based on the linked reproduction. 21 | 22 | 23 | Change MY_PROJECT to your project name, add credentials if needed and run. 24 | 25 | ### A clear and concise description of what the bug is, and what you expected to happen. 26 | 27 | The application crashes with the following exception (which there is no way to catch). It should just emit error, and allow graceful handling. 28 | TypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string or an instance of Buffer or Uint8Array. Received an instance of Object 29 | at _write (node:internal/streams/writable:474:13) 30 | at Writable.write (node:internal/streams/writable:502:10) 31 | at Duplexify._write (/project/node_modules/duplexify/index.js:212:22) 32 | at doWrite (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:390:139) 33 | at writeOrBuffer (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:381:5) 34 | at Writable.write (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:302:11) 35 | at Pumpify. (/project/node_modules/@google-cloud/speech/build/src/helpers.js:79:27) 36 | at Object.onceWrapper (node:events:633:26) 37 | at Pumpify.emit (node:events:518:28) 38 | at obj. [as _write] (/project/node_modules/stubs/index.js:28:22) 39 | at doWrite (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:390:139) 40 | at writeOrBuffer (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:381:5) 41 | at Writable.write (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:302:11) 42 | at PassThrough.ondata (node:internal/streams/readable:1007:22) 43 | at PassThrough.emit (node:events:518:28) 44 | at addChunk (node:internal/streams/readable:559:12) { 45 | code: 'ERR_INVALID_ARG_TYPE' 46 | 47 | 48 | ### A clear and concise description WHY you expect this behavior, i.e., was it a recent change, there is documentation that points to this behavior, etc. ** 49 | 50 | No library should crash an application this way. -------------------------------------------------------------------------------- /.github/scripts/fixtures/validIssueBodyDifferentLinkLocation.txt: -------------------------------------------------------------------------------- 1 | ### Please make sure you have searched for information in the following guides. 2 | 3 | - [X] Search the issues already opened: https://github.com/GoogleCloudPlatform/google-cloud-node/issues 4 | - [X] Search StackOverflow: http://stackoverflow.com/questions/tagged/google-cloud-platform+node.js 5 | - [X] Check our Troubleshooting guide: https://googlecloudplatform.github.io/google-cloud-node/#/docs/guides/troubleshooting 6 | - [X] Check our FAQ: https://googlecloudplatform.github.io/google-cloud-node/#/docs/guides/faq 7 | - [X] Check our libraries HOW-TO: https://github.com/googleapis/gax-nodejs/blob/main/client-libraries.md 8 | - [X] Check out our authentication guide: https://github.com/googleapis/google-auth-library-nodejs 9 | - [X] Check out handwritten samples for many of our APIs: https://github.com/GoogleCloudPlatform/nodejs-docs-samples 10 | 11 | ### A screenshot that you have tested with "Try this API". 12 | 13 | 14 | N/A 15 | 16 | ### A step-by-step description of how to reproduce the issue, based on the linked reproduction. 17 | 18 | 19 | Change MY_PROJECT to your project name, add credentials if needed and run. 20 | 21 | ### A clear and concise description of what the bug is, and what you expected to happen. 22 | 23 | The application crashes with the following exception (which there is no way to catch). It should just emit error, and allow graceful handling. 24 | TypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string or an instance of Buffer or Uint8Array. Received an instance of Object 25 | at _write (node:internal/streams/writable:474:13) 26 | at Writable.write (node:internal/streams/writable:502:10) 27 | at Duplexify._write (/project/node_modules/duplexify/index.js:212:22) 28 | at doWrite (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:390:139) 29 | at writeOrBuffer (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:381:5) 30 | at Writable.write (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:302:11) 31 | at Pumpify. (/project/node_modules/@google-cloud/speech/build/src/helpers.js:79:27) 32 | at Object.onceWrapper (node:events:633:26) 33 | at Pumpify.emit (node:events:518:28) 34 | at obj. [as _write] (/project/node_modules/stubs/index.js:28:22) 35 | at doWrite (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:390:139) 36 | at writeOrBuffer (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:381:5) 37 | at Writable.write (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:302:11) 38 | at PassThrough.ondata (node:internal/streams/readable:1007:22) 39 | at PassThrough.emit (node:events:518:28) 40 | at addChunk (node:internal/streams/readable:559:12) { 41 | code: 'ERR_INVALID_ARG_TYPE' 42 | 43 | ### Link to the code that reproduces this issue. A link to a **public** Github Repository with a minimal reproduction. 44 | 45 | 46 | https://gist.github.com/orgads/13cbf44c91923da27d8772b5f10489c9 47 | 48 | ### A clear and concise description WHY you expect this behavior, i.e., was it a recent change, there is documentation that points to this behavior, etc. ** 49 | 50 | No library should crash an application this way. -------------------------------------------------------------------------------- /.github/scripts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tests", 3 | "private": true, 4 | "description": "tests for script", 5 | "scripts": { 6 | "test": "mocha tests/close-invalid-link.test.cjs && mocha tests/close-or-remove-response-label.test.cjs" 7 | }, 8 | "author": "Google Inc.", 9 | "license": "Apache-2.0", 10 | "engines": { 11 | "node": ">=18" 12 | }, 13 | "dependencies": { 14 | "js-yaml": "^4.1.0" 15 | }, 16 | "devDependencies": { 17 | "@octokit/rest": "^21.0.0", 18 | "mocha": "^10.0.0", 19 | "sinon": "^18.0.0" 20 | } 21 | } -------------------------------------------------------------------------------- /.github/scripts/remove-response-label.cjs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | // http://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 | module.exports = async ({ github, context }) => { 16 | const commenter = context.actor; 17 | const issue = await github.rest.issues.get({ 18 | owner: context.repo.owner, 19 | repo: context.repo.repo, 20 | issue_number: context.issue.number, 21 | }); 22 | const author = issue.data.user.login; 23 | const labels = issue.data.labels.map((e) => e.name); 24 | 25 | if (author === commenter && labels.includes("needs more info")) { 26 | await github.rest.issues.removeLabel({ 27 | owner: context.repo.owner, 28 | repo: context.repo.repo, 29 | issue_number: context.issue.number, 30 | name: "needs more info", 31 | }); 32 | } 33 | }; -------------------------------------------------------------------------------- /.github/scripts/tests/close-invalid-link.test.cjs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | 'use strict'; 16 | 17 | const { describe, it } = require('mocha'); 18 | const closeInvalidLink = require('../close-invalid-link.cjs'); 19 | const fs = require('fs'); 20 | const sinon = require('sinon'); 21 | 22 | describe('close issues with invalid links', () => { 23 | let octokitStub; 24 | let issuesStub; 25 | 26 | beforeEach(() => { 27 | issuesStub = { 28 | get: sinon.stub(), 29 | createComment: sinon.stub(), 30 | update: sinon.stub(), 31 | }; 32 | octokitStub = { 33 | rest: { 34 | issues: issuesStub, 35 | }, 36 | }; 37 | }); 38 | 39 | afterEach(() => { 40 | sinon.restore(); 41 | }); 42 | 43 | it('does not do anything if it is not a bug', async () => { 44 | const context = { repo: { owner: 'testOrg', repo: 'testRepo' }, issue: { number: 1 } }; 45 | issuesStub.get.resolves({ data: { body: "I'm having a problem with this." } }); 46 | 47 | await closeInvalidLink({ github: octokitStub, context }); 48 | 49 | sinon.assert.calledOnce(issuesStub.get); 50 | sinon.assert.notCalled(issuesStub.createComment); 51 | sinon.assert.notCalled(issuesStub.update); 52 | }); 53 | 54 | it('does not do anything if it is a bug with an appropriate link', async () => { 55 | const context = { repo: { owner: 'testOrg', repo: 'testRepo' }, issue: { number: 1 } }; 56 | issuesStub.get.resolves({ data: { body: fs.readFileSync('./fixtures/validIssueBody.txt', 'utf-8') } }); 57 | 58 | await closeInvalidLink({ github: octokitStub, context }); 59 | 60 | sinon.assert.calledOnce(issuesStub.get); 61 | sinon.assert.notCalled(issuesStub.createComment); 62 | sinon.assert.notCalled(issuesStub.update); 63 | }); 64 | 65 | it('does not do anything if it is a bug with an appropriate link and the template changes', async () => { 66 | const context = { repo: { owner: 'testOrg', repo: 'testRepo' }, issue: { number: 1 } }; 67 | issuesStub.get.resolves({ data: { body: fs.readFileSync('./fixtures/validIssueBodyDifferentLinkLocation.txt', 'utf-8') } }); 68 | 69 | await closeInvalidLink({ github: octokitStub, context }); 70 | 71 | sinon.assert.calledOnce(issuesStub.get); 72 | sinon.assert.notCalled(issuesStub.createComment); 73 | sinon.assert.notCalled(issuesStub.update); 74 | }); 75 | 76 | it('closes the issue if the link is invalid', async () => { 77 | const context = { repo: { owner: 'testOrg', repo: 'testRepo' }, issue: { number: 1 } }; 78 | issuesStub.get.resolves({ data: { body: fs.readFileSync('./fixtures/invalidIssueBody.txt', 'utf-8') } }); 79 | 80 | await closeInvalidLink({ github: octokitStub, context }); 81 | 82 | sinon.assert.calledOnce(issuesStub.get); 83 | sinon.assert.calledOnce(issuesStub.createComment); 84 | sinon.assert.calledOnce(issuesStub.update); 85 | }); 86 | }); -------------------------------------------------------------------------------- /.github/sync-repo-settings.yaml: -------------------------------------------------------------------------------- 1 | branchProtectionRules: 2 | - pattern: main 3 | isAdminEnforced: true 4 | requiredApprovingReviewCount: 1 5 | requiresCodeOwnerReviews: true 6 | requiresStrictStatusChecks: true 7 | requiredStatusCheckContexts: 8 | - "ci/kokoro: Samples test" 9 | - "ci/kokoro: System test" 10 | - lint 11 | - test (18) 12 | - test (20) 13 | - test (22) 14 | - cla/google 15 | - windows 16 | - OwlBot Post Processor 17 | permissionRules: 18 | - team: yoshi-admins 19 | permission: admin 20 | - team: jsteam-admins 21 | permission: admin 22 | - team: jsteam 23 | permission: push 24 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | pull_request: 6 | name: ci 7 | jobs: 8 | test: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | matrix: 12 | node: [18, 20, 22] 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: actions/setup-node@v4 16 | with: 17 | node-version: ${{ matrix.node }} 18 | - run: node --version 19 | # The first installation step ensures that all of our production 20 | # dependencies work on the given Node.js version, this helps us find 21 | # dependencies that don't match our engines field: 22 | - run: npm install --production --engine-strict --ignore-scripts --no-package-lock 23 | # Clean up the production install, before installing dev/production: 24 | - run: rm -rf node_modules 25 | - run: npm install --engine-strict 26 | - run: npm test 27 | env: 28 | MOCHA_THROW_DEPRECATION: false 29 | test-script: 30 | runs-on: ubuntu-latest 31 | steps: 32 | - uses: actions/checkout@v4 33 | - uses: actions/setup-node@v4 34 | with: 35 | node-version: 18 36 | - run: node --version 37 | - run: npm install --engine-strict 38 | working-directory: .github/scripts 39 | - run: npm test 40 | working-directory: .github/scripts 41 | env: 42 | MOCHA_THROW_DEPRECATION: false 43 | windows: 44 | runs-on: windows-latest 45 | steps: 46 | - uses: actions/checkout@v4 47 | - uses: actions/setup-node@v4 48 | with: 49 | node-version: 18 50 | - run: npm install --engine-strict 51 | - run: npm test 52 | env: 53 | MOCHA_THROW_DEPRECATION: false 54 | lint: 55 | runs-on: ubuntu-latest 56 | steps: 57 | - uses: actions/checkout@v4 58 | - uses: actions/setup-node@v4 59 | with: 60 | node-version: 18 61 | - run: npm install 62 | - run: npm run lint 63 | docs: 64 | runs-on: ubuntu-latest 65 | steps: 66 | - uses: actions/checkout@v4 67 | - uses: actions/setup-node@v4 68 | with: 69 | node-version: 18 70 | - run: npm install 71 | - run: npm run docs 72 | - uses: JustinBeckwith/linkinator-action@v1 73 | with: 74 | paths: docs/ 75 | -------------------------------------------------------------------------------- /.github/workflows/issues-no-repro.yaml: -------------------------------------------------------------------------------- 1 | name: invalid_link 2 | on: 3 | issues: 4 | types: [opened, reopened] 5 | 6 | jobs: 7 | close: 8 | runs-on: ubuntu-latest 9 | permissions: 10 | issues: write 11 | pull-requests: write 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: actions/setup-node@v4 15 | with: 16 | node-version: 18 17 | - run: npm install 18 | working-directory: ./.github/scripts 19 | - uses: actions/github-script@v7 20 | with: 21 | script: | 22 | const script = require('./.github/scripts/close-invalid-link.cjs') 23 | await script({github, context}) 24 | -------------------------------------------------------------------------------- /.github/workflows/response.yaml: -------------------------------------------------------------------------------- 1 | name: no_response 2 | on: 3 | schedule: 4 | - cron: '30 1 * * *' # Run every day at 01:30 5 | workflow_dispatch: 6 | issue_comment: 7 | 8 | jobs: 9 | close: 10 | if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' 11 | runs-on: ubuntu-latest 12 | permissions: 13 | issues: write 14 | pull-requests: write 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: actions/github-script@v7 18 | with: 19 | script: | 20 | const script = require('./.github/scripts/close-unresponsive.cjs') 21 | await script({github, context}) 22 | 23 | remove_label: 24 | if: github.event_name == 'issue_comment' 25 | runs-on: ubuntu-latest 26 | permissions: 27 | issues: write 28 | pull-requests: write 29 | steps: 30 | - uses: actions/checkout@v4 31 | - uses: actions/github-script@v7 32 | with: 33 | script: | 34 | const script = require('./.github/scripts/remove-response-label.cjs') 35 | await script({github, context}) 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build/ 3 | .idea 4 | .vscode 5 | docs/ 6 | npm-debug.log 7 | .coverage 8 | coverage 9 | yarn-error.log 10 | samples/*.keys.json 11 | .nyc_output 12 | package-lock.json 13 | yarn.lock 14 | dist/ 15 | __pycache__ 16 | .DS_Store 17 | -------------------------------------------------------------------------------- /.jsdoc.js: -------------------------------------------------------------------------------- 1 | // Copyright 2019 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 | 16 | 'use strict'; 17 | 18 | module.exports = { 19 | opts: { 20 | readme: './README.md', 21 | package: './package.json', 22 | template: './node_modules/jsdoc-fresh', 23 | recurse: true, 24 | verbose: true, 25 | destination: './docs/', 26 | }, 27 | plugins: ['plugins/markdown', 'jsdoc-region-tag'], 28 | source: { 29 | include: ['build/src'], 30 | includePattern: '\\.js$', 31 | }, 32 | templates: { 33 | copyright: 'Copyright 2019 Google LLC', 34 | includeDate: false, 35 | sourceFiles: false, 36 | systemName: 'google-auth-library', 37 | theme: 'lumen', 38 | default: { 39 | outputSourceFiles: false, 40 | }, 41 | }, 42 | markdown: { 43 | idInHeadings: true, 44 | }, 45 | }; 46 | -------------------------------------------------------------------------------- /.kokoro/.gitattributes: -------------------------------------------------------------------------------- 1 | * linguist-generated=true 2 | -------------------------------------------------------------------------------- /.kokoro/browser-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2018 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eo pipefail 18 | 19 | export NPM_CONFIG_PREFIX=/home/node/.npm-global 20 | 21 | # Setup service account credentials. 22 | export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/service-account.json 23 | export GCLOUD_PROJECT=long-door-651 24 | 25 | cd $(dirname $0)/.. 26 | 27 | npm install 28 | 29 | npm run browser-test 30 | -------------------------------------------------------------------------------- /.kokoro/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | } 8 | } 9 | 10 | # Download trampoline resources. 11 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 12 | 13 | # Use the trampoline script to run in docker. 14 | build_file: "google-auth-library-nodejs/.kokoro/trampoline_v2.sh" 15 | 16 | # Configure the docker image for kokoro-trampoline. 17 | env_vars: { 18 | key: "TRAMPOLINE_IMAGE" 19 | value: "gcr.io/cloud-devrel-kokoro-resources/node:18-user" 20 | } 21 | env_vars: { 22 | key: "TRAMPOLINE_BUILD_FILE" 23 | value: "github/google-auth-library-nodejs/.kokoro/test.sh" 24 | } 25 | -------------------------------------------------------------------------------- /.kokoro/continuous/node14/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | } 8 | } 9 | 10 | # Download trampoline resources. 11 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 12 | 13 | # Use the trampoline script to run in docker. 14 | build_file: "google-auth-library-nodejs/.kokoro/trampoline_v2.sh" 15 | 16 | # Configure the docker image for kokoro-trampoline. 17 | env_vars: { 18 | key: "TRAMPOLINE_IMAGE" 19 | value: "gcr.io/cloud-devrel-kokoro-resources/node:18-user" 20 | } 21 | env_vars: { 22 | key: "TRAMPOLINE_BUILD_FILE" 23 | value: "github/google-auth-library-nodejs/.kokoro/test.sh" 24 | } 25 | -------------------------------------------------------------------------------- /.kokoro/continuous/node14/lint.cfg: -------------------------------------------------------------------------------- 1 | env_vars: { 2 | key: "TRAMPOLINE_BUILD_FILE" 3 | value: "github/google-auth-library-nodejs/.kokoro/lint.sh" 4 | } 5 | -------------------------------------------------------------------------------- /.kokoro/continuous/node14/samples-test.cfg: -------------------------------------------------------------------------------- 1 | # Download resources for system tests (service account key, etc.) 2 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-nodejs" 3 | 4 | env_vars: { 5 | key: "TRAMPOLINE_BUILD_FILE" 6 | value: "github/google-auth-library-nodejs/.kokoro/samples-test.sh" 7 | } 8 | 9 | env_vars: { 10 | key: "SECRET_MANAGER_KEYS" 11 | value: "long-door-651-kokoro-system-test-service-account" 12 | } -------------------------------------------------------------------------------- /.kokoro/continuous/node14/system-test.cfg: -------------------------------------------------------------------------------- 1 | # Download resources for system tests (service account key, etc.) 2 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-nodejs" 3 | 4 | env_vars: { 5 | key: "TRAMPOLINE_BUILD_FILE" 6 | value: "github/google-auth-library-nodejs/.kokoro/system-test.sh" 7 | } 8 | 9 | env_vars: { 10 | key: "SECRET_MANAGER_KEYS" 11 | value: "long-door-651-kokoro-system-test-service-account" 12 | } -------------------------------------------------------------------------------- /.kokoro/continuous/node14/test.cfg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-nodejs/ed6296b02a18920399f9d2401cfe615d3698ef38/.kokoro/continuous/node14/test.cfg -------------------------------------------------------------------------------- /.kokoro/continuous/node18/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | } 8 | } 9 | 10 | # Download trampoline resources. 11 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 12 | 13 | # Use the trampoline script to run in docker. 14 | build_file: "google-auth-library-nodejs/.kokoro/trampoline_v2.sh" 15 | 16 | # Configure the docker image for kokoro-trampoline. 17 | env_vars: { 18 | key: "TRAMPOLINE_IMAGE" 19 | value: "gcr.io/cloud-devrel-kokoro-resources/node:18-user" 20 | } 21 | env_vars: { 22 | key: "TRAMPOLINE_BUILD_FILE" 23 | value: "github/google-auth-library-nodejs/.kokoro/test.sh" 24 | } 25 | -------------------------------------------------------------------------------- /.kokoro/continuous/node18/lint.cfg: -------------------------------------------------------------------------------- 1 | env_vars: { 2 | key: "TRAMPOLINE_BUILD_FILE" 3 | value: "github/google-auth-library-nodejs/.kokoro/lint.sh" 4 | } 5 | -------------------------------------------------------------------------------- /.kokoro/continuous/node18/samples-test.cfg: -------------------------------------------------------------------------------- 1 | # Download resources for system tests (service account key, etc.) 2 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-nodejs" 3 | 4 | env_vars: { 5 | key: "TRAMPOLINE_BUILD_FILE" 6 | value: "github/google-auth-library-nodejs/.kokoro/samples-test.sh" 7 | } 8 | 9 | env_vars: { 10 | key: "SECRET_MANAGER_KEYS" 11 | value: "long-door-651-kokoro-system-test-service-account" 12 | } -------------------------------------------------------------------------------- /.kokoro/continuous/node18/system-test.cfg: -------------------------------------------------------------------------------- 1 | # Download resources for system tests (service account key, etc.) 2 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-nodejs" 3 | 4 | env_vars: { 5 | key: "TRAMPOLINE_BUILD_FILE" 6 | value: "github/google-auth-library-nodejs/.kokoro/system-test.sh" 7 | } 8 | 9 | env_vars: { 10 | key: "SECRET_MANAGER_KEYS" 11 | value: "long-door-651-kokoro-system-test-service-account" 12 | } -------------------------------------------------------------------------------- /.kokoro/continuous/node18/test.cfg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-nodejs/ed6296b02a18920399f9d2401cfe615d3698ef38/.kokoro/continuous/node18/test.cfg -------------------------------------------------------------------------------- /.kokoro/docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2018 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eo pipefail 18 | 19 | export NPM_CONFIG_PREFIX=${HOME}/.npm-global 20 | 21 | cd $(dirname $0)/.. 22 | 23 | npm install 24 | 25 | npm run docs-test 26 | -------------------------------------------------------------------------------- /.kokoro/lint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2018 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eo pipefail 18 | 19 | export NPM_CONFIG_PREFIX=${HOME}/.npm-global 20 | 21 | cd $(dirname $0)/.. 22 | 23 | npm install 24 | 25 | # Install and link samples 26 | if [ -f samples/package.json ]; then 27 | cd samples/ 28 | npm link ../ 29 | npm install 30 | cd .. 31 | fi 32 | 33 | npm run lint 34 | -------------------------------------------------------------------------------- /.kokoro/populate-secrets.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2020 Google LLC. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | # This file is called in the early stage of `trampoline_v2.sh` to 17 | # populate secrets needed for the CI builds. 18 | 19 | set -eo pipefail 20 | 21 | function now { date +"%Y-%m-%d %H:%M:%S" | tr -d '\n' ;} 22 | function msg { println "$*" >&2 ;} 23 | function println { printf '%s\n' "$(now) $*" ;} 24 | 25 | # Populates requested secrets set in SECRET_MANAGER_KEYS 26 | 27 | # In Kokoro CI builds, we use the service account attached to the 28 | # Kokoro VM. This means we need to setup auth on other CI systems. 29 | # For local run, we just use the gcloud command for retrieving the 30 | # secrets. 31 | 32 | if [[ "${RUNNING_IN_CI:-}" == "true" ]]; then 33 | GCLOUD_COMMANDS=( 34 | "docker" 35 | "run" 36 | "--entrypoint=gcloud" 37 | "--volume=${KOKORO_GFILE_DIR}:${KOKORO_GFILE_DIR}" 38 | "gcr.io/google.com/cloudsdktool/cloud-sdk" 39 | ) 40 | if [[ "${TRAMPOLINE_CI:-}" == "kokoro" ]]; then 41 | SECRET_LOCATION="${KOKORO_GFILE_DIR}/secret_manager" 42 | else 43 | echo "Authentication for this CI system is not implemented yet." 44 | exit 2 45 | # TODO: Determine appropriate SECRET_LOCATION and the GCLOUD_COMMANDS. 46 | fi 47 | else 48 | # For local run, use /dev/shm or temporary directory for 49 | # KOKORO_GFILE_DIR. 50 | if [[ -d "/dev/shm" ]]; then 51 | export KOKORO_GFILE_DIR=/dev/shm 52 | else 53 | export KOKORO_GFILE_DIR=$(mktemp -d -t ci-XXXXXXXX) 54 | fi 55 | SECRET_LOCATION="${KOKORO_GFILE_DIR}/secret_manager" 56 | GCLOUD_COMMANDS=("gcloud") 57 | fi 58 | 59 | msg "Creating folder on disk for secrets: ${SECRET_LOCATION}" 60 | mkdir -p ${SECRET_LOCATION} 61 | 62 | for key in $(echo ${SECRET_MANAGER_KEYS} | sed "s/,/ /g") 63 | do 64 | msg "Retrieving secret ${key}" 65 | "${GCLOUD_COMMANDS[@]}" \ 66 | secrets versions access latest \ 67 | --project cloud-devrel-kokoro-resources \ 68 | --secret $key > \ 69 | "$SECRET_LOCATION/$key" 70 | if [[ $? == 0 ]]; then 71 | msg "Secret written to ${SECRET_LOCATION}/${key}" 72 | else 73 | msg "Error retrieving secret ${key}" 74 | exit 2 75 | fi 76 | done 77 | -------------------------------------------------------------------------------- /.kokoro/presubmit/node14/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | } 8 | } 9 | 10 | # Download trampoline resources. 11 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 12 | 13 | # Use the trampoline script to run in docker. 14 | build_file: "google-auth-library-nodejs/.kokoro/trampoline_v2.sh" 15 | 16 | # Configure the docker image for kokoro-trampoline. 17 | env_vars: { 18 | key: "TRAMPOLINE_IMAGE" 19 | value: "gcr.io/cloud-devrel-kokoro-resources/node:18-user" 20 | } 21 | env_vars: { 22 | key: "TRAMPOLINE_BUILD_FILE" 23 | value: "github/google-auth-library-nodejs/.kokoro/test.sh" 24 | } 25 | -------------------------------------------------------------------------------- /.kokoro/presubmit/node14/samples-test.cfg: -------------------------------------------------------------------------------- 1 | # Download resources for system tests (service account key, etc.) 2 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-nodejs" 3 | 4 | env_vars: { 5 | key: "TRAMPOLINE_BUILD_FILE" 6 | value: "github/google-auth-library-nodejs/.kokoro/samples-test.sh" 7 | } 8 | 9 | env_vars: { 10 | key: "SECRET_MANAGER_KEYS" 11 | value: "long-door-651-kokoro-system-test-service-account" 12 | } -------------------------------------------------------------------------------- /.kokoro/presubmit/node14/system-test.cfg: -------------------------------------------------------------------------------- 1 | # Download resources for system tests (service account key, etc.) 2 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-nodejs" 3 | 4 | env_vars: { 5 | key: "TRAMPOLINE_BUILD_FILE" 6 | value: "github/google-auth-library-nodejs/.kokoro/system-test.sh" 7 | } 8 | 9 | env_vars: { 10 | key: "SECRET_MANAGER_KEYS" 11 | value: "long-door-651-kokoro-system-test-service-account" 12 | } -------------------------------------------------------------------------------- /.kokoro/presubmit/node14/test.cfg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-nodejs/ed6296b02a18920399f9d2401cfe615d3698ef38/.kokoro/presubmit/node14/test.cfg -------------------------------------------------------------------------------- /.kokoro/presubmit/node18/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | } 8 | } 9 | 10 | # Download trampoline resources. 11 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 12 | 13 | # Use the trampoline script to run in docker. 14 | build_file: "google-auth-library-nodejs/.kokoro/trampoline_v2.sh" 15 | 16 | # Configure the docker image for kokoro-trampoline. 17 | env_vars: { 18 | key: "TRAMPOLINE_IMAGE" 19 | value: "gcr.io/cloud-devrel-kokoro-resources/node:18-user" 20 | } 21 | env_vars: { 22 | key: "TRAMPOLINE_BUILD_FILE" 23 | value: "github/google-auth-library-nodejs/.kokoro/test.sh" 24 | } 25 | -------------------------------------------------------------------------------- /.kokoro/presubmit/node18/samples-test.cfg: -------------------------------------------------------------------------------- 1 | # Download resources for system tests (service account key, etc.) 2 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-nodejs" 3 | 4 | env_vars: { 5 | key: "TRAMPOLINE_BUILD_FILE" 6 | value: "github/google-auth-library-nodejs/.kokoro/samples-test.sh" 7 | } 8 | 9 | env_vars: { 10 | key: "SECRET_MANAGER_KEYS" 11 | value: "long-door-651-kokoro-system-test-service-account" 12 | } -------------------------------------------------------------------------------- /.kokoro/presubmit/node18/system-test.cfg: -------------------------------------------------------------------------------- 1 | # Download resources for system tests (service account key, etc.) 2 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-nodejs" 3 | 4 | env_vars: { 5 | key: "TRAMPOLINE_BUILD_FILE" 6 | value: "github/google-auth-library-nodejs/.kokoro/system-test.sh" 7 | } 8 | 9 | env_vars: { 10 | key: "SECRET_MANAGER_KEYS" 11 | value: "long-door-651-kokoro-system-test-service-account" 12 | } -------------------------------------------------------------------------------- /.kokoro/presubmit/node18/test.cfg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-nodejs/ed6296b02a18920399f9d2401cfe615d3698ef38/.kokoro/presubmit/node18/test.cfg -------------------------------------------------------------------------------- /.kokoro/presubmit/windows/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | -------------------------------------------------------------------------------- /.kokoro/presubmit/windows/test.cfg: -------------------------------------------------------------------------------- 1 | # Use the test file directly 2 | build_file: "google-auth-library-nodejs/.kokoro/test.bat" 3 | -------------------------------------------------------------------------------- /.kokoro/publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2018 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eo pipefail 18 | 19 | export NPM_CONFIG_PREFIX=${HOME}/.npm-global 20 | 21 | # Start the releasetool reporter 22 | python3 -m releasetool publish-reporter-script > /tmp/publisher-script; source /tmp/publisher-script 23 | 24 | cd $(dirname $0)/.. 25 | 26 | NPM_TOKEN=$(cat $KOKORO_KEYSTORE_DIR/73713_google-cloud-npm-token-1) 27 | echo "//wombat-dressing-room.appspot.com/:_authToken=${NPM_TOKEN}" > ~/.npmrc 28 | 29 | npm install 30 | npm pack . 31 | # npm provides no way to specify, observe, or predict the name of the tarball 32 | # file it generates. We have to look in the current directory for the freshest 33 | # .tgz file. 34 | TARBALL=$(ls -1 -t *.tgz | head -1) 35 | 36 | npm publish --access=public --registry=https://wombat-dressing-room.appspot.com "$TARBALL" 37 | 38 | # Kokoro collects *.tgz and package-lock.json files and stores them in Placer 39 | # so we can generate SBOMs and attestations. 40 | # However, we *don't* want Kokoro to collect package-lock.json and *.tgz files 41 | # that happened to be installed with dependencies. 42 | find node_modules -name package-lock.json -o -name "*.tgz" | xargs rm -f -------------------------------------------------------------------------------- /.kokoro/release/common.cfg: -------------------------------------------------------------------------------- 1 | before_action { 2 | fetch_keystore { 3 | keystore_resource { 4 | keystore_config_id: 73713 5 | keyname: "yoshi-automation-github-key" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.kokoro/release/docs-devsite.cfg: -------------------------------------------------------------------------------- 1 | # service account used to publish up-to-date docs. 2 | before_action { 3 | fetch_keystore { 4 | keystore_resource { 5 | keystore_config_id: 73713 6 | keyname: "docuploader_service_account" 7 | } 8 | } 9 | } 10 | 11 | # doc publications use a Python image. 12 | env_vars: { 13 | key: "TRAMPOLINE_IMAGE" 14 | value: "gcr.io/cloud-devrel-kokoro-resources/node:18-user" 15 | } 16 | 17 | # Download trampoline resources. 18 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 19 | 20 | # Use the trampoline script to run in docker. 21 | build_file: "google-auth-library-nodejs/.kokoro/trampoline_v2.sh" 22 | 23 | env_vars: { 24 | key: "TRAMPOLINE_BUILD_FILE" 25 | value: "github/google-auth-library-nodejs/.kokoro/release/docs-devsite.sh" 26 | } 27 | -------------------------------------------------------------------------------- /.kokoro/release/docs-devsite.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2021 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eo pipefail 18 | 19 | if [[ -z "$CREDENTIALS" ]]; then 20 | # if CREDENTIALS are explicitly set, assume we're testing locally 21 | # and don't set NPM_CONFIG_PREFIX. 22 | export NPM_CONFIG_PREFIX=${HOME}/.npm-global 23 | export PATH="$PATH:${NPM_CONFIG_PREFIX}/bin" 24 | cd $(dirname $0)/../.. 25 | fi 26 | 27 | npm install 28 | npm install --no-save @google-cloud/cloud-rad@^0.4.0 29 | # publish docs to devsite 30 | npx @google-cloud/cloud-rad . cloud-rad 31 | -------------------------------------------------------------------------------- /.kokoro/release/docs.cfg: -------------------------------------------------------------------------------- 1 | # service account used to publish up-to-date docs. 2 | before_action { 3 | fetch_keystore { 4 | keystore_resource { 5 | keystore_config_id: 73713 6 | keyname: "docuploader_service_account" 7 | } 8 | } 9 | } 10 | 11 | # doc publications use a Python image. 12 | env_vars: { 13 | key: "TRAMPOLINE_IMAGE" 14 | value: "gcr.io/cloud-devrel-kokoro-resources/node:18-user" 15 | } 16 | 17 | # Download trampoline resources. 18 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 19 | 20 | # Use the trampoline script to run in docker. 21 | build_file: "google-auth-library-nodejs/.kokoro/trampoline_v2.sh" 22 | 23 | env_vars: { 24 | key: "TRAMPOLINE_BUILD_FILE" 25 | value: "github/google-auth-library-nodejs/.kokoro/release/docs.sh" 26 | } 27 | -------------------------------------------------------------------------------- /.kokoro/release/docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2019 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eo pipefail 18 | 19 | # build jsdocs (Python is installed on the Node 18 docker image). 20 | if [[ -z "$CREDENTIALS" ]]; then 21 | # if CREDENTIALS are explicitly set, assume we're testing locally 22 | # and don't set NPM_CONFIG_PREFIX. 23 | export NPM_CONFIG_PREFIX=${HOME}/.npm-global 24 | export PATH="$PATH:${NPM_CONFIG_PREFIX}/bin" 25 | cd $(dirname $0)/../.. 26 | fi 27 | npm install 28 | npm run docs 29 | 30 | # create docs.metadata, based on package.json and .repo-metadata.json. 31 | npm i json@9.0.6 -g 32 | python3 -m docuploader create-metadata \ 33 | --name=$(cat .repo-metadata.json | json name) \ 34 | --version=$(cat package.json | json version) \ 35 | --language=$(cat .repo-metadata.json | json language) \ 36 | --distribution-name=$(cat .repo-metadata.json | json distribution_name) \ 37 | --product-page=$(cat .repo-metadata.json | json product_documentation) \ 38 | --github-repository=$(cat .repo-metadata.json | json repo) \ 39 | --issue-tracker=$(cat .repo-metadata.json | json issue_tracker) 40 | cp docs.metadata ./docs/docs.metadata 41 | 42 | # deploy the docs. 43 | if [[ -z "$CREDENTIALS" ]]; then 44 | CREDENTIALS=${KOKORO_KEYSTORE_DIR}/73713_docuploader_service_account 45 | fi 46 | if [[ -z "$BUCKET" ]]; then 47 | BUCKET=docs-staging 48 | fi 49 | python3 -m docuploader upload ./docs --credentials $CREDENTIALS --staging-bucket $BUCKET 50 | -------------------------------------------------------------------------------- /.kokoro/release/publish.cfg: -------------------------------------------------------------------------------- 1 | before_action { 2 | fetch_keystore { 3 | keystore_resource { 4 | keystore_config_id: 73713 5 | keyname: "docuploader_service_account" 6 | } 7 | } 8 | } 9 | 10 | before_action { 11 | fetch_keystore { 12 | keystore_resource { 13 | keystore_config_id: 73713 14 | keyname: "google-cloud-npm-token-1" 15 | } 16 | } 17 | } 18 | 19 | env_vars: { 20 | key: "SECRET_MANAGER_KEYS" 21 | value: "releasetool-publish-reporter-app,releasetool-publish-reporter-googleapis-installation,releasetool-publish-reporter-pem" 22 | } 23 | 24 | # Download trampoline resources. 25 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 26 | 27 | # Use the trampoline script to run in docker. 28 | build_file: "google-auth-library-nodejs/.kokoro/trampoline_v2.sh" 29 | 30 | # Configure the docker image for kokoro-trampoline. 31 | env_vars: { 32 | key: "TRAMPOLINE_IMAGE" 33 | value: "gcr.io/cloud-devrel-kokoro-resources/node:18-user" 34 | } 35 | 36 | env_vars: { 37 | key: "TRAMPOLINE_BUILD_FILE" 38 | value: "github/google-auth-library-nodejs/.kokoro/publish.sh" 39 | } 40 | 41 | # Store the packages we uploaded to npmjs.org and their corresponding 42 | # package-lock.jsons in Placer. That way, we have a record of exactly 43 | # what we published, and which version of which tools we used to publish 44 | # it, which we can use to generate SBOMs and attestations. 45 | action { 46 | define_artifacts { 47 | regex: "github/**/*.tgz" 48 | regex: "github/**/package-lock.json" 49 | strip_prefix: "github" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /.kokoro/samples-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2018 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eo pipefail 18 | 19 | # Ensure the npm global directory is writable, otherwise rebuild `npm` 20 | mkdir -p $NPM_CONFIG_PREFIX 21 | npm config -g ls || npm i -g npm@`npm --version` 22 | 23 | # Setup service account credentials. 24 | export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/secret_manager/long-door-651-kokoro-system-test-service-account 25 | export GCLOUD_PROJECT=long-door-651 26 | 27 | cd $(dirname $0)/.. 28 | 29 | # Run a pre-test hook, if a pre-samples-test.sh is in the project 30 | if [ -f .kokoro/pre-samples-test.sh ]; then 31 | set +x 32 | . .kokoro/pre-samples-test.sh 33 | set -x 34 | fi 35 | 36 | if [ -f samples/package.json ]; then 37 | npm install 38 | 39 | # Install and link samples 40 | cd samples/ 41 | npm link ../ 42 | npm install 43 | cd .. 44 | # If tests are running against main branch, configure flakybot 45 | # to open issues on failures: 46 | if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"continuous"* ]] || [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"nightly"* ]]; then 47 | export MOCHA_REPORTER_OUTPUT=test_output_sponge_log.xml 48 | export MOCHA_REPORTER=xunit 49 | cleanup() { 50 | chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot 51 | $KOKORO_GFILE_DIR/linux_amd64/flakybot 52 | } 53 | trap cleanup EXIT HUP 54 | fi 55 | 56 | npm run samples-test 57 | fi 58 | 59 | # codecov combines coverage across integration and unit tests. Include 60 | # the logic below for any environment you wish to collect coverage for: 61 | COVERAGE_NODE=18 62 | if npx check-node-version@3.3.0 --silent --node $COVERAGE_NODE; then 63 | NYC_BIN=./node_modules/nyc/bin/nyc.js 64 | if [ -f "$NYC_BIN" ]; then 65 | $NYC_BIN report || true 66 | fi 67 | bash $KOKORO_GFILE_DIR/codecov.sh 68 | else 69 | echo "coverage is only reported for Node $COVERAGE_NODE" 70 | fi 71 | -------------------------------------------------------------------------------- /.kokoro/system-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2018 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eo pipefail 18 | 19 | export NPM_CONFIG_PREFIX=${HOME}/.npm-global 20 | 21 | # Setup service account credentials. 22 | export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/secret_manager/long-door-651-kokoro-system-test-service-account 23 | export GCLOUD_PROJECT=long-door-651 24 | 25 | cd $(dirname $0)/.. 26 | 27 | # Run a pre-test hook, if a pre-system-test.sh is in the project 28 | if [ -f .kokoro/pre-system-test.sh ]; then 29 | set +x 30 | . .kokoro/pre-system-test.sh 31 | set -x 32 | fi 33 | 34 | npm install 35 | 36 | # If tests are running against main branch, configure flakybot 37 | # to open issues on failures: 38 | if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"continuous"* ]] || [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"nightly"* ]]; then 39 | export MOCHA_REPORTER_OUTPUT=test_output_sponge_log.xml 40 | export MOCHA_REPORTER=xunit 41 | cleanup() { 42 | chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot 43 | $KOKORO_GFILE_DIR/linux_amd64/flakybot 44 | } 45 | trap cleanup EXIT HUP 46 | fi 47 | 48 | npm run system-test 49 | 50 | # codecov combines coverage across integration and unit tests. Include 51 | # the logic below for any environment you wish to collect coverage for: 52 | COVERAGE_NODE=18 53 | if npx check-node-version@3.3.0 --silent --node $COVERAGE_NODE; then 54 | NYC_BIN=./node_modules/nyc/bin/nyc.js 55 | if [ -f "$NYC_BIN" ]; then 56 | $NYC_BIN report || true 57 | fi 58 | bash $KOKORO_GFILE_DIR/codecov.sh 59 | else 60 | echo "coverage is only reported for Node $COVERAGE_NODE" 61 | fi 62 | -------------------------------------------------------------------------------- /.kokoro/test.bat: -------------------------------------------------------------------------------- 1 | @rem Copyright 2018 Google LLC. All rights reserved. 2 | @rem 3 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 4 | @rem you may not use this file except in compliance with the License. 5 | @rem You may obtain a copy of the License at 6 | @rem 7 | @rem http://www.apache.org/licenses/LICENSE-2.0 8 | @rem 9 | @rem Unless required by applicable law or agreed to in writing, software 10 | @rem distributed under the License is distributed on an "AS IS" BASIS, 11 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | @rem See the License for the specific language governing permissions and 13 | @rem limitations under the License. 14 | 15 | @echo "Starting Windows build" 16 | 17 | cd /d %~dp0 18 | cd .. 19 | 20 | @rem npm path is not currently set in our image, we should fix this next time 21 | @rem we upgrade Node.js in the image: 22 | SET PATH=%PATH%;/cygdrive/c/Program Files/nodejs/npm 23 | 24 | call nvm use 18 25 | call which node 26 | 27 | call npm install || goto :error 28 | call npm run test || goto :error 29 | 30 | goto :EOF 31 | 32 | :error 33 | exit /b 1 34 | -------------------------------------------------------------------------------- /.kokoro/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2018 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eo pipefail 18 | 19 | export NPM_CONFIG_PREFIX=${HOME}/.npm-global 20 | 21 | cd $(dirname $0)/.. 22 | 23 | npm install 24 | # If tests are running against main branch, configure flakybot 25 | # to open issues on failures: 26 | if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"continuous"* ]] || [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"nightly"* ]]; then 27 | export MOCHA_REPORTER_OUTPUT=test_output_sponge_log.xml 28 | export MOCHA_REPORTER=xunit 29 | cleanup() { 30 | chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot 31 | $KOKORO_GFILE_DIR/linux_amd64/flakybot 32 | } 33 | trap cleanup EXIT HUP 34 | fi 35 | # Unit tests exercise the entire API surface, which may include 36 | # deprecation warnings: 37 | export MOCHA_THROW_DEPRECATION=false 38 | npm test 39 | 40 | # codecov combines coverage across integration and unit tests. Include 41 | # the logic below for any environment you wish to collect coverage for: 42 | COVERAGE_NODE=18 43 | if npx check-node-version@3.3.0 --silent --node $COVERAGE_NODE; then 44 | NYC_BIN=./node_modules/nyc/bin/nyc.js 45 | if [ -f "$NYC_BIN" ]; then 46 | $NYC_BIN report || true 47 | fi 48 | bash $KOKORO_GFILE_DIR/codecov.sh 49 | else 50 | echo "coverage is only reported for Node $COVERAGE_NODE" 51 | fi 52 | -------------------------------------------------------------------------------- /.kokoro/trampoline.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2017 Google Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | # This file is not used any more, but we keep this file for making it 17 | # easy to roll back. 18 | # TODO: Remove this file from the template. 19 | 20 | set -eo pipefail 21 | 22 | # Always run the cleanup script, regardless of the success of bouncing into 23 | # the container. 24 | function cleanup() { 25 | chmod +x ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh 26 | ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh 27 | echo "cleanup"; 28 | } 29 | trap cleanup EXIT 30 | 31 | $(dirname $0)/populate-secrets.sh # Secret Manager secrets. 32 | python3 "${KOKORO_GFILE_DIR}/trampoline_v1.py" 33 | -------------------------------------------------------------------------------- /.mocharc.js: -------------------------------------------------------------------------------- 1 | // Copyright 2020 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 | // http://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 | const config = { 15 | "enable-source-maps": true, 16 | "throw-deprecation": true, 17 | "timeout": 10000, 18 | "recursive": true 19 | } 20 | if (process.env.MOCHA_THROW_DEPRECATION === 'false') { 21 | delete config['throw-deprecation']; 22 | } 23 | if (process.env.MOCHA_REPORTER) { 24 | config.reporter = process.env.MOCHA_REPORTER; 25 | } 26 | if (process.env.MOCHA_REPORTER_OUTPUT) { 27 | config['reporter-option'] = `output=${process.env.MOCHA_REPORTER_OUTPUT}`; 28 | } 29 | module.exports = config 30 | -------------------------------------------------------------------------------- /.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "report-dir": "./.coverage", 3 | "reporter": ["text", "lcov"], 4 | "exclude": [ 5 | "**/*-test", 6 | "**/.coverage", 7 | "**/apis", 8 | "**/benchmark", 9 | "**/conformance", 10 | "**/docs", 11 | "**/samples", 12 | "**/scripts", 13 | "**/protos", 14 | "**/test", 15 | "**/*.d.ts", 16 | ".jsdoc.js", 17 | "**/.jsdoc.js", 18 | "karma.conf.js", 19 | "webpack-tests.config.js", 20 | "webpack.config.js" 21 | ], 22 | "exclude-after-remap": false, 23 | "all": true 24 | } 25 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | **/coverage 3 | test/fixtures 4 | build/ 5 | docs/ 6 | protos/ 7 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | // Copyright 2020 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 | module.exports = { 16 | ...require('gts/.prettierrc.json') 17 | } 18 | -------------------------------------------------------------------------------- /.repo-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "google-auth-library", 3 | "name_pretty": "Google Auth Library", 4 | "product_documentation": "https://cloud.google.com/docs/authentication/", 5 | "client_documentation": "https://cloud.google.com/nodejs/docs/reference/google-auth-library/latest", 6 | "release_level": "stable", 7 | "language": "nodejs", 8 | "repo": "googleapis/google-auth-library-nodejs", 9 | "distribution_name": "google-auth-library", 10 | "codeowner_team": "@googleapis/nodejs-auth", 11 | "library_type": "AUTH" 12 | } 13 | -------------------------------------------------------------------------------- /.trampolinerc: -------------------------------------------------------------------------------- 1 | # Copyright 2020 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 | # http://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 | # Template for .trampolinerc 16 | 17 | # Add required env vars here. 18 | required_envvars+=( 19 | ) 20 | 21 | # Add env vars which are passed down into the container here. 22 | pass_down_envvars+=( 23 | "AUTORELEASE_PR" 24 | "VERSION" 25 | ) 26 | 27 | # Prevent unintentional override on the default image. 28 | if [[ "${TRAMPOLINE_IMAGE_UPLOAD:-false}" == "true" ]] && \ 29 | [[ -z "${TRAMPOLINE_IMAGE:-}" ]]; then 30 | echo "Please set TRAMPOLINE_IMAGE if you want to upload the Docker image." 31 | exit 1 32 | fi 33 | 34 | # Define the default value if it makes sense. 35 | if [[ -z "${TRAMPOLINE_IMAGE_UPLOAD:-}" ]]; then 36 | TRAMPOLINE_IMAGE_UPLOAD="" 37 | fi 38 | 39 | if [[ -z "${TRAMPOLINE_IMAGE:-}" ]]; then 40 | TRAMPOLINE_IMAGE="" 41 | fi 42 | 43 | if [[ -z "${TRAMPOLINE_DOCKERFILE:-}" ]]; then 44 | TRAMPOLINE_DOCKERFILE="" 45 | fi 46 | 47 | if [[ -z "${TRAMPOLINE_BUILD_FILE:-}" ]]; then 48 | TRAMPOLINE_BUILD_FILE="" 49 | fi 50 | 51 | # Secret Manager secrets. 52 | source ${PROJECT_ROOT}/.kokoro/populate-secrets.sh 53 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to become a contributor and submit your own code 2 | 3 | **Table of contents** 4 | 5 | * [Contributor License Agreements](#contributor-license-agreements) 6 | * [Contributing a patch](#contributing-a-patch) 7 | * [Running the tests](#running-the-tests) 8 | * [Releasing the library](#releasing-the-library) 9 | 10 | ## Contributor License Agreements 11 | 12 | We'd love to accept your sample apps and patches! Before we can take them, we 13 | have to jump a couple of legal hurdles. 14 | 15 | Please fill out either the individual or corporate Contributor License Agreement 16 | (CLA). 17 | 18 | * If you are an individual writing original source code and you're sure you 19 | own the intellectual property, then you'll need to sign an [individual CLA](https://developers.google.com/open-source/cla/individual). 20 | * If you work for a company that wants to allow you to contribute your work, 21 | then you'll need to sign a [corporate CLA](https://developers.google.com/open-source/cla/corporate). 22 | 23 | Follow either of the two links above to access the appropriate CLA and 24 | instructions for how to sign and return it. Once we receive it, we'll be able to 25 | accept your pull requests. 26 | 27 | ## Contributing A Patch 28 | 29 | 1. Submit an issue describing your proposed change to the repo in question. 30 | 1. The repo owner will respond to your issue promptly. 31 | 1. If your proposed change is accepted, and you haven't already done so, sign a 32 | Contributor License Agreement (see details above). 33 | 1. Fork the desired repo, develop and test your code changes. 34 | 1. Ensure that your code adheres to the existing style in the code to which 35 | you are contributing. 36 | 1. Ensure that your code has an appropriate set of tests which all pass. 37 | 1. Title your pull request following [Conventional Commits](https://www.conventionalcommits.org/) styling. 38 | 1. Submit a pull request. 39 | 40 | ### Before you begin 41 | 42 | 1. [Select or create a Cloud Platform project][projects]. 43 | 1. [Set up authentication with a service account][auth] so you can access the 44 | API from your local workstation. 45 | 46 | 47 | ## Running the tests 48 | 49 | 1. [Prepare your environment for Node.js setup][setup]. 50 | 51 | 1. Install dependencies: 52 | 53 | npm install 54 | 55 | 1. Run the tests: 56 | 57 | # Run unit tests. 58 | npm test 59 | 60 | # Run sample integration tests. 61 | npm run samples-test 62 | 63 | # Run all system tests. 64 | npm run system-test 65 | 66 | 1. Lint (and maybe fix) any changes: 67 | 68 | npm run fix 69 | 70 | [setup]: https://cloud.google.com/nodejs/docs/setup 71 | [projects]: https://console.cloud.google.com/project 72 | [billing]: https://support.google.com/cloud/answer/6293499#enable-billing 73 | 74 | [auth]: https://cloud.google.com/docs/authentication/getting-started -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | To report a security issue, please use [g.co/vulnz](https://g.co/vulnz). 4 | 5 | The Google Security Team will respond within 5 working days of your report on g.co/vulnz. 6 | 7 | We use g.co/vulnz for our intake, and do coordination and disclosure here using GitHub Security Advisory to privately discuss and fix the issue. 8 | -------------------------------------------------------------------------------- /browser-test/fixtures/keys.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 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 | // http://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 | // The following private and public keys were copied from JWK RFC 7517: 16 | // https://tools.ietf.org/html/rfc7517 17 | export const privateKey = { 18 | kty: 'RSA', 19 | n: '0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw', 20 | e: 'AQAB', 21 | d: 'X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9M7dx5oo7GURknchnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqijwp3RTzlBaCxWp4doFk5N2o8Gy_nHNKroADIkJ46pRUohsXywbReAdYaMwFs9tv8d_cPVY3i07a3t8MN6TNwm0dSawm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBznbJSzFHK66jT8bgkuqsk0GjskDJk19Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFzme1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q', 22 | p: '83i-7IvMGXoMXCskv73TKr8637FiO7Z27zv8oj6pbWUQyLPQBQxtPVnwD20R-60eTDmD2ujnMt5PoqMrm8RfmNhVWDtjjMmCMjOpSXicFHj7XOuVIYQyqVWlWEh6dN36GVZYk93N8Bc9vY41xy8B9RzzOGVQzXvNEvn7O0nVbfs', 23 | q: '3dfOR9cuYq-0S-mkFLzgItgMEfFzB2q3hWehMuG0oCuqnb3vobLyumqjVZQO1dIrdwgTnCdpYzBcOfW5r370AFXjiWft_NGEiovonizhKpo9VVS78TzFgxkIdrecRezsZ-1kYd_s1qDbxtkDEgfAITAG9LUnADun4vIcb6yelxk', 24 | dp: 'G4sPXkc6Ya9y8oJW9_ILj4xuppu0lzi_H7VTkS8xj5SdX3coE0oimYwxIi2emTAue0UOa5dpgFGyBJ4c8tQ2VF402XRugKDTP8akYhFo5tAA77Qe_NmtuYZc3C3m3I24G2GvR5sSDxUyAN2zq8Lfn9EUms6rY3Ob8YeiKkTiBj0', 25 | dq: 's9lAH9fggBsoFR8Oac2R_E2gw282rT2kGOAhvIllETE1efrA6huUUvMfBcMpn8lqeW6vzznYY5SSQF7pMdC_agI3nG8Ibp1BUb0JUiraRNqUfLhcQb_d9GF4Dh7e74WbRsobRonujTYN1xCaP6TO61jvWrX-L18txXw494Q_cgk', 26 | qi: 'GyM_p6JrXySiz1toFgKbWV-JdI3jQ4ypu9rbMWx3rQJBfmt0FoYzgUIZEVFEcOqwemRN81zoDAaa-Bk0KWNGDjJHZDdDmFhW3AN7lI-puxk_mHZGJ11rxyR8O55XLSe3SPmRfKwZI6yU24ZxvQKFYItdldUKGzO6Ia6zTKhAVRU', 27 | alg: 'RS256', 28 | kid: '2011-04-29', 29 | }; 30 | 31 | export const publicKey = { 32 | kty: 'RSA', 33 | n: '0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw', 34 | e: 'AQAB', 35 | alg: 'RS256', 36 | kid: '2011-04-29', 37 | }; 38 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Copyright 2019 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 | // http://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 | // Karma configuration 16 | // Use `npm run browser-test` to run browser tests with Karma. 17 | const isDocker = require('is-docker')(); 18 | 19 | const webpackConfig = require('./webpack-tests.config.js'); 20 | process.env.CHROME_BIN = require('puppeteer').executablePath(); 21 | 22 | module.exports = function (config) { 23 | config.set({ 24 | // base path that will be used to resolve all patterns (eg. files, exclude) 25 | basePath: '', 26 | 27 | // frameworks to use 28 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 29 | frameworks: ['mocha'], 30 | 31 | // list of files / patterns to load in the browser 32 | files: ['./browser-test/*.ts'], 33 | 34 | // list of files / patterns to exclude 35 | exclude: [], 36 | 37 | // preprocess matching files before serving them to the browser 38 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 39 | preprocessors: { 40 | './src/*.ts': ['coverage'], 41 | './src/**/*.ts': ['coverage'], 42 | './browser-test/*.ts': ['webpack', 'sourcemap'], 43 | }, 44 | 45 | webpack: webpackConfig, 46 | 47 | // test results reporter to use 48 | // possible values: 'dots', 'progress' 49 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 50 | reporters: ['progress', 'coverage', 'remap-coverage'], 51 | 52 | coverageReporter: {type: 'in-memory'}, 53 | remapCoverageReporter: {html: './coverage'}, 54 | 55 | // web server port 56 | port: 9876, 57 | 58 | // enable / disable colors in the output (reporters and logs) 59 | colors: true, 60 | 61 | // level of logging 62 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 63 | logLevel: config.LOG_INFO, 64 | 65 | // enable / disable watching file and executing tests whenever any file changes 66 | autoWatch: false, 67 | 68 | // start these browsers 69 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 70 | browsers: ['ChromeCustom'], 71 | customLaunchers: { 72 | ChromeCustom: { 73 | base: 'ChromeHeadless', 74 | // We must disable the Chrome sandbox when running Chrome inside Docker (Chrome's sandbox needs 75 | // more permissions than Docker allows by default) 76 | flags: isDocker ? ['--no-sandbox'] : [], 77 | }, 78 | }, 79 | 80 | // Continuous Integration mode 81 | // if true, Karma captures browsers, runs the tests and exits 82 | singleRun: true, 83 | 84 | // Concurrency level 85 | // how many browser should be started simultaneous 86 | concurrency: Infinity, 87 | 88 | // set correct MIME type when serving .ts files (already compiled to JavaScript): 89 | mime: { 90 | 'text/javascript': ['ts'], 91 | }, 92 | }); 93 | }; 94 | -------------------------------------------------------------------------------- /linkinator.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "recurse": true, 3 | "skip": [ 4 | "https://codecov.io/gh/googleapis/", 5 | "www.googleapis.com", 6 | "img.shields.io", 7 | "http://169.254.169.254/latest/api/token%22", 8 | "https://github.com/googleapis/google-auth-library-nodejs/blob/" 9 | ], 10 | "silent": true, 11 | "retry": true, 12 | "retryErrors": true, 13 | "retryErrorsCount": 3, 14 | "retryErrorsJitter": 5 15 | } 16 | -------------------------------------------------------------------------------- /owlbot.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 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 | # http://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 | """This script is used to synthesize generated parts of this library.""" 15 | 16 | import synthtool.languages.node as node 17 | import logging 18 | 19 | logging.basicConfig(level=logging.DEBUG) 20 | 21 | # List of excludes for the enhanced library 22 | node.owlbot_main( 23 | templates_excludes=[ 24 | ".github/ISSUE_TEMPLATE/bug_report.yml" 25 | ], 26 | ) 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "google-auth-library", 3 | "version": "9.15.1", 4 | "author": "Google Inc.", 5 | "description": "Google APIs Authentication Client Library for Node.js", 6 | "engines": { 7 | "node": ">=18" 8 | }, 9 | "main": "./build/src/index.js", 10 | "types": "./build/src/index.d.ts", 11 | "repository": "googleapis/google-auth-library-nodejs.git", 12 | "keywords": [ 13 | "google", 14 | "api", 15 | "google apis", 16 | "client", 17 | "client library" 18 | ], 19 | "dependencies": { 20 | "base64-js": "^1.3.0", 21 | "ecdsa-sig-formatter": "^1.0.11", 22 | "gaxios": "^7.0.0-rc.4", 23 | "gcp-metadata": "^7.0.0-rc.1", 24 | "google-logging-utils": "^1.0.0", 25 | "gtoken": "^8.0.0-rc.1", 26 | "jws": "^4.0.0" 27 | }, 28 | "devDependencies": { 29 | "@types/base64-js": "^1.2.5", 30 | "@types/jws": "^3.1.0", 31 | "@types/mocha": "^10.0.10", 32 | "@types/mv": "^2.1.0", 33 | "@types/ncp": "^2.0.1", 34 | "@types/node": "^22.0.0", 35 | "@types/sinon": "^17.0.0", 36 | "assert-rejects": "^1.0.0", 37 | "c8": "^10.0.0", 38 | "codecov": "^3.0.2", 39 | "gts": "^6.0.0", 40 | "is-docker": "^3.0.0", 41 | "jsdoc": "^4.0.0", 42 | "jsdoc-fresh": "^4.0.0", 43 | "jsdoc-region-tag": "^3.0.0", 44 | "karma": "^6.0.0", 45 | "karma-chrome-launcher": "^3.0.0", 46 | "karma-coverage": "^2.0.0", 47 | "karma-firefox-launcher": "^2.0.0", 48 | "karma-mocha": "^2.0.0", 49 | "karma-sourcemap-loader": "^0.4.0", 50 | "karma-webpack": "^5.0.1", 51 | "keypair": "^1.0.4", 52 | "linkinator": "^6.1.2", 53 | "mocha": "^11.1.0", 54 | "mv": "^2.1.1", 55 | "ncp": "^2.0.0", 56 | "nock": "^14.0.1", 57 | "null-loader": "^4.0.0", 58 | "puppeteer": "^24.0.0", 59 | "sinon": "^18.0.1", 60 | "ts-loader": "^8.0.0", 61 | "typescript": "^5.1.6", 62 | "webpack": "^5.21.2", 63 | "webpack-cli": "^4.0.0" 64 | }, 65 | "files": [ 66 | "build/src", 67 | "!build/src/**/*.map" 68 | ], 69 | "scripts": { 70 | "test": "c8 mocha build/test", 71 | "clean": "gts clean", 72 | "prepare": "npm run compile", 73 | "lint": "gts check", 74 | "compile": "tsc -p .", 75 | "fix": "gts fix", 76 | "pretest": "npm run compile -- --sourceMap", 77 | "docs": "jsdoc -c .jsdoc.js", 78 | "samples-setup": "cd samples/ && npm link ../ && npm run setup && cd ../", 79 | "samples-test": "cd samples/ && npm link ../ && npm test && cd ../", 80 | "system-test": "mocha build/system-test --timeout 60000", 81 | "presystem-test": "npm run compile -- --sourceMap", 82 | "webpack": "webpack", 83 | "browser-test": "karma start", 84 | "docs-test": "linkinator docs", 85 | "predocs-test": "npm run docs", 86 | "prelint": "cd samples; npm link ../; npm install" 87 | }, 88 | "license": "Apache-2.0" 89 | } 90 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base", 4 | "docker:disable", 5 | ":disableDependencyDashboard" 6 | ], 7 | "constraintsFiltering": "strict", 8 | "pinVersions": false, 9 | "rebaseStalePrs": true, 10 | "schedule": [ 11 | "after 9am and before 3pm" 12 | ], 13 | "gitAuthor": null, 14 | "packageRules": [ 15 | { 16 | "extends": "packages:linters", 17 | "groupName": "linters" 18 | } 19 | ], 20 | "ignoreDeps": ["typescript"] 21 | } 22 | -------------------------------------------------------------------------------- /samples/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | --- 2 | rules: 3 | no-console: off 4 | node/no-missing-require: off 5 | node/no-unpublished-require: off 6 | -------------------------------------------------------------------------------- /samples/adc.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018, Google, LLC. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | 'use strict'; 15 | 16 | /** 17 | * Import the GoogleAuth library, and create a new GoogleAuth client. 18 | */ 19 | const {GoogleAuth} = require('google-auth-library'); 20 | 21 | /** 22 | * Acquire a client, and make a request to an API that's enabled by default. 23 | */ 24 | async function main() { 25 | const auth = new GoogleAuth({ 26 | scopes: 'https://www.googleapis.com/auth/cloud-platform', 27 | }); 28 | const client = await auth.getClient(); 29 | const projectId = await auth.getProjectId(); 30 | const url = `https://dns.googleapis.com/dns/v1/projects/${projectId}`; 31 | const res = await client.request({url}); 32 | console.log('DNS Info:'); 33 | console.log(res.data); 34 | } 35 | 36 | main().catch(console.error); 37 | -------------------------------------------------------------------------------- /samples/authenticateAPIKey.js: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | // http://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 | function main() { 16 | // [START apikeys_authenticate_api_key] 17 | 18 | const { 19 | v1: {LanguageServiceClient}, 20 | } = require('@google-cloud/language'); 21 | 22 | /** 23 | * Authenticates with an API key for Google Language service. 24 | * 25 | * @param {string} apiKey An API Key to use 26 | */ 27 | async function authenticateWithAPIKey(apiKey) { 28 | const language = new LanguageServiceClient({apiKey}); 29 | 30 | // Alternatively: 31 | // const {GoogleAuth} = require('google-auth-library'); 32 | // const auth = new GoogleAuth({apiKey}); 33 | // const language = new LanguageServiceClient({auth}); 34 | 35 | const text = 'Hello, world!'; 36 | 37 | const [response] = await language.analyzeSentiment({ 38 | document: { 39 | content: text, 40 | type: 'PLAIN_TEXT', 41 | }, 42 | }); 43 | 44 | console.log(`Text: ${text}`); 45 | console.log( 46 | `Sentiment: ${response.documentSentiment.score}, ${response.documentSentiment.magnitude}`, 47 | ); 48 | console.log('Successfully authenticated using the API key'); 49 | } 50 | 51 | authenticateWithAPIKey(); 52 | // [END apikeys_authenticate_api_key] 53 | } 54 | 55 | process.on('unhandledRejection', err => { 56 | console.error(err.message); 57 | process.exitCode = 1; 58 | }); 59 | 60 | main(...process.argv.slice(2)); 61 | -------------------------------------------------------------------------------- /samples/authenticateExplicit.js: -------------------------------------------------------------------------------- 1 | // Copyright 2022 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 | // http://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 | /** 16 | * Lists storage buckets by authenticating with ADC. 17 | */ 18 | function main() { 19 | // [START auth_cloud_explicit_adc] 20 | /** 21 | * TODO(developer): 22 | * 1. Set up ADC as described in https://cloud.google.com/docs/authentication/external/set-up-adc 23 | * 2. Make sure you have the necessary permission to list storage buckets "storage.buckets.list" 24 | */ 25 | 26 | const {GoogleAuth} = require('google-auth-library'); 27 | const {Storage} = require('@google-cloud/storage'); 28 | 29 | async function authenticateExplicit() { 30 | const googleAuth = new GoogleAuth({ 31 | scopes: 'https://www.googleapis.com/auth/cloud-platform', 32 | }); 33 | 34 | // Construct the Google credentials object which obtains the default configuration from your 35 | // working environment. 36 | // googleAuth.getApplicationDefault() will give you ComputeEngineCredentials 37 | // if you are on a GCE (or other metadata server supported environments). 38 | const {credential, projectId} = await googleAuth.getApplicationDefault(); 39 | // If you are authenticating to a Cloud API, you can let the library include the default scope, 40 | // https://www.googleapis.com/auth/cloud-platform, because IAM is used to provide fine-grained 41 | // permissions for Cloud. 42 | // If you need to provide a scope, specify it as follows: 43 | // const googleAuth = new GoogleAuth({ scopes: scope }); 44 | // For more information on scopes to use, 45 | // see: https://developers.google.com/identity/protocols/oauth2/scopes 46 | 47 | const storageOptions = { 48 | projectId, 49 | authClient: credential, 50 | }; 51 | 52 | // Construct the Storage client. 53 | const storage = new Storage(storageOptions); 54 | const [buckets] = await storage.getBuckets(); 55 | console.log('Buckets:'); 56 | 57 | for (const bucket of buckets) { 58 | console.log(`- ${bucket.name}`); 59 | } 60 | 61 | console.log('Listed all storage buckets.'); 62 | } 63 | 64 | authenticateExplicit(); 65 | // [END auth_cloud_explicit_adc] 66 | } 67 | 68 | process.on('unhandledRejection', err => { 69 | console.error(err.message); 70 | process.exitCode = 1; 71 | }); 72 | 73 | main(...process.argv.slice(2)); 74 | -------------------------------------------------------------------------------- /samples/authenticateImplicitWithAdc.js: -------------------------------------------------------------------------------- 1 | // Copyright 2022 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 | // http://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 | /** 16 | * Shows credentials auto-detections in the intercation with GCP libraries 17 | * 18 | * @param {string} projectId - Project ID or project number of the Cloud project you want to use. 19 | */ 20 | function main(projectId) { 21 | // [START auth_cloud_implicit_adc] 22 | /** 23 | * TODO(developer): 24 | * 1. Uncomment and replace these variables before running the sample. 25 | * 2. Set up ADC as described in https://cloud.google.com/docs/authentication/external/set-up-adc 26 | * 3. Make sure you have the necessary permission to list storage buckets "storage.buckets.list" 27 | * (https://cloud.google.com/storage/docs/access-control/iam-permissions#bucket_permissions) 28 | */ 29 | // const projectId = 'YOUR_PROJECT_ID'; 30 | 31 | const {Storage} = require('@google-cloud/storage'); 32 | 33 | async function authenticateImplicitWithAdc() { 34 | // This snippet demonstrates how to list buckets. 35 | // NOTE: Replace the client created below with the client required for your application. 36 | // Note that the credentials are not specified when constructing the client. 37 | // The client library finds your credentials using ADC. 38 | const storage = new Storage({ 39 | projectId, 40 | }); 41 | const [buckets] = await storage.getBuckets(); 42 | console.log('Buckets:'); 43 | 44 | for (const bucket of buckets) { 45 | console.log(`- ${bucket.name}`); 46 | } 47 | 48 | console.log('Listed all storage buckets.'); 49 | } 50 | 51 | authenticateImplicitWithAdc(); 52 | // [END auth_cloud_implicit_adc] 53 | } 54 | 55 | process.on('unhandledRejection', err => { 56 | console.error(err.message); 57 | process.exitCode = 1; 58 | }); 59 | 60 | main(...process.argv.slice(2)); 61 | -------------------------------------------------------------------------------- /samples/compute.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018, Google, LLC. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | 'use strict'; 15 | 16 | const {auth, Compute} = require('google-auth-library'); 17 | 18 | /** 19 | * This example directly instantiates a Compute client to acquire credentials. 20 | * Generally, you wouldn't directly create this class, rather call the 21 | * `auth.getClient()` method to automatically obtain credentials. 22 | */ 23 | async function main() { 24 | const client = new Compute({ 25 | // Specifying the serviceAccountEmail is optional. It will use the default 26 | // service account if one is not defined. 27 | serviceAccountEmail: 'some-service-account@example.com', 28 | }); 29 | const projectId = await auth.getProjectId(); 30 | const url = `https://dns.googleapis.com/dns/v1/projects/${projectId}`; 31 | const res = await client.request({url}); 32 | console.log(res.data); 33 | } 34 | 35 | main().catch(console.error); 36 | -------------------------------------------------------------------------------- /samples/credentials.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018, Google, LLC. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | 'use strict'; 15 | 16 | /** 17 | * Import the GoogleAuth library, and create a new GoogleAuth client. 18 | */ 19 | const {GoogleAuth} = require('google-auth-library'); 20 | 21 | /** 22 | * This sample demonstrates passing a `credentials` object directly into the 23 | * `getClient` method. This is useful if you're storing the fields required 24 | * in environment variables. The original `client_email` and `private_key` 25 | * values are obtained from a service account credential file. 26 | */ 27 | async function main() { 28 | const clientEmail = process.env.CLIENT_EMAIL; 29 | const privateKey = process.env.PRIVATE_KEY; 30 | if (!clientEmail || !privateKey) { 31 | throw new Error(` 32 | The CLIENT_EMAIL and PRIVATE_KEY environment variables are required for 33 | this sample. 34 | `); 35 | } 36 | const auth = new GoogleAuth({ 37 | credentials: { 38 | client_email: clientEmail, 39 | private_key: privateKey, 40 | }, 41 | scopes: 'https://www.googleapis.com/auth/cloud-platform', 42 | }); 43 | const client = await auth.getClient(); 44 | const projectId = await auth.getProjectId(); 45 | const url = `https://dns.googleapis.com/dns/v1/projects/${projectId}`; 46 | const res = await client.request({url}); 47 | console.log('DNS Info:'); 48 | console.log(res.data); 49 | } 50 | 51 | main().catch(console.error); 52 | -------------------------------------------------------------------------------- /samples/downscopedclient.js: -------------------------------------------------------------------------------- 1 | // Copyright 2021 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 | // http://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 | 'use strict'; 16 | 17 | /** 18 | * Imports the Google Auth and Google Cloud libraries. 19 | */ 20 | const { 21 | OAuth2Client, 22 | GoogleAuth, 23 | DownscopedClient, 24 | } = require('google-auth-library'); 25 | const {Storage} = require('@google-cloud/storage'); 26 | 27 | /** 28 | * The following sample demonstrates how to initialize a DownscopedClient using 29 | * a credential access boundary and a client obtained via ADC. The 30 | * DownscopedClient is used to create downscoped tokens which can be consumed 31 | * via the OAuth2Client. A refresh handler is used to obtain new downscoped 32 | * tokens seamlessly when they expire. Then the oauth2Client is used to define 33 | * a cloud storage object and call GCS APIs to access specified object and 34 | * print the contents. 35 | */ 36 | async function main() { 37 | const bucketName = process.env.BUCKET_NAME; 38 | const objectName = process.env.OBJECT_NAME; 39 | // Defines a credential access boundary that grants objectViewer access in 40 | // the specified bucket. 41 | const credentialAccessBoundary = { 42 | accessBoundary: { 43 | accessBoundaryRules: [ 44 | { 45 | availableResource: `//storage.googleapis.com/projects/_/buckets/${bucketName}`, 46 | availablePermissions: ['inRole:roles/storage.objectViewer'], 47 | availabilityCondition: { 48 | expression: 49 | "resource.name.startsWith('projects/_/buckets/" + 50 | `${bucketName}/objects/${objectName}')`, 51 | }, 52 | }, 53 | ], 54 | }, 55 | }; 56 | 57 | const googleAuth = new GoogleAuth({ 58 | scopes: 'https://www.googleapis.com/auth/cloud-platform', 59 | }); 60 | const projectId = await googleAuth.getProjectId(); 61 | // Obtain an authenticated client via ADC. 62 | const client = await googleAuth.getClient(); 63 | // Use the client to generate a DownscopedClient. 64 | const cabClient = new DownscopedClient({ 65 | authClient: client, 66 | credentialAccessBoundary, 67 | }); 68 | 69 | // OAuth 2.0 Client 70 | const authClient = new OAuth2Client(); 71 | // Define a refreshHandler that will be used to refresh the downscoped token 72 | // when it expires. 73 | authClient.refreshHandler = async () => { 74 | const refreshedAccessToken = await cabClient.getAccessToken(); 75 | return { 76 | access_token: refreshedAccessToken.token, 77 | expiry_date: refreshedAccessToken.expirationTime, 78 | }; 79 | }; 80 | 81 | const storageOptions = { 82 | projectId, 83 | authClient: new GoogleAuth({authClient}), 84 | }; 85 | 86 | const storage = new Storage(storageOptions); 87 | const downloadFile = await storage 88 | .bucket(bucketName) 89 | .file(objectName) 90 | .download(); 91 | console.log('Successfully retrieved file. Contents:'); 92 | console.log(downloadFile.toString('utf8')); 93 | } 94 | 95 | main().catch(console.error); 96 | -------------------------------------------------------------------------------- /samples/headers.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018, Google, LLC. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | 'use strict'; 15 | 16 | /** 17 | * Import the GoogleAuth library, and create a new GoogleAuth client. 18 | */ 19 | const {GoogleAuth} = require('google-auth-library'); 20 | const fetch = require('node-fetch'); 21 | 22 | /** 23 | * This example shows obtaining authenticated HTTP request headers, and using 24 | * those headers to construct your own authenticated request. This example uses 25 | * node-fetch, but you could use any HTTP client you like. 26 | */ 27 | async function main() { 28 | // create auth instance with custom scopes. 29 | const auth = new GoogleAuth({ 30 | scopes: 'https://www.googleapis.com/auth/cloud-platform', 31 | }); 32 | const projectId = await auth.getProjectId(); 33 | const url = `https://dns.googleapis.com/dns/v1/projects/${projectId}`; 34 | 35 | // obtain an authenticated client 36 | const client = await auth.getClient(); 37 | // Use the client to get authenticated request headers 38 | const headers = await client.getRequestHeaders(); 39 | console.log('Headers:'); 40 | console.log(headers); 41 | 42 | // Attach those headers to another request, and use it to call a Google API 43 | const res = await fetch(url, {headers}); 44 | const data = await res.json(); 45 | console.log('DNS Info:'); 46 | console.log(data); 47 | } 48 | 49 | main().catch(console.error); 50 | -------------------------------------------------------------------------------- /samples/idTokenFromImpersonatedCredentials.js: -------------------------------------------------------------------------------- 1 | // Copyright 2022 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 | // http://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 | /** 16 | * Uses a service account (SA1) to impersonate as another service account (SA2) and obtain id token for the impersonated account. 17 | * To obtain token for SA2, SA1 should have the "roles/iam.serviceAccountTokenCreator" permission on SA2. 18 | * 19 | * @param {string} scope - The scope that you might need to request to access Google APIs, 20 | * depending on the level of access you need. For this example, we use the cloud-wide scope 21 | * and use IAM to narrow the permissions: https://cloud.google.com/docs/authentication#authorization_for_services. 22 | * For more information, see: https://developers.google.com/identity/protocols/oauth2/scopes. 23 | * @param {string} targetAudience - The service name for which the id token is requested. Service name refers to the 24 | * logical identifier of an API service, such as "http://www.example.com". 25 | * @param {string} impersonatedServiceAccount - The name of the privilege-bearing service account for whom 26 | * the credential is created. 27 | */ 28 | function main(scope, targetAudience, impersonatedServiceAccount) { 29 | // [START auth_cloud_idtoken_impersonated_credentials] 30 | /** 31 | * TODO(developer): 32 | * 1. Uncomment and replace these variables before running the sample. 33 | */ 34 | // const scope = 'https://www.googleapis.com/auth/cloud-platform'; 35 | // const targetAudience = 'http://www.example.com'; 36 | // const impersonatedServiceAccount = 'name@project.service.gserviceaccount.com'; 37 | 38 | const {GoogleAuth, Impersonated} = require('google-auth-library'); 39 | 40 | async function getIdTokenFromImpersonatedCredentials() { 41 | const googleAuth = new GoogleAuth(); 42 | 43 | // Construct the GoogleCredentials object which obtains the default configuration from your 44 | // working environment. 45 | const {credential} = await googleAuth.getApplicationDefault(); 46 | 47 | // delegates: The chained list of delegates required to grant the final accessToken. 48 | // For more information, see: 49 | // https://cloud.google.com/iam/docs/create-short-lived-credentials-direct#sa-credentials-permissions 50 | // Delegate is NOT USED here. 51 | const delegates = []; 52 | 53 | // Create the impersonated credential. 54 | const impersonatedCredentials = new Impersonated({ 55 | sourceClient: credential, 56 | delegates, 57 | targetPrincipal: impersonatedServiceAccount, 58 | targetScopes: [scope], 59 | lifetime: 300, 60 | }); 61 | 62 | // Get the ID token. 63 | // Once you've obtained the ID token, you can use it to make an authenticated call 64 | // to the target audience. 65 | await impersonatedCredentials.fetchIdToken(targetAudience, { 66 | includeEmail: true, 67 | }); 68 | console.log('Generated ID token.'); 69 | } 70 | 71 | getIdTokenFromImpersonatedCredentials(); 72 | // [END auth_cloud_idtoken_impersonated_credentials] 73 | } 74 | 75 | process.on('unhandledRejection', err => { 76 | console.error(err.message); 77 | process.exitCode = 1; 78 | }); 79 | 80 | main(...process.argv.slice(2)); 81 | -------------------------------------------------------------------------------- /samples/idTokenFromMetadataServer.js: -------------------------------------------------------------------------------- 1 | // Copyright 2022 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 | // http://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 | /** 16 | * Uses the Google Cloud metadata server environment to create an identity token 17 | * and add it to the HTTP request as part of an authorization header. 18 | * 19 | * @param {string} targetAudience - The url or target audience to obtain the ID token for. 20 | */ 21 | function main(targetAudience) { 22 | // [START auth_cloud_idtoken_metadata_server] 23 | /** 24 | * TODO(developer): 25 | * 1. Uncomment and replace these variables before running the sample. 26 | */ 27 | // const targetAudience = 'http://www.example.com'; 28 | 29 | const {GoogleAuth} = require('google-auth-library'); 30 | 31 | async function getIdTokenFromMetadataServer() { 32 | const googleAuth = new GoogleAuth(); 33 | 34 | const client = await googleAuth.getIdTokenClient(targetAudience); 35 | 36 | // Get the ID token. 37 | // Once you've obtained the ID token, you can use it to make an authenticated call 38 | // to the target audience. 39 | await client.idTokenProvider.fetchIdToken(targetAudience); 40 | console.log('Generated ID token.'); 41 | } 42 | 43 | getIdTokenFromMetadataServer(); 44 | // [END auth_cloud_idtoken_metadata_server] 45 | } 46 | 47 | process.on('unhandledRejection', err => { 48 | console.error(err.message); 49 | process.exitCode = 1; 50 | }); 51 | 52 | main(...process.argv.slice(2)); 53 | -------------------------------------------------------------------------------- /samples/idTokenFromServiceAccount.js: -------------------------------------------------------------------------------- 1 | // Copyright 2022 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 | // http://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 | /** 16 | * Obtains the id token by providing the target audience using service account credentials. 17 | * 18 | * @param {string} jsonCredentialsPath - Path to the service account json credential file. 19 | * and use IAM to narrow the permissions: https://cloud.google.com/docs/authentication#authorization_for_services 20 | * @param {string} targetAudience - The url or target audience to obtain the ID token for. 21 | */ 22 | function main(targetAudience, jsonCredentialsPath) { 23 | // [START auth_cloud_idtoken_service_account] 24 | /** 25 | * TODO(developer): 26 | * 1. Uncomment and replace these variables before running the sample. 27 | */ 28 | // const jsonCredentialsPath = '/path/example'; 29 | // const targetAudience = 'http://www.example.com'; 30 | 31 | // Using service account keys introduces risk; they are long-lived, and can be used by anyone 32 | // that obtains the key. Proper rotation and storage reduce this risk but do not eliminate it. 33 | // For these reasons, you should consider an alternative approach that 34 | // does not use a service account key. Several alternatives to service account keys 35 | // are described here: 36 | // https://cloud.google.com/docs/authentication/external/set-up-adc 37 | 38 | const {GoogleAuth} = require('google-auth-library'); 39 | const fs = require('fs'); 40 | const credentials = JSON.parse(fs.readFileSync(jsonCredentialsPath, 'utf8')); 41 | 42 | async function getIdTokenFromServiceAccount() { 43 | const auth = new GoogleAuth({credentials}); 44 | 45 | // Get an ID token client. 46 | // The client can be used to make authenticated requests or you can use the 47 | // provider to fetch an id token. 48 | const client = await auth.getIdTokenClient(targetAudience); 49 | await client.idTokenProvider.fetchIdToken(targetAudience); 50 | 51 | console.log('Generated ID token.'); 52 | } 53 | 54 | getIdTokenFromServiceAccount(); 55 | // [END auth_cloud_idtoken_service_account] 56 | } 57 | 58 | process.on('unhandledRejection', err => { 59 | console.error(err.message); 60 | process.exitCode = 1; 61 | }); 62 | 63 | main(...process.argv.slice(2)); 64 | -------------------------------------------------------------------------------- /samples/idtokens-iap.js: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Google LLC 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // sample-metadata: 15 | // title: ID Tokens for Identity-Aware Proxy (IAP) 16 | // description: Requests an IAP-protected resource with an ID Token. 17 | // usage: node idtokens-iap.js 18 | 19 | 'use strict'; 20 | 21 | function main( 22 | url = 'https://some.iap.url', 23 | targetAudience = 'IAP_CLIENT_ID.apps.googleusercontent.com', 24 | ) { 25 | // [START iap_make_request] 26 | /** 27 | * TODO(developer): Uncomment these variables before running the sample. 28 | */ 29 | // const url = 'https://some.iap.url'; 30 | // const targetAudience = 'IAP_CLIENT_ID.apps.googleusercontent.com'; 31 | 32 | const {GoogleAuth} = require('google-auth-library'); 33 | const auth = new GoogleAuth(); 34 | 35 | async function request() { 36 | console.info(`request IAP ${url} with target audience ${targetAudience}`); 37 | const client = await auth.getIdTokenClient(targetAudience); 38 | const res = await client.request({url}); 39 | console.info(res.data); 40 | } 41 | 42 | request().catch(err => { 43 | console.error(err.message); 44 | process.exitCode = 1; 45 | }); 46 | // [END iap_make_request] 47 | } 48 | 49 | const args = process.argv.slice(2); 50 | main(...args); 51 | -------------------------------------------------------------------------------- /samples/idtokens-serverless.js: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Google LLC 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // sample-metadata: 15 | // title: ID Tokens for Serverless 16 | // description: Requests a Cloud Run or Cloud Functions URL with an ID Token. 17 | // usage: node idtokens-serverless.js [] 18 | 19 | 'use strict'; 20 | 21 | function main( 22 | url = 'https://service-1234-uc.a.run.app', 23 | targetAudience = null, 24 | ) { 25 | if (!targetAudience) { 26 | // Use the target service's hostname as the target audience for requests. 27 | // (For example: https://my-cloud-run-service.run.app) 28 | const {URL} = require('url'); 29 | targetAudience = new URL(url).origin; 30 | } 31 | // [START cloudrun_service_to_service_auth] 32 | // [START functions_bearer_token] 33 | /** 34 | * TODO(developer): Uncomment these variables before running the sample. 35 | */ 36 | // [END functions_bearer_token] 37 | // [END cloudrun_service_to_service_auth] 38 | 39 | // [START cloudrun_service_to_service_auth] 40 | // Example: https://my-cloud-run-service.run.app/books/delete/12345 41 | // const url = 'https://TARGET_HOSTNAME/TARGET_URL'; 42 | 43 | // Example (Cloud Run): https://my-cloud-run-service.run.app/ 44 | // const targetAudience = 'https://TARGET_AUDIENCE/'; 45 | // [END cloudrun_service_to_service_auth] 46 | 47 | // [START functions_bearer_token] 48 | 49 | // Cloud Functions uses your function's url as the `targetAudience` value 50 | // const targetAudience = 'https://project-region-projectid.cloudfunctions.net/myFunction'; 51 | // For Cloud Functions, endpoint (`url`) and `targetAudience` should be equal 52 | // const url = targetAudience; 53 | 54 | // [END functions_bearer_token] 55 | 56 | // [START functions_bearer_token] 57 | // [START cloudrun_service_to_service_auth] 58 | 59 | const {GoogleAuth} = require('google-auth-library'); 60 | const auth = new GoogleAuth(); 61 | 62 | async function request() { 63 | console.info(`request ${url} with target audience ${targetAudience}`); 64 | const client = await auth.getIdTokenClient(targetAudience); 65 | 66 | // Alternatively, one can use `client.idTokenProvider.fetchIdToken` 67 | // to return the ID Token. 68 | const res = await client.request({url}); 69 | console.info(res.data); 70 | } 71 | 72 | request().catch(err => { 73 | console.error(err.message); 74 | process.exitCode = 1; 75 | }); 76 | // [END functions_bearer_token] 77 | // [END cloudrun_service_to_service_auth] 78 | } 79 | 80 | const args = process.argv.slice(2); 81 | main(...args); 82 | -------------------------------------------------------------------------------- /samples/jwt.js: -------------------------------------------------------------------------------- 1 | // Copyright 2017 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 | // http://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 | 'use strict'; 16 | 17 | /** 18 | * The JWT authorization is ideal for performing server-to-server 19 | * communication without asking for user consent. Usually, you aren't 20 | * going to directly instantiate a JWT instance. Typically, this is acquired 21 | * by using the `auth.getClient()` method. 22 | * 23 | * Suggested reading for Admin SDK users using service accounts: 24 | * https://developers.google.com/admin-sdk/directory/v1/guides/delegation 25 | **/ 26 | 27 | const {JWT} = require('google-auth-library'); 28 | const fs = require('fs'); 29 | 30 | async function main( 31 | // Full path to the service account credential 32 | keyFile = process.env.GOOGLE_APPLICATION_CREDENTIALS, 33 | ) { 34 | const keys = JSON.parse(fs.readFileSync(keyFile, 'utf8')); 35 | const client = new JWT({ 36 | email: keys.client_email, 37 | key: keys.private_key, 38 | scopes: ['https://www.googleapis.com/auth/cloud-platform'], 39 | }); 40 | const url = `https://dns.googleapis.com/dns/v1/projects/${keys.project_id}`; 41 | const res = await client.request({url}); 42 | console.log('DNS Info:'); 43 | console.log(res.data); 44 | 45 | // After acquiring an access_token, you may want to check on the audience, expiration, 46 | // or original scopes requested. You can do that with the `getTokenInfo` method. 47 | const tokenInfo = await client.getTokenInfo(client.credentials.access_token); 48 | console.log(tokenInfo); 49 | } 50 | 51 | const args = process.argv.slice(2); 52 | main(...args).catch(console.error); 53 | -------------------------------------------------------------------------------- /samples/keepalive.js: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Google LLC 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | 'use strict'; 15 | 16 | /** 17 | * This is an example of using the GoogleAuth object to acquire 18 | * and use a client via Application Default Credentials. It also uses 19 | * a single httpAgent with keepAlive set, so a single connection can be 20 | * used across multiple requests. 21 | */ 22 | 23 | /** 24 | * Import the GoogleAuth library, and create a new GoogleAuth client. 25 | */ 26 | const {GoogleAuth} = require('google-auth-library'); 27 | const https = require('https'); 28 | 29 | /** 30 | * Acquire a client, and make a request to an API that's enabled by default. 31 | */ 32 | async function main() { 33 | // create a new agent with keepAlive enabled. 34 | const agent = new https.Agent({keepAlive: true}); 35 | 36 | const auth = new GoogleAuth({ 37 | scopes: 'https://www.googleapis.com/auth/cloud-platform', 38 | clientOptions: { 39 | transporterOptions: { 40 | agent, 41 | }, 42 | }, 43 | }); 44 | const client = await auth.getClient(); 45 | const projectId = await auth.getProjectId(); 46 | const url = `https://dns.googleapis.com/dns/v1/projects/${projectId}`; 47 | 48 | // the agent uses the provided agent. 49 | const res = await client.request({url}); 50 | console.log(res.data); 51 | 52 | // Can also use another agent per-request. 53 | const res2 = await client.request({url, agent}); 54 | console.log(res2.data); 55 | } 56 | 57 | main().catch(console.error); 58 | -------------------------------------------------------------------------------- /samples/keyfile.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 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 | // http://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 | 'use strict'; 16 | 17 | /** 18 | * Import the GoogleAuth library, and create a new GoogleAuth client. 19 | */ 20 | const {GoogleAuth} = require('google-auth-library'); 21 | 22 | /** 23 | * Acquire a client, and make a request to an API that's enabled by default. 24 | */ 25 | async function main( 26 | // Full path to the service account credential 27 | keyFile = process.env.GOOGLE_APPLICATION_CREDENTIALS, 28 | ) { 29 | const auth = new GoogleAuth({ 30 | keyFile: keyFile, 31 | scopes: 'https://www.googleapis.com/auth/cloud-platform', 32 | }); 33 | const client = await auth.getClient(); 34 | const projectId = await auth.getProjectId(); 35 | const url = `https://dns.googleapis.com/dns/v1/projects/${projectId}`; 36 | const res = await client.request({url}); 37 | console.log('DNS Info:'); 38 | console.log(res.data); 39 | } 40 | 41 | const args = process.argv.slice(2); 42 | main(...args).catch(console.error); 43 | -------------------------------------------------------------------------------- /samples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "google-auth-library-samples", 3 | "description": "A set of samples for the google-auth-library npm module.", 4 | "files": [ 5 | "*.js" 6 | ], 7 | "scripts": { 8 | "setup": "node scripts/*.js", 9 | "test": "mocha --timeout 60000" 10 | }, 11 | "engines": { 12 | "node": ">=18" 13 | }, 14 | "license": "Apache-2.0", 15 | "dependencies": { 16 | "@google-cloud/language": "^7.0.0", 17 | "@google-cloud/storage": "^7.0.0", 18 | "@googleapis/iam": "^27.0.0", 19 | "google-auth-library": "^9.15.1", 20 | "node-fetch": "^2.3.0", 21 | "open": "^9.0.0", 22 | "server-destroy": "^1.0.1" 23 | }, 24 | "devDependencies": { 25 | "chai": "^4.2.0", 26 | "mocha": "^8.0.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /samples/puppeteer/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | --- 2 | rules: 3 | no-console: off 4 | node/no-unpublished-require: off 5 | -------------------------------------------------------------------------------- /samples/puppeteer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "puppeteer-example", 3 | "private": true, 4 | "description": "An example of using puppeteer to orchestrate a Google sign in flow.", 5 | "main": "oauth2-test.js", 6 | "engines": { 7 | "node": ">=18" 8 | }, 9 | "scripts": { 10 | "start": "node oauth2-test.js" 11 | }, 12 | "license": "Apache-2.0", 13 | "dependencies": { 14 | "google-auth-library": "^9.0.0", 15 | "puppeteer": "^24.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /samples/scripts/downscoping-with-cab-setup.js: -------------------------------------------------------------------------------- 1 | // Copyright 2021 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 | // http://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 | // This script is used to generate the project configurations needed to 16 | // end-to-end test Downscoping with Credential Access Boundaries in the Auth 17 | // library. 18 | 19 | // In order to run this script, the GOOGLE_APPLICATION_CREDENTIALS environment 20 | // variable needs to be set to point to a service account key file. 21 | // 22 | // GCP project changes: 23 | // -------------------- 24 | // The following IAM role need to be set on the service account: 25 | // 1. Storage Admin (needed to create bucket and object). 26 | 27 | // This script needs to be run once. It will do the following: 28 | // 1. Generates a random ID for bucketName and objectName. 29 | // 2. Creates a GCS bucket in the specified project defined in GOOGLE_APPLICATION_CREDENTIALS. 30 | // 3. Creates two object in the bucket created in the last step. 31 | // 4. Prints out the identifiers (bucketName, first objectName, second objectName) 32 | // to be used in the accompanying tests. 33 | // 34 | // The same service account used for this setup script should be used for 35 | // the integration tests. 36 | // 37 | // It is safe to run the setup script again. A new bucket is created along with 38 | // new objects. If run multiple times, it is advisable to delete 39 | // unused buckets. 40 | 41 | const {Storage} = require('@google-cloud/storage'); 42 | const fs = require('fs'); 43 | const {promisify} = require('util'); 44 | 45 | const readFile = promisify(fs.readFile); 46 | const CONTENT = 'first'; 47 | 48 | /** 49 | * Generates a random string of the specified length, optionally using the 50 | * specified alphabet. 51 | * 52 | * @param {number} length The length of the string to generate. 53 | * @return {string} A random string of the provided length. 54 | */ 55 | function generateRandomString(length) { 56 | const chars = []; 57 | const allowedChars = 'abcdefghijklmnopqrstuvwxyz0123456789'; 58 | for (let i = 0; i < length; i++) { 59 | chars.push( 60 | allowedChars.charAt(Math.floor(Math.random() * allowedChars.length)), 61 | ); 62 | } 63 | return chars.join(''); 64 | } 65 | 66 | async function main() { 67 | const keyFile = process.env.GOOGLE_APPLICATION_CREDENTIALS; 68 | if (!process.env.GOOGLE_APPLICATION_CREDENTIALS) { 69 | throw new Error('No GOOGLE_APPLICATION_CREDENTIALS env var is available'); 70 | } 71 | const keys = JSON.parse(await readFile(keyFile, 'utf8')); 72 | 73 | const suffix = generateRandomString(10); 74 | const bucketName = `cab-int-bucket-${suffix}`; 75 | const objectName = `cab-first-${suffix}.txt`; 76 | const projectId = keys.project_id; 77 | const storage = new Storage(projectId); 78 | 79 | try { 80 | await storage.createBucket(bucketName); 81 | await storage.bucket(bucketName).file(objectName).save(CONTENT); 82 | } catch (error) { 83 | console.log(error.message); 84 | } 85 | 86 | console.log('bucket name: ' + bucketName); 87 | console.log('object name: ' + objectName); 88 | } 89 | 90 | main().catch(console.error); 91 | -------------------------------------------------------------------------------- /samples/signBlob.js: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Google LLC 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | 'use strict'; 15 | 16 | const {auth} = require('google-auth-library'); 17 | 18 | /** 19 | * Use the iamcredentials API to sign a blob of data. 20 | */ 21 | async function main() { 22 | const signedData = await auth.sign('some data'); 23 | console.log(signedData); 24 | } 25 | 26 | main().catch(e => { 27 | console.error(e); 28 | throw e; 29 | }); 30 | -------------------------------------------------------------------------------- /samples/signBlobImpersonated.js: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Google LLC 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | 'use strict'; 15 | 16 | const {GoogleAuth, Impersonated} = require('google-auth-library'); 17 | 18 | /** 19 | * Use the iamcredentials API to sign a blob of data. 20 | */ 21 | async function main() { 22 | // get source credentials 23 | const auth = new GoogleAuth(); 24 | const client = await auth.getClient(); 25 | 26 | // First impersonate 27 | const scopes = ['https://www.googleapis.com/auth/cloud-platform']; 28 | 29 | const targetPrincipal = 'target@project.iam.gserviceaccount.com'; 30 | const targetClient = new Impersonated({ 31 | sourceClient: client, 32 | targetPrincipal: targetPrincipal, 33 | lifetime: 30, 34 | delegates: [], 35 | targetScopes: [scopes], 36 | }); 37 | 38 | const signedData = await targetClient.sign('some data'); 39 | console.log(signedData.signedBlob); 40 | 41 | // or use the client to create a GCS signedURL 42 | // const { Storage } = require('@google-cloud/storage'); 43 | 44 | // const projectId = 'yourProjectID' 45 | // const bucketName = 'yourBucket' 46 | // const objectName = 'yourObject' 47 | 48 | // // use the impersonated client to access gcs 49 | // const storageOptions = { 50 | // projectId, 51 | // authClient: targetClient, 52 | // }; 53 | 54 | // const storage = new Storage(storageOptions); 55 | 56 | // const signOptions = { 57 | // version: 'v4', 58 | // action: 'read', 59 | // expires: Date.now() + 15 * 60 * 1000, // 15 minutes 60 | // }; 61 | 62 | // const signedURL = await storage 63 | // .bucket(bucketName) 64 | // .file(objectName) 65 | // .getSignedUrl(signOptions); 66 | 67 | // console.log(signedURL); 68 | } 69 | 70 | main().catch(e => { 71 | console.error(e); 72 | throw e; 73 | }); 74 | -------------------------------------------------------------------------------- /samples/test/auth.test.js: -------------------------------------------------------------------------------- 1 | // Copyright 2022 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 | // http://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 | 'use strict'; 16 | 17 | const assert = require('assert'); 18 | const cp = require('child_process'); 19 | const {auth} = require('google-auth-library'); 20 | const {describe, it} = require('mocha'); 21 | const fs = require('fs'); 22 | 23 | const TARGET_AUDIENCE = 'iap.googleapis.com'; 24 | const ZONE = 'us-central1-a'; 25 | 26 | const keyFile = process.env.GOOGLE_APPLICATION_CREDENTIALS; 27 | 28 | const execSync = (command, opts) => { 29 | return cp.execSync(command, Object.assign({encoding: 'utf-8'}, opts)); 30 | }; 31 | 32 | describe('auth samples', () => { 33 | it('should authenticate explicitly', async () => { 34 | const output = execSync('node authenticateExplicit'); 35 | 36 | assert.match(output, /Listed all storage buckets./); 37 | }); 38 | 39 | it('should authenticate implicitly with adc', async () => { 40 | const projectId = await auth.getProjectId(); 41 | 42 | const output = execSync( 43 | `node authenticateImplicitWithAdc ${projectId} ${ZONE}`, 44 | ); 45 | 46 | assert.match(output, /Listed all storage buckets./); 47 | }); 48 | 49 | it('should get id token from metadata server', async () => { 50 | const output = execSync( 51 | 'node idTokenFromMetadataServer https://www.google.com', 52 | ); 53 | 54 | assert.match(output, /Generated ID token./); 55 | }); 56 | 57 | it('should get id token from service account', async () => { 58 | const output = execSync( 59 | `node idTokenFromServiceAccount ${TARGET_AUDIENCE} ${keyFile}`, 60 | ); 61 | 62 | assert.match(output, /Generated ID token./); 63 | }); 64 | 65 | it('should verify google id token', async () => { 66 | const jsonConfig = JSON.parse(fs.readFileSync(keyFile, 'utf8')); 67 | const client = auth.fromJSON(jsonConfig); 68 | 69 | const idToken = await client.fetchIdToken(TARGET_AUDIENCE); 70 | 71 | const output = execSync( 72 | `node verifyGoogleIdToken ${idToken} ${TARGET_AUDIENCE} https://www.googleapis.com/oauth2/v3/certs`, 73 | ); 74 | 75 | assert.match(output, /ID token verified./); 76 | }); 77 | }); 78 | -------------------------------------------------------------------------------- /samples/test/downscoping-with-cab.test.js: -------------------------------------------------------------------------------- 1 | // Copyright 2021 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 | // http://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 | // Prerequisites: 16 | // Make sure to run the setup in samples/scripts/downscoping-with-cab-setup.js 17 | // and copy the logged constant strings (bucketName, objectName1 and 18 | // objectName2) into this file before running this test suite. 19 | // Once that is done, this test can be run indefinitely. 20 | // 21 | // The only requirement for this test suite to run is to set the environment 22 | // variable GOOGLE_APPLICATION_CREDENTIALS to point to the same service account 23 | // keys used in the setup script. 24 | 25 | const cp = require('child_process'); 26 | const {assert} = require('chai'); 27 | const {describe, it} = require('mocha'); 28 | const {promisify} = require('util'); 29 | 30 | const exec = promisify(cp.exec); 31 | // Copy values from the output of samples/scripts/downscoping-with-cab-setup.js. 32 | // GCS bucket name. 33 | const bucketName = 'cab-int-bucket-brd3qlsuok'; 34 | // GCS object name. 35 | const objectName = 'cab-first-"brd3qlsuok.txt'; 36 | 37 | /** 38 | * Runs the provided command using asynchronous child_process.exec. 39 | * Unlike execSync, this works with another local HTTP server running in the 40 | * background. 41 | * @param {string} cmd The actual command string to run. 42 | * @param {*} opts The optional parameters for child_process.exec. 43 | * @return {Promise} A promise that resolves with a string 44 | * corresponding with the terminal output. 45 | */ 46 | const execAsync = async (cmd, opts) => { 47 | const {stdout, stderr} = await exec(cmd, opts); 48 | return stdout + stderr; 49 | }; 50 | 51 | describe('samples for downscoping with cab', () => { 52 | it('should have access to the object specified in the cab rule', async () => { 53 | const output = await execAsync(`${process.execPath} downscopedclient`, { 54 | env: { 55 | ...process.env, 56 | // GCS bucket name environment variable. 57 | BUCKET_NAME: bucketName, 58 | // GCS object name environment variable. 59 | OBJECT_NAME: objectName, 60 | }, 61 | }); 62 | 63 | // Confirm expected script output. 64 | assert.match(output, /Successfully retrieved file/); 65 | assert.match(output, /first/); 66 | }); 67 | }); 68 | -------------------------------------------------------------------------------- /samples/test/jwt.test.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 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 | // http://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 | const cp = require('child_process'); 16 | const {assert} = require('chai'); 17 | const {describe, it} = require('mocha'); 18 | const fs = require('fs'); 19 | const {promisify} = require('util'); 20 | 21 | const execSync = (cmd, opts) => { 22 | return cp.execSync(cmd, Object.assign({encoding: 'utf-8'}, opts)); 23 | }; 24 | 25 | const readFile = promisify(fs.readFile); 26 | const keyFile = process.env.GOOGLE_APPLICATION_CREDENTIALS; 27 | 28 | describe('samples', () => { 29 | it('should acquire application default credentials', async () => { 30 | const output = execSync('node adc'); 31 | assert.match(output, /DNS Info:/); 32 | }); 33 | 34 | it('should create a JWT', async () => { 35 | const output = execSync('node jwt'); 36 | assert.match(output, /DNS Info:/); 37 | }); 38 | 39 | it('should read from a keyfile', async () => { 40 | const output = execSync('node keyfile'); 41 | assert.match(output, /DNS Info:/); 42 | }); 43 | 44 | it('should allow directly passing creds', async () => { 45 | const keys = JSON.parse(await readFile(keyFile, 'utf8')); 46 | const stdout = execSync('node credentials', { 47 | env: Object.assign({}, process.env, { 48 | CLIENT_EMAIL: keys.client_email, 49 | PRIVATE_KEY: keys.private_key, 50 | }), 51 | }); 52 | assert.match(stdout, /DNS Info:/); 53 | }); 54 | 55 | it('should obtain headers for a request', async () => { 56 | const output = execSync('node headers'); 57 | assert.match(output, /Headers:/); 58 | assert.match(output, /DNS Info:/); 59 | }); 60 | 61 | it('should fetch ID token for Cloud Run', async () => { 62 | // process.env.CLOUD_RUN_URL should be a cloud run service running 63 | // gcr.io/cloudrun/hello: 64 | const url = 65 | process.env.CLOUD_RUN_URL || 'https://hello-rftcw63abq-uc.a.run.app'; 66 | const output = execSync(`node idtokens-serverless ${url}`); 67 | assert.match(output, /What's next?/); 68 | }); 69 | 70 | it.skip('should fetch ID token for IAP', async () => { 71 | // process.env.IAP_URL should be an App Engine app, protected with IAP: 72 | const url = 73 | process.env.IAP_URL || 'https://nodejs-docs-samples-iap.appspot.com'; 74 | const targetAudience = 75 | process.env.IAP_CLIENT_ID || 76 | '170454875485-fbn7jalc9214bb67lslv1pbvmnijrb20.apps.googleusercontent.com'; 77 | const output = execSync(`node idtokens-iap ${url} ${targetAudience}`); 78 | assert.match(output, /Hello, world/); 79 | }); 80 | 81 | it('should sign the blobs with IAM credentials API', () => { 82 | const out = execSync('node signBlob'); 83 | assert.ok(out.length > 0); 84 | }); 85 | }); 86 | -------------------------------------------------------------------------------- /samples/verifyGoogleIdToken.js: -------------------------------------------------------------------------------- 1 | // Copyright 2022 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 | // http://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 | /** 16 | * Verifies the obtained Google id token. This is done at the receiving end of the OIDC endpoint. 17 | * The most common use case for verifying the ID token is when you are protecting 18 | * your own APIs with IAP. Google services already verify credentials as a platform, 19 | * so verifying ID tokens before making Google API calls is usually unnecessary. 20 | * 21 | * @param {string} idToken - The Google ID token to verify. 22 | * and use IAM to narrow the permissions: https://cloud.google.com/docs/authentication#authorization_for_services 23 | * @param {string} expectedAudience - The service name for which the id token is requested. Service name refers to the 24 | * logical identifier of an API service, such as "iap.googleapis.com". 25 | */ 26 | function main(idToken, expectedAudience) { 27 | // [START auth_cloud_verify_google_idtoken] 28 | /** 29 | * TODO(developer): 30 | * 1. Uncomment and replace these variables before running the sample. 31 | */ 32 | // const idToken = 'id-token'; 33 | // const targetAudience = 'pubsub.googleapis.com'; 34 | 35 | const {OAuth2Client} = require('google-auth-library'); 36 | 37 | async function verifyGoogleIdToken() { 38 | const oAuth2Client = new OAuth2Client(); 39 | 40 | const result = await oAuth2Client.verifyIdToken({ 41 | idToken, 42 | expectedAudience, 43 | }); 44 | 45 | // Verify that the token contains subject and email claims. 46 | // Get the User id. 47 | if (result.payload['sub']) { 48 | console.log(`User id: ${result.payload['sub']}`); 49 | } 50 | 51 | // Optionally, if "includeEmail" was set in the token options, check if the 52 | // email was verified 53 | if (result.payload['email_verified']) { 54 | console.log(`Email verified: ${result.payload['email_verified']}`); 55 | } 56 | 57 | console.log('ID token verified.'); 58 | } 59 | 60 | verifyGoogleIdToken(); 61 | // [END auth_cloud_verify_google_idtoken] 62 | } 63 | 64 | process.on('unhandledRejection', err => { 65 | console.error(err.message); 66 | process.exitCode = 1; 67 | }); 68 | 69 | main(...process.argv.slice(2)); 70 | -------------------------------------------------------------------------------- /samples/verifyIdToken-iap.js: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Google LLC 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // sample-metadata: 15 | // title: Verifying ID Tokens from Identity-Aware Proxy (IAP) 16 | // description: Verifying the signed token from the header of an IAP-protected resource. 17 | // usage: node verifyIdToken-iap.js [] [] [] 18 | 19 | 'use strict'; 20 | 21 | const {OAuth2Client} = require('google-auth-library'); 22 | 23 | /** 24 | * Verify the ID token from IAP 25 | * @see https://cloud.google.com/iap/docs/signed-headers-howto 26 | */ 27 | function main( 28 | iapJwt, 29 | projectNumber = '', 30 | projectId = '', 31 | backendServiceId = '', 32 | ) { 33 | // [START iap_validate_jwt] 34 | /** 35 | * TODO(developer): Uncomment these variables before running the sample. 36 | */ 37 | // const iapJwt = 'SOME_ID_TOKEN'; // JWT from the "x-goog-iap-jwt-assertion" header 38 | 39 | let expectedAudience = null; 40 | if (projectNumber && projectId) { 41 | // Expected Audience for App Engine. 42 | expectedAudience = `/projects/${projectNumber}/apps/${projectId}`; 43 | } else if (projectNumber && backendServiceId) { 44 | // Expected Audience for Compute Engine 45 | expectedAudience = `/projects/${projectNumber}/global/backendServices/${backendServiceId}`; 46 | } 47 | 48 | const oAuth2Client = new OAuth2Client(); 49 | 50 | async function verify() { 51 | // Verify the id_token, and access the claims. 52 | const response = await oAuth2Client.getIapPublicKeys(); 53 | const ticket = await oAuth2Client.verifySignedJwtWithCertsAsync( 54 | iapJwt, 55 | response.pubkeys, 56 | expectedAudience, 57 | ['https://cloud.google.com/iap'], 58 | ); 59 | // Print out the info contained in the IAP ID token 60 | console.log(ticket); 61 | } 62 | 63 | verify().catch(console.error); 64 | 65 | // [END iap_validate_jwt] 66 | if (!expectedAudience) { 67 | console.log( 68 | 'Audience not verified! Supply a projectNumber and projectID to verify', 69 | ); 70 | } 71 | } 72 | 73 | const args = process.argv.slice(2); 74 | main(...args); 75 | -------------------------------------------------------------------------------- /src/auth/credentials.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2014 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 | // http://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 | export interface Credentials { 16 | /** 17 | * This field is only present if the access_type parameter was set to offline in the authentication request. For details, see Refresh tokens. 18 | */ 19 | refresh_token?: string | null; 20 | /** 21 | * The time in ms at which this token is thought to expire. 22 | */ 23 | expiry_date?: number | null; 24 | /** 25 | * A token that can be sent to a Google API. 26 | */ 27 | access_token?: string | null; 28 | /** 29 | * Identifies the type of token returned. At this time, this field always has the value Bearer. 30 | */ 31 | token_type?: string | null; 32 | /** 33 | * A JWT that contains identity information about the user that is digitally signed by Google. 34 | */ 35 | id_token?: string | null; 36 | /** 37 | * The scopes of access granted by the access_token expressed as a list of space-delimited, case-sensitive strings. 38 | */ 39 | scope?: string; 40 | } 41 | 42 | export interface CredentialRequest { 43 | /** 44 | * This field is only present if the access_type parameter was set to offline in the authentication request. For details, see Refresh tokens. 45 | */ 46 | refresh_token?: string; 47 | /** 48 | * A token that can be sent to a Google API. 49 | */ 50 | access_token?: string; 51 | /** 52 | * Identifies the type of token returned. At this time, this field always has the value Bearer. 53 | */ 54 | token_type?: string; 55 | /** 56 | * The remaining lifetime of the access token in seconds. 57 | */ 58 | expires_in?: number; 59 | /** 60 | * A JWT that contains identity information about the user that is digitally signed by Google. 61 | */ 62 | id_token?: string; 63 | /** 64 | * The scopes of access granted by the access_token expressed as a list of space-delimited, case-sensitive strings. 65 | */ 66 | scope?: string; 67 | } 68 | 69 | export interface JWTInput { 70 | type?: string; 71 | client_email?: string; 72 | private_key?: string; 73 | private_key_id?: string; 74 | project_id?: string; 75 | client_id?: string; 76 | client_secret?: string; 77 | refresh_token?: string; 78 | quota_project_id?: string; 79 | universe_domain?: string; 80 | } 81 | 82 | export interface ImpersonatedJWTInput { 83 | type?: string; 84 | source_credentials?: JWTInput; 85 | service_account_impersonation_url?: string; 86 | delegates?: string[]; 87 | } 88 | 89 | export interface CredentialBody { 90 | client_email?: string; 91 | private_key?: string; 92 | universe_domain?: string; 93 | } 94 | -------------------------------------------------------------------------------- /src/auth/envDetect.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018 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 | // http://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 | import * as gcpMetadata from 'gcp-metadata'; 16 | 17 | export enum GCPEnv { 18 | APP_ENGINE = 'APP_ENGINE', 19 | KUBERNETES_ENGINE = 'KUBERNETES_ENGINE', 20 | CLOUD_FUNCTIONS = 'CLOUD_FUNCTIONS', 21 | COMPUTE_ENGINE = 'COMPUTE_ENGINE', 22 | CLOUD_RUN = 'CLOUD_RUN', 23 | NONE = 'NONE', 24 | } 25 | 26 | let envPromise: Promise | undefined; 27 | 28 | export function clear() { 29 | envPromise = undefined; 30 | } 31 | 32 | export async function getEnv() { 33 | if (envPromise) { 34 | return envPromise; 35 | } 36 | envPromise = getEnvMemoized(); 37 | return envPromise; 38 | } 39 | 40 | async function getEnvMemoized(): Promise { 41 | let env = GCPEnv.NONE; 42 | if (isAppEngine()) { 43 | env = GCPEnv.APP_ENGINE; 44 | } else if (isCloudFunction()) { 45 | env = GCPEnv.CLOUD_FUNCTIONS; 46 | } else if (await isComputeEngine()) { 47 | if (await isKubernetesEngine()) { 48 | env = GCPEnv.KUBERNETES_ENGINE; 49 | } else if (isCloudRun()) { 50 | env = GCPEnv.CLOUD_RUN; 51 | } else { 52 | env = GCPEnv.COMPUTE_ENGINE; 53 | } 54 | } else { 55 | env = GCPEnv.NONE; 56 | } 57 | return env; 58 | } 59 | 60 | function isAppEngine() { 61 | return !!(process.env.GAE_SERVICE || process.env.GAE_MODULE_NAME); 62 | } 63 | 64 | function isCloudFunction() { 65 | return !!(process.env.FUNCTION_NAME || process.env.FUNCTION_TARGET); 66 | } 67 | 68 | /** 69 | * This check only verifies that the environment is running knative. 70 | * This must be run *after* checking for Kubernetes, otherwise it will 71 | * return a false positive. 72 | */ 73 | function isCloudRun() { 74 | return !!process.env.K_CONFIGURATION; 75 | } 76 | 77 | async function isKubernetesEngine() { 78 | try { 79 | await gcpMetadata.instance('attributes/cluster-name'); 80 | return true; 81 | } catch (e) { 82 | return false; 83 | } 84 | } 85 | 86 | async function isComputeEngine() { 87 | return gcpMetadata.isAvailable(); 88 | } 89 | -------------------------------------------------------------------------------- /src/auth/externalclient.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021 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 | // http://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 | import { 16 | BaseExternalAccountClient, 17 | // This is the identifier in the JSON config for the type of credential. 18 | // This string constant indicates that an external account client should be 19 | // instantiated. 20 | // There are 3 types of JSON configs: 21 | // 1. authorized_user => Google end user credential 22 | // 2. service_account => Google service account credential 23 | // 3. external_Account => non-GCP service (eg. AWS, Azure, K8s) 24 | EXTERNAL_ACCOUNT_TYPE, 25 | } from './baseexternalclient'; 26 | import { 27 | IdentityPoolClient, 28 | IdentityPoolClientOptions, 29 | } from './identitypoolclient'; 30 | import {AwsClient, AwsClientOptions} from './awsclient'; 31 | import { 32 | PluggableAuthClient, 33 | PluggableAuthClientOptions, 34 | } from './pluggable-auth-client'; 35 | 36 | export type ExternalAccountClientOptions = 37 | | IdentityPoolClientOptions 38 | | AwsClientOptions 39 | | PluggableAuthClientOptions; 40 | 41 | /** 42 | * Dummy class with no constructor. Developers are expected to use fromJSON. 43 | */ 44 | export class ExternalAccountClient { 45 | constructor() { 46 | throw new Error( 47 | 'ExternalAccountClients should be initialized via: ' + 48 | 'ExternalAccountClient.fromJSON(), ' + 49 | 'directly via explicit constructors, eg. ' + 50 | 'new AwsClient(options), new IdentityPoolClient(options), new' + 51 | 'PluggableAuthClientOptions, or via ' + 52 | 'new GoogleAuth(options).getClient()', 53 | ); 54 | } 55 | 56 | /** 57 | * This static method will instantiate the 58 | * corresponding type of external account credential depending on the 59 | * underlying credential source. 60 | * @param options The external account options object typically loaded 61 | * from the external account JSON credential file. 62 | * @return A BaseExternalAccountClient instance or null if the options 63 | * provided do not correspond to an external account credential. 64 | */ 65 | static fromJSON( 66 | options: ExternalAccountClientOptions, 67 | ): BaseExternalAccountClient | null { 68 | if (options && options.type === EXTERNAL_ACCOUNT_TYPE) { 69 | if ((options as AwsClientOptions).credential_source?.environment_id) { 70 | return new AwsClient(options as AwsClientOptions); 71 | } else if ( 72 | (options as PluggableAuthClientOptions).credential_source?.executable 73 | ) { 74 | return new PluggableAuthClient(options as PluggableAuthClientOptions); 75 | } else { 76 | return new IdentityPoolClient(options as IdentityPoolClientOptions); 77 | } 78 | } else { 79 | return null; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/auth/iam.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2014 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 | // http://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 | export interface RequestMetadata { 16 | 'x-goog-iam-authority-selector': string; 17 | 'x-goog-iam-authorization-token': string; 18 | } 19 | 20 | export class IAMAuth { 21 | /** 22 | * IAM credentials. 23 | * 24 | * @param selector the iam authority selector 25 | * @param token the token 26 | * @constructor 27 | */ 28 | constructor( 29 | public selector: string, 30 | public token: string, 31 | ) { 32 | this.selector = selector; 33 | this.token = token; 34 | } 35 | 36 | /** 37 | * Acquire the HTTP headers required to make an authenticated request. 38 | */ 39 | getRequestHeaders() { 40 | return { 41 | 'x-goog-iam-authority-selector': this.selector, 42 | 'x-goog-iam-authorization-token': this.token, 43 | }; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/auth/idtokenclient.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 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 | // http://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 | import {Credentials} from './credentials'; 16 | import { 17 | OAuth2Client, 18 | OAuth2ClientOptions, 19 | RequestMetadataResponse, 20 | } from './oauth2client'; 21 | 22 | export interface IdTokenOptions extends OAuth2ClientOptions { 23 | /** 24 | * The client to make the request to fetch an ID token. 25 | */ 26 | idTokenProvider: IdTokenProvider; 27 | /** 28 | * The audience to use when requesting an ID token. 29 | */ 30 | targetAudience: string; 31 | } 32 | 33 | export interface IdTokenProvider { 34 | fetchIdToken: (targetAudience: string) => Promise; 35 | } 36 | 37 | export class IdTokenClient extends OAuth2Client { 38 | targetAudience: string; 39 | idTokenProvider: IdTokenProvider; 40 | 41 | /** 42 | * Google ID Token client 43 | * 44 | * Retrieve ID token from the metadata server. 45 | * See: https://cloud.google.com/docs/authentication/get-id-token#metadata-server 46 | */ 47 | constructor(options: IdTokenOptions) { 48 | super(options); 49 | this.targetAudience = options.targetAudience; 50 | this.idTokenProvider = options.idTokenProvider; 51 | } 52 | 53 | protected async getRequestMetadataAsync(): Promise { 54 | if ( 55 | !this.credentials.id_token || 56 | !this.credentials.expiry_date || 57 | this.isTokenExpiring() 58 | ) { 59 | const idToken = await this.idTokenProvider.fetchIdToken( 60 | this.targetAudience, 61 | ); 62 | this.credentials = { 63 | id_token: idToken, 64 | expiry_date: this.getIdTokenExpiryDate(idToken), 65 | } as Credentials; 66 | } 67 | 68 | const headers = new Headers({ 69 | authorization: 'Bearer ' + this.credentials.id_token, 70 | }); 71 | return {headers}; 72 | } 73 | 74 | private getIdTokenExpiryDate(idToken: string): number | void { 75 | const payloadB64 = idToken.split('.')[1]; 76 | if (payloadB64) { 77 | const payload = JSON.parse( 78 | Buffer.from(payloadB64, 'base64').toString('ascii'), 79 | ); 80 | return payload.exp * 1000; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/auth/passthrough.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | // http://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 | import {GaxiosOptions} from 'gaxios'; 16 | import {AuthClient, GetAccessTokenResponse} from './authclient'; 17 | 18 | /** 19 | * An AuthClient without any Authentication information. Useful for: 20 | * - Anonymous access 21 | * - Local Emulators 22 | * - Testing Environments 23 | * 24 | */ 25 | export class PassThroughClient extends AuthClient { 26 | /** 27 | * Creates a request without any authentication headers or checks. 28 | * 29 | * @remarks 30 | * 31 | * In testing environments it may be useful to change the provided 32 | * {@link AuthClient.transporter} for any desired request overrides/handling. 33 | * 34 | * @param opts 35 | * @returns The response of the request. 36 | */ 37 | async request(opts: GaxiosOptions) { 38 | return this.transporter.request(opts); 39 | } 40 | 41 | /** 42 | * A required method of the base class. 43 | * Always will return an empty object. 44 | * 45 | * @returns {} 46 | */ 47 | async getAccessToken(): Promise { 48 | return {}; 49 | } 50 | 51 | /** 52 | * A required method of the base class. 53 | * Always will return an empty object. 54 | * 55 | * @returns {} 56 | */ 57 | async getRequestHeaders(): Promise { 58 | return new Headers(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/crypto/crypto.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 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 | // http://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 | /* global window */ 15 | 16 | import {BrowserCrypto} from './browser/crypto'; 17 | import {NodeCrypto} from './node/crypto'; 18 | import {Crypto} from './shared'; 19 | 20 | export * from './shared'; 21 | 22 | export interface CryptoSigner { 23 | update(data: string): void; 24 | sign(key: string, outputFormat: string): string; 25 | } 26 | 27 | // Crypto interface will provide required crypto functions. 28 | // Use `createCrypto()` factory function to create an instance 29 | // of Crypto. It will either use Node.js `crypto` module, or 30 | // use browser's SubtleCrypto interface. Since most of the 31 | // SubtleCrypto methods return promises, we must make those 32 | // methods return promises here as well, even though in Node.js 33 | // they are synchronous. 34 | 35 | export function createCrypto(): Crypto { 36 | if (hasBrowserCrypto()) { 37 | return new BrowserCrypto(); 38 | } 39 | return new NodeCrypto(); 40 | } 41 | 42 | export function hasBrowserCrypto() { 43 | return ( 44 | typeof window !== 'undefined' && 45 | typeof window.crypto !== 'undefined' && 46 | typeof window.crypto.subtle !== 'undefined' 47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /src/crypto/node/crypto.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 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 | // http://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 | import * as crypto from 'crypto'; 16 | 17 | import {Crypto} from '../shared'; 18 | 19 | export class NodeCrypto implements Crypto { 20 | async sha256DigestBase64(str: string): Promise { 21 | return crypto.createHash('sha256').update(str).digest('base64'); 22 | } 23 | 24 | randomBytesBase64(count: number): string { 25 | return crypto.randomBytes(count).toString('base64'); 26 | } 27 | 28 | async verify( 29 | pubkey: string, 30 | data: string | Buffer, 31 | signature: string, 32 | ): Promise { 33 | const verifier = crypto.createVerify('RSA-SHA256'); 34 | verifier.update(data); 35 | verifier.end(); 36 | return verifier.verify(pubkey, signature, 'base64'); 37 | } 38 | 39 | async sign(privateKey: string, data: string | Buffer): Promise { 40 | const signer = crypto.createSign('RSA-SHA256'); 41 | signer.update(data); 42 | signer.end(); 43 | return signer.sign(privateKey, 'base64'); 44 | } 45 | 46 | decodeBase64StringUtf8(base64: string): string { 47 | return Buffer.from(base64, 'base64').toString('utf-8'); 48 | } 49 | 50 | encodeBase64StringUtf8(text: string): string { 51 | return Buffer.from(text, 'utf-8').toString('base64'); 52 | } 53 | 54 | /** 55 | * Computes the SHA-256 hash of the provided string. 56 | * @param str The plain text string to hash. 57 | * @return A promise that resolves with the SHA-256 hash of the provided 58 | * string in hexadecimal encoding. 59 | */ 60 | async sha256DigestHex(str: string): Promise { 61 | return crypto.createHash('sha256').update(str).digest('hex'); 62 | } 63 | 64 | /** 65 | * Computes the HMAC hash of a message using the provided crypto key and the 66 | * SHA-256 algorithm. 67 | * @param key The secret crypto key in utf-8 or ArrayBuffer format. 68 | * @param msg The plain text message. 69 | * @return A promise that resolves with the HMAC-SHA256 hash in ArrayBuffer 70 | * format. 71 | */ 72 | async signWithHmacSha256( 73 | key: string | ArrayBuffer, 74 | msg: string, 75 | ): Promise { 76 | const cryptoKey = typeof key === 'string' ? key : toBuffer(key); 77 | return toArrayBuffer( 78 | crypto.createHmac('sha256', cryptoKey).update(msg).digest(), 79 | ); 80 | } 81 | } 82 | 83 | /** 84 | * Converts a Node.js Buffer to an ArrayBuffer. 85 | * https://stackoverflow.com/questions/8609289/convert-a-binary-nodejs-buffer-to-javascript-arraybuffer 86 | * @param buffer The Buffer input to covert. 87 | * @return The ArrayBuffer representation of the input. 88 | */ 89 | function toArrayBuffer(buffer: Buffer): ArrayBuffer { 90 | return buffer.buffer.slice( 91 | buffer.byteOffset, 92 | buffer.byteOffset + buffer.byteLength, 93 | ); 94 | } 95 | 96 | /** 97 | * Converts an ArrayBuffer to a Node.js Buffer. 98 | * @param arrayBuffer The ArrayBuffer input to covert. 99 | * @return The Buffer representation of the input. 100 | */ 101 | function toBuffer(arrayBuffer: ArrayBuffer): Buffer { 102 | return Buffer.from(arrayBuffer); 103 | } 104 | -------------------------------------------------------------------------------- /src/crypto/shared.ts: -------------------------------------------------------------------------------- 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 | // http://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 | /** 16 | * Crypto interface will provide required crypto functions. 17 | * Use `createCrypto()` factory function to create an instance 18 | * of Crypto. It will either use Node.js `crypto` module, or 19 | * use browser's SubtleCrypto interface. Since most of the 20 | * SubtleCrypto methods return promises, we must make those 21 | * methods return promises here as well, even though in Node.js 22 | * they are synchronous. 23 | */ 24 | export interface Crypto { 25 | sha256DigestBase64(str: string): Promise; 26 | randomBytesBase64(n: number): string; 27 | verify( 28 | pubkey: string | JwkCertificate, 29 | data: string | Buffer, 30 | signature: string, 31 | ): Promise; 32 | sign( 33 | privateKey: string | JwkCertificate, 34 | data: string | Buffer, 35 | ): Promise; 36 | decodeBase64StringUtf8(base64: string): string; 37 | encodeBase64StringUtf8(text: string): string; 38 | /** 39 | * Computes the SHA-256 hash of the provided string. 40 | * @param str The plain text string to hash. 41 | * @return A promise that resolves with the SHA-256 hash of the provided 42 | * string in hexadecimal encoding. 43 | */ 44 | sha256DigestHex(str: string): Promise; 45 | 46 | /** 47 | * Computes the HMAC hash of a message using the provided crypto key and the 48 | * SHA-256 algorithm. 49 | * @param key The secret crypto key in utf-8 or ArrayBuffer format. 50 | * @param msg The plain text message. 51 | * @return A promise that resolves with the HMAC-SHA256 hash in ArrayBuffer 52 | * format. 53 | */ 54 | signWithHmacSha256( 55 | key: string | ArrayBuffer, 56 | msg: string, 57 | ): Promise; 58 | } 59 | 60 | export interface JwkCertificate { 61 | kty: string; 62 | alg: string; 63 | use?: string; 64 | kid: string; 65 | n: string; 66 | e: string; 67 | } 68 | 69 | /** 70 | * Converts an ArrayBuffer to a hexadecimal string. 71 | * @param arrayBuffer The ArrayBuffer to convert to hexadecimal string. 72 | * @return The hexadecimal encoding of the ArrayBuffer. 73 | */ 74 | export function fromArrayBufferToHex(arrayBuffer: ArrayBuffer): string { 75 | // Convert buffer to byte array. 76 | const byteArray = Array.from(new Uint8Array(arrayBuffer)); 77 | // Convert bytes to hex string. 78 | return byteArray 79 | .map(byte => { 80 | return byte.toString(16).padStart(2, '0'); 81 | }) 82 | .join(''); 83 | } 84 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2017 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 | // http://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 | import {GoogleAuth} from './auth/googleauth'; 15 | 16 | // Export common deps to ensure types/instances are the exact match. Useful 17 | // for consistently configuring the library across versions. 18 | export * as gcpMetadata from 'gcp-metadata'; 19 | export * as gaxios from 'gaxios'; 20 | 21 | import {AuthClient} from './auth/authclient'; 22 | export {AuthClient, DEFAULT_UNIVERSE} from './auth/authclient'; 23 | export {Compute, ComputeOptions} from './auth/computeclient'; 24 | export { 25 | CredentialBody, 26 | CredentialRequest, 27 | Credentials, 28 | JWTInput, 29 | } from './auth/credentials'; 30 | export {GCPEnv} from './auth/envDetect'; 31 | export {GoogleAuthOptions, ProjectIdCallback} from './auth/googleauth'; 32 | export {IAMAuth, RequestMetadata} from './auth/iam'; 33 | export {IdTokenClient, IdTokenProvider} from './auth/idtokenclient'; 34 | export {Claims, JWTAccess} from './auth/jwtaccess'; 35 | export {JWT, JWTOptions} from './auth/jwtclient'; 36 | export {Impersonated, ImpersonatedOptions} from './auth/impersonated'; 37 | export { 38 | Certificates, 39 | CodeChallengeMethod, 40 | CodeVerifierResults, 41 | GenerateAuthUrlOpts, 42 | GetTokenOptions, 43 | OAuth2Client, 44 | OAuth2ClientOptions, 45 | RefreshOptions, 46 | TokenInfo, 47 | VerifyIdTokenOptions, 48 | ClientAuthentication, 49 | } from './auth/oauth2client'; 50 | export {LoginTicket, TokenPayload} from './auth/loginticket'; 51 | export { 52 | UserRefreshClient, 53 | UserRefreshClientOptions, 54 | } from './auth/refreshclient'; 55 | export { 56 | AwsClient, 57 | AwsClientOptions, 58 | AwsSecurityCredentialsSupplier, 59 | } from './auth/awsclient'; 60 | export { 61 | AwsSecurityCredentials, 62 | AwsRequestSigner, 63 | } from './auth/awsrequestsigner'; 64 | export { 65 | IdentityPoolClient, 66 | IdentityPoolClientOptions, 67 | SubjectTokenSupplier, 68 | } from './auth/identitypoolclient'; 69 | export { 70 | ExternalAccountClient, 71 | ExternalAccountClientOptions, 72 | } from './auth/externalclient'; 73 | export { 74 | BaseExternalAccountClient, 75 | BaseExternalAccountClientOptions, 76 | SharedExternalAccountClientOptions, 77 | ExternalAccountSupplierContext, 78 | IamGenerateAccessTokenResponse, 79 | } from './auth/baseexternalclient'; 80 | export { 81 | CredentialAccessBoundary, 82 | DownscopedClient, 83 | } from './auth/downscopedclient'; 84 | export { 85 | PluggableAuthClient, 86 | PluggableAuthClientOptions, 87 | ExecutableError, 88 | } from './auth/pluggable-auth-client'; 89 | export {PassThroughClient} from './auth/passthrough'; 90 | 91 | type ALL_EXPORTS = (typeof import('./'))[keyof typeof import('./')]; 92 | 93 | /** 94 | * A union type for all {@link AuthClient `AuthClient`}s. 95 | */ 96 | export type AnyAuthClient = InstanceType< 97 | // Extract All `AuthClient`s from exports 98 | Extract 99 | >; 100 | 101 | const auth = new GoogleAuth(); 102 | export {auth, GoogleAuth}; 103 | -------------------------------------------------------------------------------- /src/shared.cts: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Google LLC 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | const pkg: { 15 | name: string; 16 | version: string; 17 | } = require('../../package.json'); 18 | 19 | const PRODUCT_NAME = 'google-api-nodejs-client'; 20 | const USER_AGENT = `${PRODUCT_NAME}/${pkg.version}`; 21 | 22 | export {pkg, PRODUCT_NAME, USER_AGENT}; 23 | -------------------------------------------------------------------------------- /system-test/fixtures/kitchen/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "google-auth-library-nodejs-fixture", 3 | "version": "1.0.0", 4 | "description": "An app we're using to test the library. ", 5 | "scripts": { 6 | "check": "gts check", 7 | "clean": "gts clean", 8 | "compile": "tsc -p .", 9 | "fix": "gts fix", 10 | "prepare": "npm run compile", 11 | "pretest": "npm run compile", 12 | "posttest": "npm run check", 13 | "start": "node build/src/index.js" 14 | }, 15 | "license": "Apache-2.0", 16 | "dependencies": { 17 | "google-auth-library": "file:./google-auth-library.tgz" 18 | }, 19 | "devDependencies": { 20 | "@types/node": "^22.0.0", 21 | "typescript": "^5.0.0", 22 | "gts": "^6.0.0", 23 | "null-loader": "^4.0.0", 24 | "ts-loader": "^8.0.0", 25 | "webpack": "^4.20.2", 26 | "webpack-cli": "^4.0.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /system-test/fixtures/kitchen/src/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 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 | // http://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 | import {GoogleAuth, JWT} from 'google-auth-library'; 16 | // uncomment the line below during development 17 | // import {GoogleAuth} from '../../../../build/src/index'; 18 | const jwt = new JWT(); 19 | const auth = new GoogleAuth(); 20 | async function getToken() { 21 | const token = await jwt.getToken('token'); 22 | await auth.getProjectId(); 23 | await auth.getApplicationDefault(); 24 | return token; 25 | } 26 | getToken(); 27 | -------------------------------------------------------------------------------- /system-test/fixtures/kitchen/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/gts/tsconfig-google.json", 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "outDir": "build", 6 | "esModuleInterop": false // test default setting 7 | }, 8 | "include": [ 9 | "src/*.ts", 10 | "src/**/*.ts" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /system-test/fixtures/kitchen/webpack.config.js: -------------------------------------------------------------------------------- 1 | // Copyright 2019 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 | // http://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 | // Use `npm run webpack` to produce Webpack bundle for this library. 16 | 17 | const path = require('path'); 18 | 19 | module.exports = { 20 | performance: { 21 | hints: false, 22 | maxEntrypointSize: 524288, 23 | maxAssetSize: 524288, 24 | }, 25 | entry: './src/index.ts', 26 | resolve: { 27 | extensions: ['.ts', '.js', '.json'], 28 | alias: { 29 | '../../package.json': path.resolve(__dirname, 'package.json'), 30 | }, 31 | }, 32 | output: { 33 | filename: 'bundle.min.js', 34 | path: path.resolve(__dirname, 'dist'), 35 | }, 36 | node: { 37 | child_process: 'empty', 38 | fs: 'empty', 39 | crypto: 'empty', 40 | }, 41 | module: { 42 | rules: [ 43 | { 44 | test: /node_modules\/gtoken\//, 45 | use: 'null-loader', 46 | }, 47 | { 48 | test: /node_modules\/pkginfo\//, 49 | use: 'null-loader', 50 | }, 51 | { 52 | test: /node_modules\/https-proxy-agent\//, 53 | use: 'null-loader', 54 | }, 55 | { 56 | test: /\.ts$/, 57 | use: 'ts-loader', 58 | exclude: /node_modules/, 59 | }, 60 | ], 61 | }, 62 | mode: 'production', 63 | plugins: [], 64 | }; 65 | -------------------------------------------------------------------------------- /test/fixtures/aws-security-credentials-fake.json: -------------------------------------------------------------------------------- 1 | { 2 | "Code" : "Success", 3 | "LastUpdated" : "2020-08-11T19:33:07Z", 4 | "Type" : "AWS-HMAC", 5 | "AccessKeyId" : "ASIARD4OQDT6A77FR3CL", 6 | "SecretAccessKey" : "Y8AfSaucF37G4PpvfguKZ3/l7Id4uocLXxX0+VTx", 7 | "Token" : "IQoJb3JpZ2luX2VjEIz//////////wEaCXVzLWVhc3QtMiJGMEQCIH7MHX/Oy/OB8OlLQa9GrqU1B914+iMikqWQW7vPCKlgAiA/Lsv8Jcafn14owfxXn95FURZNKaaphj0ykpmS+Ki+CSq0AwhlEAAaDDA3NzA3MTM5MTk5NiIMx9sAeP1ovlMTMKLjKpEDwuJQg41/QUKx0laTZYjPlQvjwSqS3OB9P1KAXPWSLkliVMMqaHqelvMF/WO/glv3KwuTfQsavRNs3v5pcSEm4SPO3l7mCs7KrQUHwGP0neZhIKxEXy+Ls//1C/Bqt53NL+LSbaGv6RPHaX82laz2qElphg95aVLdYgIFY6JWV5fzyjgnhz0DQmy62/Vi8pNcM2/VnxeCQ8CC8dRDSt52ry2v+nc77vstuI9xV5k8mPtnaPoJDRANh0bjwY5Sdwkbp+mGRUJBAQRlNgHUJusefXQgVKBCiyJY4w3Csd8Bgj9IyDV+Azuy1jQqfFZWgP68LSz5bURyIjlWDQunO82stZ0BgplKKAa/KJHBPCp8Qi6i99uy7qh76FQAqgVTsnDuU6fGpHDcsDSGoCls2HgZjZFPeOj8mmRhFk1Xqvkbjuz8V1cJk54d3gIJvQt8gD2D6yJQZecnuGWd5K2e2HohvCc8Fc9kBl1300nUJPV+k4tr/A5R/0QfEKOZL1/k5lf1g9CREnrM8LVkGxCgdYMxLQow1uTL+QU67AHRRSp5PhhGX4Rek+01vdYSnJCMaPhSEgcLqDlQkhk6MPsyT91QMXcWmyO+cAZwUPwnRamFepuP4K8k2KVXs/LIJHLELwAZ0ekyaS7CptgOqS7uaSTFG3U+vzFZLEnGvWQ7y9IPNQZ+Dffgh4p3vF4J68y9049sI6Sr5d5wbKkcbm8hdCDHZcv4lnqohquPirLiFQ3q7B17V9krMPu3mz1cg4Ekgcrn/E09NTsxAqD8NcZ7C7ECom9r+X3zkDOxaajW6hu3Az8hGlyylDaMiFfRbBJpTIlxp7jfa7CxikNgNtEKLH9iCzvuSg2vhA==", 8 | "Expiration" : "2020-08-11T07:35:49Z" 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/badlink: -------------------------------------------------------------------------------- 1 | ./noexists.json -------------------------------------------------------------------------------- /test/fixtures/config-no-quota/.config/gcloud/application_default_credentials.json: -------------------------------------------------------------------------------- 1 | { 2 | "client_id": "764086051850-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com", 3 | "client_secret": "privatekey", 4 | "refresh_token": "refreshtoken", 5 | "type": "authorized_user", 6 | "project_id": "my-project" 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/config-with-quota/.config/gcloud/application_default_credentials.json: -------------------------------------------------------------------------------- 1 | { 2 | "client_id": "764086051850-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com", 3 | "client_secret": "privatekey", 4 | "refresh_token": "refreshtoken", 5 | "type": "authorized_user", 6 | "project_id": "my-project", 7 | "quota_project_id": "my-quota-project" 8 | } 9 | -------------------------------------------------------------------------------- /test/fixtures/ecdsapublickeys.json: -------------------------------------------------------------------------------- 1 | { 2 | "2nMJtw": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9e1x7YRZg53A5zIJ0p2ZQ9yTrgPL\nGIf4ntOk+4O2R2+ryIObueyenPXE92tYG1NlKjDNyJLc7tsxi0UUnyxpig==\n-----END PUBLIC KEY-----\n", 3 | "f9R3yg": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESqCmEwytkqG6tL6a2GTQGmSNI4jH\nYo5MeDUs7DpETVhCXXLIFrLg2sZvNqw8SGnnonLoeqgOSqRdjJBGt4I6jQ==\n-----END PUBLIC KEY-----\n" 4 | } -------------------------------------------------------------------------------- /test/fixtures/empty.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /test/fixtures/emptylink: -------------------------------------------------------------------------------- 1 | ./empty.json -------------------------------------------------------------------------------- /test/fixtures/external-account-authorized-user-cred.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "external_account_authorized_user", 3 | "audience": "//iam.googleapis.com/projects/123456/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID", 4 | "client_id": "clientId", 5 | "client_secret": "clientSecret", 6 | "refresh_token": "refreshToken", 7 | "token_url": "https://sts.googleapis.com/v1/oauthtoken", 8 | "token_info_url": "https://sts.googleapis.com/v1/introspect" 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/external-account-cred.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "external_account", 3 | "audience": "//iam.googleapis.com/projects/123456/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID", 4 | "subject_token_type": "urn:ietf:params:oauth:token-type:jwt", 5 | "token_url": "https://sts.googleapis.com/v1/token", 6 | "credential_source": { 7 | "file": "./test/fixtures/external-subject-token.txt" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/external-subject-token.json: -------------------------------------------------------------------------------- 1 | { 2 | "access_token": "HEADER.SIMULATED_JWT_PAYLOAD.SIGNATURE" 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/external-subject-token.txt: -------------------------------------------------------------------------------- 1 | HEADER.SIMULATED_JWT_PAYLOAD.SIGNATURE -------------------------------------------------------------------------------- /test/fixtures/fake-ecdsa-private.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PARAMETERS----- 2 | MIH3AgEBMCwGByqGSM49AQECIQD/////AAAAAQAAAAAAAAAAAAAAAP////////// 3 | /////zBbBCD/////AAAAAQAAAAAAAAAAAAAAAP///////////////AQgWsY12Ko6 4 | k+ez671VdpiGvGUdBrDMU7D2O848PifSYEsDFQDEnTYIhucEk2pmeOETnSa3gZ9+ 5 | kARBBGsX0fLhLEJH+Lzm5WOkQPJ3A32BLeszoPShOUXYmMKWT+NC4v4af5uO5+tK 6 | fA+eFivOM1drMV7Oy7ZAaDe/UfUCIQD/////AAAAAP//////////vOb6racXnoTz 7 | ucrC/GMlUQIBAQ== 8 | -----END EC PARAMETERS----- 9 | -----BEGIN EC PRIVATE KEY----- 10 | MIIBaAIBAQQgI59iRg8vYTW9VySmCM3Tvn+WPLKQr132U5HGec3HTgWggfowgfcC 11 | AQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAAAAAAAAAAAAAA//////////////// 12 | MFsEIP////8AAAABAAAAAAAAAAAAAAAA///////////////8BCBaxjXYqjqT57Pr 13 | vVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVAMSdNgiG5wSTamZ44ROdJreBn36QBEEE 14 | axfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5RdiYwpZP40Li/hp/m47n60p8D54W 15 | K84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA//////////+85vqtpxeehPO5ysL8 16 | YyVRAgEBoUQDQgAEUF5XFvBU1J2PP2Ggh/DiLNv9l4MTM/edN145vGOZIvWe4QBp 17 | FaqzLN7WjTP7BiJCXI044iqRbuDGc2goPf8LMw== 18 | -----END EC PRIVATE KEY----- 19 | -------------------------------------------------------------------------------- /test/fixtures/fake-ecdsa-public.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBSzCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAA 3 | AAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA//// 4 | ///////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVAMSd 5 | NgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5 6 | RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA 7 | //////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABFBeVxbwVNSdjz9hoIfw4izb 8 | /ZeDEzP3nTdeObxjmSL1nuEAaRWqsyze1o0z+wYiQlyNOOIqkW7gxnNoKD3/CzM= 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /test/fixtures/goodlink: -------------------------------------------------------------------------------- 1 | ./private.json -------------------------------------------------------------------------------- /test/fixtures/impersonated_application_default_credentials.json: -------------------------------------------------------------------------------- 1 | { 2 | "delegates": [], 3 | "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/target@project.iam.gserviceaccount.com:generateAccessToken", 4 | "source_credentials": { 5 | "client_id": "764086051850-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com", 6 | "client_secret": "privatekey", 7 | "refresh_token": "refreshtoken", 8 | "type": "authorized_user" 9 | }, 10 | "type": "impersonated_service_account" 11 | } -------------------------------------------------------------------------------- /test/fixtures/key.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-nodejs/ed6296b02a18920399f9d2401cfe615d3698ef38/test/fixtures/key.p12 -------------------------------------------------------------------------------- /test/fixtures/oauthcertspem.json: -------------------------------------------------------------------------------- 1 | { 2 | "a15eea964ab9cce480e5ef4f47cb17b9fa7d0b21": "-----BEGIN CERTIFICATE-----\nMIICITCCAYqgAwIBAgIIY9n5UFWlXMAwDQYJKoZIhvcNAQEFBQAwNjE0MDIGA1UE\nAxMrZmVkZXJhdGVkLXNpZ25vbi5zeXN0ZW0uZ3NlcnZpY2VhY2NvdW50LmNvbTAe\nFw0xNDA3MTUyMTU4MzRaFw0xNDA3MTcxMDU4MzRaMDYxNDAyBgNVBAMTK2ZlZGVy\nYXRlZC1zaWdub24uc3lzdGVtLmdzZXJ2aWNlYWNjb3VudC5jb20wgZ8wDQYJKoZI\nhvcNAQEBBQADgY0AMIGJAoGBAMT3/AJ10HrJpVccblw6/U5tRla+XRLnqIwrL6d5\nafjp2foFzY6pMpF6Nf0kDVZrLEi00nLAJ4XLc3DMAU6Lfmasz8ssCsZtt4egYb9C\nRXc1XgiX0xNGILjVuniq1bWMuoXYO3ZOFTQC6ja3Yh6cEXNowAhWYhxSL0FErur9\nJ0mRAgMBAAGjODA2MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMBYGA1Ud\nJQEB/wQMMAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBBQUAA4GBAIh8vugPyw8JpCrj\nLrIy2w22hqUvs001o9PcFochdlXfsBJdPSm6iO3tYJHGBv8CXqiepr6yBToQMyIh\nay55A11QtLwKlEcpq1adMe8iqkqhWzqYNGU0zLn1+XsINy8g3YDLyFemX/0OA9r1\n7WuFo73Jp3O5G0fI6E56rRTZQzCf\n-----END CERTIFICATE-----\n", 3 | "39596dc3a3f12aa74b481579e4ec944f86d24b95": "-----BEGIN CERTIFICATE-----\nMIICITCCAYqgAwIBAgIIVGbuMRHq6YMwDQYJKoZIhvcNAQEFBQAwNjE0MDIGA1UE\nAxMrZmVkZXJhdGVkLXNpZ25vbi5zeXN0ZW0uZ3NlcnZpY2VhY2NvdW50LmNvbTAe\nFw0xNDA3MTYyMTQzMzRaFw0xNDA3MTgxMDQzMzRaMDYxNDAyBgNVBAMTK2ZlZGVy\nYXRlZC1zaWdub24uc3lzdGVtLmdzZXJ2aWNlYWNjb3VudC5jb20wgZ8wDQYJKoZI\nhvcNAQEBBQADgY0AMIGJAoGBAKE7fORxNmBsk0IRN5J+IGk4QkD6bYGN89yyav8d\nqvUJ7NThVJoVK9CbsO8DW9PVohabTAfoebVakBF4gMzcKvMvoJ0lyFiy9R6/t9Py\nvb4kUhyo6nXBcdEQQ/rPhM777LqXxfMaA75LXBU07v0XS4mIu4mq75K2AM2kjrOC\nlJ+TAgMBAAGjODA2MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMBYGA1Ud\nJQEB/wQMMAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBBQUAA4GBABqDpTNCkk26mDh5\n925qoneRWHC5mnTkdG/k5FFplTABwtDCfiDlsrnjq1cKkDfl9GrCc8T7UKeJwjR3\n+dGo6SlBzC9Zt8SYPS//nDFFj1PdgGSGoTnp4ku47CdqJgY4x19IsVq+d0Ezetr9\nyS8GRVi86P14/r4vsn3SJmolhZmI\n-----END CERTIFICATE-----\n" 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/private.json: -------------------------------------------------------------------------------- 1 | { 2 | "private_key_id": "key123", 3 | "private_key": "privatekey", 4 | "client_email": "hello@youarecool.com", 5 | "client_id": "client123", 6 | "type": "service_account", 7 | "project_id": "not-a-project-id" 8 | } -------------------------------------------------------------------------------- /test/fixtures/private.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXQIBAAKBgQDzU+jLTzW6154Joezxrd2+5pCNYP0HcaMoYqEyXfNRpkNE7wrQ 3 | UEG830o4Qcaae2BhqZoujwSW7RkR6h0Fkd0WTR8h5J8rSGNHv/1jJoUUjP9iZ/5S 4 | FAyIIyEYfDPqtnA4iF1QWO2lXWlEFSuZjwM/8jBmeGzoiw17akNThIw8NwIDAQAB 5 | AoGATpboVloEAY/IdFX/QGOmfhTb1T3hG3lheBa695iOkO2BRo9qT7PMN6NqxlbA 6 | PX7ht0lfCfCZS+HSOg4CR50/6WXHMSmwlvcjGuDIDKWjviQTTYE77MlVBQHw9WzY 7 | PfiRBbtouyPGQtO4rk42zkIILC6exBZ1vKpRPOmTAnxrjCECQQD+56r6hYcS6GNp 8 | NOWyv0eVFMBX4iNWAsRf9JVVvGDz2rVuhnkNiN73vfffDWvSXkCydL1jFmalgdQD 9 | gm77UZQHAkEA9F+CauU0aZsJ1SthQ6H0sDQ+eNRUgnz4itnkSC2C20fZ3DaSpCMC 10 | 0go81CcZOhftNO730ILqiS67C3d3rqLqUQJBAP10ROHMmz4Fq7MUUcClyPtHIuk/ 11 | hXskTTZL76DMKmrN8NDxDLSUf38+eJRkt+z4osPOp/E6eN3gdXr32nox50kCQCl8 12 | hXGMU+eR0IuF/88xkY7Qb8KnmWlFuhQohZ7TSyHbAttl0GNZJkNuRYFm2duI8FZK 13 | M3wMnbCIZGy/7WuScOECQQCV+0yrf5dL1M2GHjJfwuTb00wRKalKQEH1v/kvE5vS 14 | FmdN7BPK5Ra50MaecMNoYqu9rmtyWRBn93dcvKrL57nY 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /test/fixtures/private2.json: -------------------------------------------------------------------------------- 1 | { 2 | "private_key_id": "key456", 3 | "private_key": "privatekey2", 4 | "client_email": "goodbye@youarecool.com", 5 | "client_id": "client456", 6 | "type": "service_account", 7 | "project_id": "my-awesome-project", 8 | "universe_domain": "my-universe" 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/public.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDzU+jLTzW6154Joezxrd2+5pCN 3 | YP0HcaMoYqEyXfNRpkNE7wrQUEG830o4Qcaae2BhqZoujwSW7RkR6h0Fkd0WTR8h 4 | 5J8rSGNHv/1jJoUUjP9iZ/5SFAyIIyEYfDPqtnA4iF1QWO2lXWlEFSuZjwM/8jBm 5 | eGzoiw17akNThIw8NwIDAQAB 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /test/fixtures/refresh.json: -------------------------------------------------------------------------------- 1 | { 2 | "client_secret": "privatekey", 3 | "client_id": "client123", 4 | "refresh_token": "refreshtoken", 5 | "type": "authorized_user" 6 | } 7 | -------------------------------------------------------------------------------- /test/fixtures/service-account-with-quota.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "service_account", 3 | "project_id": "my-account", 4 | "private_key_id": "abc123", 5 | "client_email": "fake@example.com", 6 | "client_id": "222222222222222222222", 7 | "auth_uri": "https://accounts.google.com/o/oauth2/auth", 8 | "token_uri": "https://oauth2.googleapis.com/token", 9 | "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", 10 | "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/fake@example.com", 11 | "quota_project_id": "fake-quota-project" 12 | } 13 | -------------------------------------------------------------------------------- /test/fixtures/wellKnown.json: -------------------------------------------------------------------------------- 1 | { 2 | "client_id": "764086051850-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com", 3 | "client_secret": "privatekey", 4 | "refresh_token": "refreshtoken", 5 | "type": "authorized_user" 6 | } 7 | -------------------------------------------------------------------------------- /test/test.iam.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2013 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 | // http://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 | import * as assert from 'assert'; 16 | import {describe, it, beforeEach, afterEach} from 'mocha'; 17 | import * as sinon from 'sinon'; 18 | import {IAMAuth} from '../src'; 19 | 20 | describe('iam', () => { 21 | const testSelector = 'a-test-selector'; 22 | const testToken = 'a-test-token'; 23 | 24 | let sandbox: sinon.SinonSandbox; 25 | let client: IAMAuth; 26 | beforeEach(() => { 27 | sandbox = sinon.createSandbox(); 28 | client = new IAMAuth(testSelector, testToken); 29 | }); 30 | afterEach(() => { 31 | sandbox.restore(); 32 | }); 33 | 34 | it('passes the token and selector to the callback ', async () => { 35 | const creds = client.getRequestHeaders(); 36 | assert.notStrictEqual(creds, null, 'metadata should be present'); 37 | assert.strictEqual(creds!['x-goog-iam-authority-selector'], testSelector); 38 | assert.strictEqual(creds!['x-goog-iam-authorization-token'], testToken); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /test/test.idtokenclient.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 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 | // http://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 | import * as assert from 'assert'; 16 | import {describe, it, afterEach} from 'mocha'; 17 | import * as fs from 'fs'; 18 | import * as nock from 'nock'; 19 | 20 | import {IdTokenClient, JWT} from '../src'; 21 | import {CredentialRequest} from '../src/auth/credentials'; 22 | 23 | describe('idtokenclient', () => { 24 | const PEM_PATH = './test/fixtures/private.pem'; 25 | const PEM_CONTENTS = fs.readFileSync(PEM_PATH, 'utf8'); 26 | nock.disableNetConnect(); 27 | 28 | function createGTokenMock(body: CredentialRequest) { 29 | return nock('https://oauth2.googleapis.com') 30 | .post('/token') 31 | .reply(200, body); 32 | } 33 | 34 | afterEach(() => { 35 | nock.cleanAll(); 36 | }); 37 | 38 | it('should determine expiry_date from JWT', async () => { 39 | const idToken = 'header.eyJleHAiOiAxNTc4NzAyOTU2fQo.signature'; 40 | const jwt = new JWT({ 41 | email: 'foo@serviceaccount.com', 42 | key: PEM_CONTENTS, 43 | subject: 'ignored@subjectaccount.com', 44 | }); 45 | 46 | const scope = createGTokenMock({id_token: idToken}); 47 | const targetAudience = 'a-target-audience'; 48 | const client = new IdTokenClient({idTokenProvider: jwt, targetAudience}); 49 | await client.getRequestHeaders(); 50 | scope.done(); 51 | assert.strictEqual(client.credentials.expiry_date, 1578702956000); 52 | }); 53 | 54 | it('should refresh ID token if expired', async () => { 55 | const jwt = new JWT({ 56 | email: 'foo@serviceaccount.com', 57 | key: PEM_CONTENTS, 58 | subject: 'ignored@subjectaccount.com', 59 | }); 60 | 61 | const scope = createGTokenMock({id_token: 'abc123'}); 62 | const targetAudience = 'a-target-audience'; 63 | const client = new IdTokenClient({idTokenProvider: jwt, targetAudience}); 64 | client.credentials = { 65 | id_token: 'an-identity-token', 66 | expiry_date: new Date().getTime() - 1000, 67 | }; 68 | const headers = await client.getRequestHeaders(); 69 | scope.done(); 70 | assert.strictEqual(client.credentials.id_token, 'abc123'); 71 | assert.deepStrictEqual( 72 | headers, 73 | new Headers({authorization: 'Bearer abc123'}), 74 | ); 75 | }); 76 | 77 | it('should refresh ID token if expiry_date not set', async () => { 78 | const jwt = new JWT({ 79 | email: 'foo@serviceaccount.com', 80 | key: PEM_CONTENTS, 81 | subject: 'ignored@subjectaccount.com', 82 | }); 83 | 84 | const scope = createGTokenMock({id_token: 'abc123'}); 85 | const targetAudience = 'a-target-audience'; 86 | const client = new IdTokenClient({idTokenProvider: jwt, targetAudience}); 87 | client.credentials = { 88 | id_token: 'an-identity-token', 89 | }; 90 | const headers = await client.getRequestHeaders(); 91 | scope.done(); 92 | assert.strictEqual(client.credentials.id_token, 'abc123'); 93 | assert.deepStrictEqual( 94 | headers, 95 | new Headers({authorization: 'Bearer abc123'}), 96 | ); 97 | }); 98 | }); 99 | -------------------------------------------------------------------------------- /test/test.index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2017 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 | // http://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 | import * as assert from 'assert'; 15 | import {describe, it} from 'mocha'; 16 | import * as gal from '../src'; 17 | 18 | describe('index', () => { 19 | it('should publicly export GoogleAuth', () => { 20 | // eslint-disable-next-line @typescript-eslint/no-var-requires 21 | const cjs = require('../src/'); 22 | assert.strictEqual(cjs.GoogleAuth, gal.GoogleAuth); 23 | }); 24 | 25 | it('should export all the things', () => { 26 | assert(gal.CodeChallengeMethod); 27 | assert(gal.Compute); 28 | assert(gal.IAMAuth); 29 | assert(gal.JWT); 30 | assert(gal.JWTAccess); 31 | assert(gal.OAuth2Client); 32 | assert(gal.UserRefreshClient); 33 | assert(gal.GoogleAuth); 34 | assert(gal.ExternalAccountClient); 35 | assert(gal.IdentityPoolClient); 36 | assert(gal.AwsClient); 37 | assert(gal.BaseExternalAccountClient); 38 | assert(gal.DownscopedClient); 39 | assert(gal.Impersonated); 40 | 41 | assert(gal.gaxios); 42 | assert(gal.gcpMetadata); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /test/test.loginticket.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2015 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 | // http://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 | import * as assert from 'assert'; 16 | import {describe, it} from 'mocha'; 17 | import {LoginTicket} from '../src/auth/loginticket'; 18 | 19 | describe('loginticket', () => { 20 | it('should return null userId even if no payload', () => { 21 | const ticket = new LoginTicket(); 22 | assert.strictEqual(ticket.getUserId(), null); 23 | }); 24 | 25 | it('should return envelope', () => { 26 | const ticket = new LoginTicket('myenvelope'); 27 | assert.strictEqual(ticket.getEnvelope(), 'myenvelope'); 28 | }); 29 | 30 | it('should return attributes from getAttributes', () => { 31 | const payload = { 32 | aud: 'aud', 33 | sub: 'sub', 34 | iss: 'iss', 35 | iat: 1514162443, 36 | exp: 1514166043, 37 | }; 38 | const ticket = new LoginTicket('myenvelope', payload); 39 | assert.deepStrictEqual(ticket.getAttributes(), { 40 | envelope: 'myenvelope', 41 | payload, 42 | }); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /test/test.passthroughclient.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | // http://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 | import {strict as assert} from 'assert'; 16 | 17 | import * as nock from 'nock'; 18 | 19 | import {PassThroughClient} from '../src'; 20 | 21 | describe('AuthClient', () => { 22 | before(async () => { 23 | nock.disableNetConnect(); 24 | }); 25 | 26 | afterEach(async () => { 27 | nock.cleanAll(); 28 | }); 29 | 30 | describe('#getAccessToken', () => { 31 | it('should return an empty object', async () => { 32 | const client = new PassThroughClient(); 33 | const token = await client.getAccessToken(); 34 | 35 | assert.deepEqual(token, {}); 36 | }); 37 | }); 38 | 39 | describe('#getRequestHeaders', () => { 40 | it('should return an empty `Headers` object', async () => { 41 | const client = new PassThroughClient(); 42 | const token = await client.getRequestHeaders(); 43 | 44 | assert.deepEqual(token, new Headers()); 45 | }); 46 | }); 47 | 48 | describe('#request', () => { 49 | it('should return the expected response', async () => { 50 | const url = 'https://google.com'; 51 | const example = {test: 'payload'}; 52 | const scope = nock(url).get('/').reply(200, example); 53 | 54 | const client = new PassThroughClient(); 55 | const response = await client.request({url}); 56 | 57 | assert.deepEqual(response.data, example); 58 | 59 | scope.done(); 60 | }); 61 | }); 62 | }); 63 | -------------------------------------------------------------------------------- /test/test.util.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2023 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 | // http://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 | import {strict as assert} from 'assert'; 16 | import * as sinon from 'sinon'; 17 | 18 | import {LRUCache} from '../src/util'; 19 | 20 | describe('util', () => { 21 | let sandbox: sinon.SinonSandbox; 22 | 23 | beforeEach(() => { 24 | sandbox = sinon.createSandbox(); 25 | }); 26 | 27 | afterEach(() => { 28 | sandbox.restore(); 29 | }); 30 | 31 | describe('LRUCache', () => { 32 | it('should set and get a cached item', () => { 33 | const expected = 'value'; 34 | const lru = new LRUCache({capacity: 5}); 35 | lru.set('sample', expected); 36 | 37 | assert.equal(lru.get('sample'), expected); 38 | }); 39 | 40 | it('should evict oldest items when over capacity', () => { 41 | const capacity = 5; 42 | const overCapacity = 2; 43 | 44 | const lru = new LRUCache({capacity}); 45 | 46 | for (let i = 0; i < capacity + overCapacity; i++) { 47 | lru.set(`${i}`, i); 48 | } 49 | 50 | // the first few shouldn't be there 51 | for (let i = 0; i < overCapacity; i++) { 52 | assert.equal(lru.get(`${i}`), undefined); 53 | } 54 | 55 | // the rest should be there 56 | for (let i = overCapacity; i < capacity + overCapacity; i++) { 57 | assert.equal(lru.get(`${i}`), i); 58 | } 59 | }); 60 | 61 | it('should evict items older than a supplied `maxAge`', async () => { 62 | const maxAge = 50; 63 | 64 | sandbox.clock = sinon.useFakeTimers(); 65 | 66 | const lru = new LRUCache({capacity: 5, maxAge}); 67 | 68 | lru.set('first', 1); 69 | lru.set('second', 2); 70 | 71 | // back to the future 🏎️ 72 | sandbox.clock.tick(maxAge + 1); 73 | 74 | // just set, so should be fine 75 | lru.set('third', 3); 76 | assert.equal(lru.get('third'), 3); 77 | 78 | // these are too old 79 | assert.equal(lru.get('first'), undefined); 80 | assert.equal(lru.get('second'), undefined); 81 | }); 82 | }); 83 | }); 84 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/gts/tsconfig-google.json", 3 | "compilerOptions": { 4 | "lib": ["DOM"], 5 | "rootDir": ".", 6 | "outDir": "build" 7 | }, 8 | "include": [ 9 | "src/**/*.ts", 10 | "src/**/*.cts", 11 | "test/**/*.ts", 12 | "system-test/*.ts", 13 | "browser-test/*.ts", 14 | "browser-test/**/*.ts" 15 | ], 16 | "exclude": ["test/fixtures"] 17 | } 18 | -------------------------------------------------------------------------------- /webpack-tests.config.js: -------------------------------------------------------------------------------- 1 | // Copyright 2019 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 | // http://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 | // This configuration file is used for browser testing with Karma. 16 | // See karma.conf.js for details. 17 | 18 | const path = require('path'); 19 | 20 | module.exports = { 21 | resolve: { 22 | extensions: ['.ts', '.js', '.json'], 23 | alias: { 24 | '../../package.json': path.resolve(__dirname, 'package.json'), 25 | }, 26 | }, 27 | node: { 28 | child_process: 'empty', 29 | fs: 'empty', 30 | crypto: 'empty', 31 | }, 32 | module: { 33 | rules: [ 34 | { 35 | test: /src\/crypto\/node\/crypto/, 36 | use: 'null-loader', 37 | }, 38 | { 39 | test: /node_modules\/gtoken\//, 40 | use: 'null-loader', 41 | }, 42 | { 43 | test: /node_modules\/pkginfo\//, 44 | use: 'null-loader', 45 | }, 46 | { 47 | test: /node_modules\/https-proxy-agent\//, 48 | use: 'null-loader', 49 | }, 50 | { 51 | test: /\.ts$/, 52 | use: 'ts-loader', 53 | exclude: /node_modules/, 54 | }, 55 | ], 56 | }, 57 | mode: 'production', 58 | plugins: [], 59 | performance: {hints: false}, 60 | }; 61 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | // Copyright 2019 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 | // http://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 | // Use `npm run webpack` to produce Webpack bundle for this library. 16 | 17 | const path = require('path'); 18 | 19 | module.exports = { 20 | entry: './src/index.ts', 21 | resolve: { 22 | extensions: ['.ts', '.js', '.json'], 23 | alias: { 24 | '../../package.json': path.resolve(__dirname, 'package.json'), 25 | }, 26 | }, 27 | output: { 28 | library: 'GoogleAuth', 29 | filename: 'google-auth-library.min.js', 30 | path: path.resolve(__dirname, 'dist'), 31 | }, 32 | node: { 33 | child_process: 'empty', 34 | fs: 'empty', 35 | crypto: 'empty', 36 | }, 37 | module: { 38 | rules: [ 39 | { 40 | test: /src\/crypto\/node\/crypto/, 41 | use: 'null-loader', 42 | }, 43 | { 44 | test: /node_modules\/https-proxy-agent\//, 45 | use: 'null-loader', 46 | }, 47 | { 48 | test: /node_modules\/gtoken\//, 49 | use: 'null-loader', 50 | }, 51 | { 52 | test: /node_modules\/pkginfo\//, 53 | use: 'null-loader', 54 | }, 55 | { 56 | test: /node_modules\/semver\//, 57 | use: 'null-loader', 58 | }, 59 | { 60 | test: /\.ts$/, 61 | use: 'ts-loader', 62 | exclude: /node_modules/, 63 | }, 64 | ], 65 | }, 66 | mode: 'production', 67 | plugins: [], 68 | }; 69 | --------------------------------------------------------------------------------