google-auth-library
Advanced tools
Comparing version
@@ -27,2 +27,5 @@ import { GaxiosError, GaxiosOptions, GaxiosPromise, GaxiosResponse } from 'gaxios'; | ||
} | ||
export interface PublicKeys { | ||
[index: string]: string; | ||
} | ||
export interface Headers { | ||
@@ -262,2 +265,9 @@ [index: string]: string; | ||
} | ||
export interface GetIapPublicKeysCallback { | ||
(err: GaxiosError | null, pubkeys?: PublicKeys, response?: GaxiosResponse<void> | null): void; | ||
} | ||
export interface IapPublicKeysResponse { | ||
pubkeys: PublicKeys; | ||
res?: GaxiosResponse<void> | null; | ||
} | ||
export interface RevokeCredentialsResult { | ||
@@ -326,2 +336,6 @@ success: boolean; | ||
/** | ||
* Google Sign on certificates in JWK format. | ||
*/ | ||
private static readonly GOOGLE_OAUTH2_IAP_PUBLIC_KEY_URL_; | ||
/** | ||
* Clock skew - five minutes in seconds | ||
@@ -463,2 +477,11 @@ */ | ||
getFederatedSignonCertsAsync(): Promise<FederatedSignonCertsResponse>; | ||
/** | ||
* Gets federated sign-on certificates to use for verifying identity tokens. | ||
* Returns certs as array structure, where keys are key ids, and values | ||
* are certificates in either PEM or JWK format. | ||
* @param callback Callback supplying the certificates | ||
*/ | ||
getIapPublicKeys(): Promise<IapPublicKeysResponse>; | ||
getIapPublicKeys(callback: GetIapPublicKeysCallback): void; | ||
getIapPublicKeysAsync(): Promise<IapPublicKeysResponse>; | ||
verifySignedJwtWithCerts(): void; | ||
@@ -475,3 +498,3 @@ /** | ||
*/ | ||
verifySignedJwtWithCertsAsync(jwt: string, certs: Certificates, requiredAudience: string | string[], issuers?: string[], maxExpiry?: number): Promise<LoginTicket>; | ||
verifySignedJwtWithCertsAsync(jwt: string, certs: Certificates | PublicKeys, requiredAudience: string | string[], issuers?: string[], maxExpiry?: number): Promise<LoginTicket>; | ||
/** | ||
@@ -478,0 +501,0 @@ * Returns true if a token is expired or will expire within |
@@ -18,2 +18,3 @@ "use strict"; | ||
const stream = require("stream"); | ||
const formatEcdsa = require("ecdsa-sig-formatter"); | ||
const crypto_1 = require("../crypto/crypto"); | ||
@@ -492,2 +493,23 @@ const messages = require("../messages"); | ||
} | ||
getIapPublicKeys(callback) { | ||
if (callback) { | ||
this.getIapPublicKeysAsync().then(r => callback(null, r.pubkeys, r.res), callback); | ||
} | ||
else { | ||
return this.getIapPublicKeysAsync(); | ||
} | ||
} | ||
async getIapPublicKeysAsync() { | ||
const nowTime = new Date().getTime(); | ||
let res; | ||
const url = OAuth2Client.GOOGLE_OAUTH2_IAP_PUBLIC_KEY_URL_; | ||
try { | ||
res = await this.transporter.request({ url }); | ||
} | ||
catch (e) { | ||
e.message = `Failed to retrieve verification certificates: ${e.message}`; | ||
throw e; | ||
} | ||
return { pubkeys: res.data, res }; | ||
} | ||
verifySignedJwtWithCerts() { | ||
@@ -518,3 +540,3 @@ // To make the code compatible with browser SubtleCrypto we need to make | ||
const signed = segments[0] + '.' + segments[1]; | ||
const signature = segments[2]; | ||
let signature = segments[2]; | ||
let envelope; | ||
@@ -547,2 +569,5 @@ let payload; | ||
const cert = certs[envelope.kid]; | ||
if (envelope.alg === 'ES256') { | ||
signature = formatEcdsa.joseToDer(signature, 'ES256').toString('base64'); | ||
} | ||
const verified = await crypto.verify(cert, signed, signature); | ||
@@ -645,2 +670,6 @@ if (!verified) { | ||
/** | ||
* Google Sign on certificates in JWK format. | ||
*/ | ||
OAuth2Client.GOOGLE_OAUTH2_IAP_PUBLIC_KEY_URL_ = 'https://www.gstatic.com/iap/verify/public_key'; | ||
/** | ||
* Clock skew - five minutes in seconds | ||
@@ -647,0 +676,0 @@ */ |
@@ -7,2 +7,14 @@ # Changelog | ||
## [5.10.0](https://www.github.com/googleapis/google-auth-library-nodejs/compare/v5.9.2...v5.10.0) (2020-02-20) | ||
### Features | ||
* support for verifying ES256 and retrieving IAP public keys ([#887](https://www.github.com/googleapis/google-auth-library-nodejs/issues/887)) ([a98e386](https://www.github.com/googleapis/google-auth-library-nodejs/commit/a98e38678dc4a5e963356378c75c658e36dccd01)) | ||
### Bug Fixes | ||
* **docs:** correct links in README ([f6a3194](https://www.github.com/googleapis/google-auth-library-nodejs/commit/f6a3194ff6df97d4fd833ae69ec80c05eab46e7b)), closes [#891](https://www.github.com/googleapis/google-auth-library-nodejs/issues/891) | ||
### [5.9.2](https://www.github.com/googleapis/google-auth-library-nodejs/compare/v5.9.1...v5.9.2) (2020-01-28) | ||
@@ -9,0 +21,0 @@ |
{ | ||
"name": "google-auth-library", | ||
"version": "5.9.2", | ||
"version": "5.10.0", | ||
"author": "Google Inc.", | ||
@@ -22,2 +22,3 @@ "description": "Google APIs Authentication Client Library for Node.js", | ||
"base64-js": "^1.3.0", | ||
"ecdsa-sig-formatter": "^1.0.11", | ||
"fast-text-encoding": "^1.0.0", | ||
@@ -36,3 +37,3 @@ "gaxios": "^2.1.0", | ||
"@types/lru-cache": "^5.0.0", | ||
"@types/mocha": "^5.2.1", | ||
"@types/mocha": "^7.0.0", | ||
"@types/mv": "^2.1.0", | ||
@@ -64,12 +65,11 @@ "@types/ncp": "^2.0.1", | ||
"keypair": "^1.0.1", | ||
"linkinator": "^1.5.0", | ||
"linkinator": "^2.0.0", | ||
"mocha": "^7.0.0", | ||
"mv": "^2.1.1", | ||
"ncp": "^2.0.0", | ||
"nock": "^11.3.2", | ||
"nock": "^12.0.0", | ||
"null-loader": "^3.0.0", | ||
"prettier": "^1.13.4", | ||
"puppeteer": "^2.0.0", | ||
"sinon": "^8.0.0", | ||
"source-map-support": "^0.5.6", | ||
"sinon": "^9.0.0", | ||
"tmp": "^0.1.0", | ||
@@ -101,5 +101,6 @@ "ts-loader": "^6.0.0", | ||
"docs-test": "linkinator docs", | ||
"predocs-test": "npm run docs" | ||
"predocs-test": "npm run docs", | ||
"prelint": "cd samples; npm link ../; npm i" | ||
}, | ||
"license": "Apache-2.0" | ||
} |
@@ -338,2 +338,3 @@ <img src="https://avatars0.githubusercontent.com/u/1342004?v=3&s=96" alt="Google Inc. logo" title="Google" align="right" height="96" width="96"/> | ||
## Working with ID Tokens | ||
### Fetching ID Tokens | ||
If your application is running behind Cloud Run, or using Cloud Identity-Aware | ||
@@ -362,2 +363,4 @@ Proxy (IAP), you will need to fetch an ID token to access your application. For | ||
A complete example can be found in [`samples/idtokens-cloudrun.js`](https://github.com/googleapis/google-auth-library-nodejs/blob/master/samples/idtokens-cloudrun.js). | ||
For invoking Cloud Identity-Aware Proxy, you will need to pass the Client ID | ||
@@ -382,4 +385,31 @@ used when you set up your protected resource as the target audience. | ||
See how to [secure your IAP app with signed headers](https://cloud.google.com/iap/docs/signed-headers-howto). | ||
A complete example can be found in [`samples/idtokens-iap.js`](https://github.com/googleapis/google-auth-library-nodejs/blob/master/samples/idtokens-iap.js). | ||
### Verifying ID Tokens | ||
If you've [secured your IAP app with signed headers](https://cloud.google.com/iap/docs/signed-headers-howto), | ||
you can use this library to verify the IAP header: | ||
```js | ||
const {OAuth2Client} = require('google-auth-library'); | ||
// Expected audience for App Engine. | ||
const expectedAudience = `/projects/your-project-number/apps/your-project-id`; | ||
// IAP issuer | ||
const issuers = ['https://cloud.google.com/iap']; | ||
// Verify the token. OAuth2Client throws an Error if verification fails | ||
const oAuth2Client = new OAuth2Client(); | ||
const response = await oAuth2Client.getIapCerts(); | ||
const ticket = await oAuth2Client.verifySignedJwtWithCertsAsync( | ||
idToken, | ||
response.pubkeys, | ||
expectedAudience, | ||
issuers | ||
); | ||
// Print out the info contained in the IAP ID token | ||
console.log(ticket) | ||
``` | ||
A complete example can be found in [`samples/verifyIdToken-iap.js`](https://github.com/googleapis/google-auth-library-nodejs/blob/master/samples/verifyIdToken-iap.js). | ||
## Questions/problems? | ||
@@ -386,0 +416,0 @@ |
228937
1.71%46
-2.13%4142
1.27%443
7.26%9
12.5%+ Added