UNPKG

19.4 kBMarkdownView Raw
1<img src="https://avatars0.githubusercontent.com/u/1342004?v=3&s=96" alt="Google Inc. logo" title="Google" align="right" height="96" width="96"/>
2
3# Google Auth Library
4
5[![npm version][npmimg]][npm]
6[![codecov][codecov-image]][codecov-url]
7[![Dependencies][david-dm-img]][david-dm]
8[![Known Vulnerabilities][snyk-image]][snyk-url]
9
10This is Google's officially supported [node.js][node] client library for using OAuth 2.0 authorization and authentication with Google APIs.
11
12## Installation
13This library is distributed on `npm`. To add it as a dependency, run the following command:
14
15``` sh
16$ npm install google-auth-library
17```
18
19## Ways to authenticate
20This library provides a variety of ways to authenticate to your Google services.
21- [Application Default Credentials](#choosing-the-correct-credential-type-automatically) - Use Application Default Credentials when you use a single identity for all users in your application. Especially useful for applications running on Google Cloud.
22- [OAuth 2](#oauth2) - Use OAuth2 when you need to perform actions on behalf of the end user.
23- [JSON Web Tokens](#json-web-tokens) - Use JWT when you are using a single identity for all users. Especially useful for server->server or server->API communication.
24- [Google Compute](#compute) - Directly use a service account on Google Cloud Platform. Useful for server->server or server->API communication.
25
26## Application Default Credentials
27This library provides an implementation of [Application Default Credentials][] for Node.js. The [Application Default Credentials][] provide a simple way to get authorization credentials for use in calling Google APIs.
28
29They are best suited for cases when the call needs to have the same identity and authorization level for the application independent of the user. This is the recommended approach to authorize calls to Cloud APIs, particularly when you're building an application that uses Google Cloud Platform.
30
31#### Download your Service Account Credentials JSON file
32
33To use Application Default Credentials, You first need to download a set of JSON credentials for your project. Go to **APIs & Auth** > **Credentials** in the [Google Developers Console][devconsole] and select **Service account** from the **Add credentials** dropdown.
34
35> This file is your *only copy* of these credentials. It should never be
36> committed with your source code, and should be stored securely.
37
38Once downloaded, store the path to this file in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable.
39
40#### Enable the API you want to use
41
42Before making your API call, you must be sure the API you're calling has been enabled. Go to **APIs & Auth** > **APIs** in the [Google Developers Console][devconsole] and enable the APIs you'd like to call. For the example below, you must enable the `DNS API`.
43
44
45#### Choosing the correct credential type automatically
46
47Rather than manually creating an OAuth2 client, JWT client, or Compute client, the auth library can create the correct credential type for you, depending upon the environment your code is running under.
48
49For example, a JWT auth client will be created when your code is running on your local developer machine, and a Compute client will be created when the same code is running on Google Cloud Platform. If you need a specific set of scopes, you can pass those in the form of a string or an array to the `GoogleAuth` constructor.
50
51The code below shows how to retrieve a default credential type, depending upon the runtime environment.
52
53```js
54const {GoogleAuth} = require('google-auth-library');
55
56/**
57 * Instead of specifying the type of client you'd like to use (JWT, OAuth2, etc)
58 * this library will automatically choose the right client based on the environment.
59 */
60async function main() {
61 const auth = new GoogleAuth({
62 scopes: 'https://www.googleapis.com/auth/cloud-platform'
63 });
64 const client = await auth.getClient();
65 const projectId = await auth.getProjectId();
66 const url = `https://dns.googleapis.com/dns/v1/projects/${projectId}`;
67 const res = await client.request({ url });
68 console.log(res.data);
69}
70
71main().catch(console.error);
72```
73
74## OAuth2
75
76This library comes with an [OAuth2][oauth] client that allows you to retrieve an access token and refreshes the token and retry the request seamlessly if you also provide an `expiry_date` and the token is expired. The basics of Google's OAuth2 implementation is explained on [Google Authorization and Authentication documentation][authdocs].
77
78In the following examples, you may need a `CLIENT_ID`, `CLIENT_SECRET` and `REDIRECT_URL`. You can find these pieces of information by going to the [Developer Console][devconsole], clicking your project > APIs & auth > credentials.
79
80For more information about OAuth2 and how it works, [see here][oauth].
81
82#### A complete OAuth2 example
83
84Let's take a look at a complete example.
85
86``` js
87const {OAuth2Client} = require('google-auth-library');
88const http = require('http');
89const url = require('url');
90const open = require('open');
91const destroyer = require('server-destroy');
92
93// Download your OAuth2 configuration from the Google
94const keys = require('./oauth2.keys.json');
95
96/**
97 * Start by acquiring a pre-authenticated oAuth2 client.
98 */
99async function main() {
100 const oAuth2Client = await getAuthenticatedClient();
101 // Make a simple request to the People API using our pre-authenticated client. The `request()` method
102 // takes an GaxiosOptions object. Visit https://github.com/JustinBeckwith/gaxios.
103 const url = 'https://people.googleapis.com/v1/people/me?personFields=names';
104 const res = await oAuth2Client.request({url});
105 console.log(res.data);
106
107 // After acquiring an access_token, you may want to check on the audience, expiration,
108 // or original scopes requested. You can do that with the `getTokenInfo` method.
109 const tokenInfo = await oAuth2Client.getTokenInfo(
110 oAuth2Client.credentials.access_token
111 );
112 console.log(tokenInfo);
113}
114
115/**
116 * Create a new OAuth2Client, and go through the OAuth2 content
117 * workflow. Return the full client to the callback.
118 */
119function getAuthenticatedClient() {
120 return new Promise((resolve, reject) => {
121 // create an oAuth client to authorize the API call. Secrets are kept in a `keys.json` file,
122 // which should be downloaded from the Google Developers Console.
123 const oAuth2Client = new OAuth2Client(
124 keys.web.client_id,
125 keys.web.client_secret,
126 keys.web.redirect_uris[0]
127 );
128
129 // Generate the url that will be used for the consent dialog.
130 const authorizeUrl = oAuth2Client.generateAuthUrl({
131 access_type: 'offline',
132 scope: 'https://www.googleapis.com/auth/userinfo.profile',
133 });
134
135 // Open an http server to accept the oauth callback. In this simple example, the
136 // only request to our webserver is to /oauth2callback?code=<code>
137 const server = http
138 .createServer(async (req, res) => {
139 try {
140 if (req.url.indexOf('/oauth2callback') > -1) {
141 // acquire the code from the querystring, and close the web server.
142 const qs = new url.URL(req.url, 'http://localhost:3000')
143 .searchParams;
144 const code = qs.get('code');
145 console.log(`Code is ${code}`);
146 res.end('Authentication successful! Please return to the console.');
147 server.destroy();
148
149 // Now that we have the code, use that to acquire tokens.
150 const r = await oAuth2Client.getToken(code);
151 // Make sure to set the credentials on the OAuth2 client.
152 oAuth2Client.setCredentials(r.tokens);
153 console.info('Tokens acquired.');
154 resolve(oAuth2Client);
155 }
156 } catch (e) {
157 reject(e);
158 }
159 })
160 .listen(3000, () => {
161 // open the browser to the authorize url to start the workflow
162 open(authorizeUrl, {wait: false}).then(cp => cp.unref());
163 });
164 destroyer(server);
165 });
166}
167
168main().catch(console.error);
169```
170
171#### Handling token events
172
173This library will automatically obtain an `access_token`, and automatically refresh the `access_token` if a `refresh_token` is present. The `refresh_token` is only returned on the [first authorization](https://github.com/googleapis/google-api-nodejs-client/issues/750#issuecomment-304521450), so if you want to make sure you store it safely. An easy way to make sure you always store the most recent tokens is to use the `tokens` event:
174
175```js
176const client = await auth.getClient();
177
178client.on('tokens', (tokens) => {
179 if (tokens.refresh_token) {
180 // store the refresh_token in my database!
181 console.log(tokens.refresh_token);
182 }
183 console.log(tokens.access_token);
184});
185
186const url = `https://dns.googleapis.com/dns/v1/projects/${projectId}`;
187const res = await client.request({ url });
188// The `tokens` event would now be raised if this was the first request
189```
190
191#### Retrieve access token
192With the code returned, you can ask for an access token as shown below:
193
194``` js
195const tokens = await oauth2Client.getToken(code);
196// Now tokens contains an access_token and an optional refresh_token. Save them.
197oauth2Client.setCredentials(tokens);
198```
199
200#### Obtaining a new Refresh Token
201If you need to obtain a new `refresh_token`, ensure the call to `generateAuthUrl` sets the `access_type` to `offline`. The refresh token will only be returned for the first authorization by the user. To force consent, set the `prompt` property to `consent`:
202
203```js
204// Generate the url that will be used for the consent dialog.
205const authorizeUrl = oAuth2Client.generateAuthUrl({
206 // To get a refresh token, you MUST set access_type to `offline`.
207 access_type: 'offline',
208 // set the appropriate scopes
209 scope: 'https://www.googleapis.com/auth/userinfo.profile',
210 // A refresh token is only returned the first time the user
211 // consents to providing access. For illustration purposes,
212 // setting the prompt to 'consent' will force this consent
213 // every time, forcing a refresh_token to be returned.
214 prompt: 'consent'
215});
216```
217
218#### Checking `access_token` information
219After obtaining and storing an `access_token`, at a later time you may want to go check the expiration date,
220original scopes, or audience for the token. To get the token info, you can use the `getTokenInfo` method:
221
222```js
223// after acquiring an oAuth2Client...
224const tokenInfo = await oAuth2Client.getTokenInfo('my-access-token');
225
226// take a look at the scopes originally provisioned for the access token
227console.log(tokenInfo.scopes);
228```
229
230This method will throw if the token is invalid.
231
232#### OAuth2 with Installed Apps (Electron)
233If you're authenticating with OAuth2 from an installed application (like Electron), you may not want to embed your `client_secret` inside of the application sources. To work around this restriction, you can choose the `iOS` application type when creating your OAuth2 credentials in the [Google Developers console][devconsole]:
234
235![application type][apptype]
236
237If using the `iOS` type, when creating the OAuth2 client you won't need to pass a `client_secret` into the constructor:
238```js
239const oAuth2Client = new OAuth2Client({
240 clientId: <your_client_id>,
241 redirectUri: <your_redirect_uri>
242});
243```
244
245## JSON Web Tokens
246The Google Developers Console provides a `.json` file that you can use to configure a JWT auth client and authenticate your requests, for example when using a service account.
247
248``` js
249const {JWT} = require('google-auth-library');
250const keys = require('./jwt.keys.json');
251
252async function main() {
253 const client = new JWT({
254 email: keys.client_email,
255 key: keys.private_key,
256 scopes: ['https://www.googleapis.com/auth/cloud-platform'],
257 });
258 const url = `https://dns.googleapis.com/dns/v1/projects/${keys.project_id}`;
259 const res = await client.request({url});
260 console.log(res.data);
261}
262
263main().catch(console.error);
264```
265
266The parameters for the JWT auth client including how to use it with a `.pem` file are explained in [samples/jwt.js](https://github.com/googleapis/google-auth-library-nodejs/blob/master/samples/jwt.js).
267
268#### Loading credentials from environment variables
269Instead of loading credentials from a key file, you can also provide them using an environment variable and the `GoogleAuth.fromJSON()` method. This is particularly convenient for systems that deploy directly from source control (Heroku, App Engine, etc).
270
271Start by exporting your credentials:
272
273```
274$ export CREDS='{
275 "type": "service_account",
276 "project_id": "your-project-id",
277 "private_key_id": "your-private-key-id",
278 "private_key": "your-private-key",
279 "client_email": "your-client-email",
280 "client_id": "your-client-id",
281 "auth_uri": "https://accounts.google.com/o/oauth2/auth",
282 "token_uri": "https://accounts.google.com/o/oauth2/token",
283 "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
284 "client_x509_cert_url": "your-cert-url"
285}'
286```
287Now you can create a new client from the credentials:
288
289```js
290const {auth} = require('google-auth-library');
291
292// load the environment variable with our keys
293const keysEnvVar = process.env['CREDS'];
294if (!keysEnvVar) {
295 throw new Error('The $CREDS environment variable was not found!');
296}
297const keys = JSON.parse(keysEnvVar);
298
299async function main() {
300 // load the JWT or UserRefreshClient from the keys
301 const client = auth.fromJSON(keys);
302 client.scopes = ['https://www.googleapis.com/auth/cloud-platform'];
303 const url = `https://dns.googleapis.com/dns/v1/projects/${keys.project_id}`;
304 const res = await client.request({url});
305 console.log(res.data);
306}
307
308main().catch(console.error);
309```
310
311#### Using a Proxy
312You can set the `HTTPS_PROXY` or `https_proxy` environment variables to proxy HTTPS requests. When `HTTPS_PROXY` or `https_proxy` are set, they will be used to proxy SSL requests that do not have an explicit proxy configuration option present.
313
314## Compute
315If your application is running on Google Cloud Platform, you can authenticate using the default service account or by specifying a specific service account.
316
317**Note**: In most cases, you will want to use [Application Default Credentials](#choosing-the-correct-credential-type-automatically). Direct use of the `Compute` class is for very specific scenarios.
318
319``` js
320const {auth, Compute} = require('google-auth-library');
321
322async function main() {
323 const client = new Compute({
324 // Specifying the service account email is optional.
325 serviceAccountEmail: 'my-service-account@example.com'
326 });
327 const projectId = await auth.getProjectId();
328 const url = `https://dns.googleapis.com/dns/v1/projects/${projectId}`;
329 const res = await client.request({url});
330 console.log(res.data);
331}
332
333main().catch(console.error);
334```
335
336## Working with ID Tokens
337### Fetching ID Tokens
338If your application is running on Cloud Run or Cloud Functions, or using Cloud Identity-Aware
339Proxy (IAP), you will need to fetch an ID token to access your application. For
340this, use the method `getIdTokenClient` on the `GoogleAuth` client.
341
342For invoking Cloud Run services, your service account will need the
343[`Cloud Run Invoker`](https://cloud.google.com/run/docs/authenticating/service-to-service)
344IAM permission.
345
346For invoking Cloud Functions, your service account will need the
347[`Function Invoker`](https://cloud.google.com/functions/docs/securing/authenticating#function-to-function)
348IAM permission.
349
350``` js
351// Make a request to a protected Cloud Run service.
352const {GoogleAuth} = require('google-auth-library');
353
354async function main() {
355 const url = 'https://cloud-run-1234-uc.a.run.app';
356 const auth = new GoogleAuth();
357 const client = await auth.getIdTokenClient(url);
358 const res = await client.request({url});
359 console.log(res.data);
360}
361
362main().catch(console.error);
363```
364
365A complete example can be found in [`samples/idtokens-serverless.js`](https://github.com/googleapis/google-auth-library-nodejs/blob/master/samples/idtokens-serverless.js).
366
367For invoking Cloud Identity-Aware Proxy, you will need to pass the Client ID
368used when you set up your protected resource as the target audience.
369
370``` js
371// Make a request to a protected Cloud Identity-Aware Proxy (IAP) resource
372const {GoogleAuth} = require('google-auth-library');
373
374async function main()
375 const targetAudience = 'iap-client-id';
376 const url = 'https://iap-url.com';
377 const auth = new GoogleAuth();
378 const client = await auth.getIdTokenClient(targetAudience);
379 const res = await client.request({url});
380 console.log(res.data);
381}
382
383main().catch(console.error);
384```
385
386A complete example can be found in [`samples/idtokens-iap.js`](https://github.com/googleapis/google-auth-library-nodejs/blob/master/samples/idtokens-iap.js).
387
388### Verifying ID Tokens
389
390If you've [secured your IAP app with signed headers](https://cloud.google.com/iap/docs/signed-headers-howto),
391you can use this library to verify the IAP header:
392
393```js
394const {OAuth2Client} = require('google-auth-library');
395// Expected audience for App Engine.
396const expectedAudience = `/projects/your-project-number/apps/your-project-id`;
397// IAP issuer
398const issuers = ['https://cloud.google.com/iap'];
399// Verify the token. OAuth2Client throws an Error if verification fails
400const oAuth2Client = new OAuth2Client();
401const response = await oAuth2Client.getIapCerts();
402const ticket = await oAuth2Client.verifySignedJwtWithCertsAsync(
403 idToken,
404 response.pubkeys,
405 expectedAudience,
406 issuers
407);
408
409// Print out the info contained in the IAP ID token
410console.log(ticket)
411```
412
413A complete example can be found in [`samples/verifyIdToken-iap.js`](https://github.com/googleapis/google-auth-library-nodejs/blob/master/samples/verifyIdToken-iap.js).
414
415## Questions/problems?
416
417* Ask your development related questions on [Stack Overflow][stackoverflow].
418* If you've found an bug/issue, please [file it on GitHub][bugs].
419
420## Contributing
421
422See [CONTRIBUTING][contributing].
423
424## License
425
426This library is licensed under Apache 2.0. Full license text is available in [LICENSE][copying].
427
428[Application Default Credentials]: https://cloud.google.com/docs/authentication/getting-started
429[apptype]: https://user-images.githubusercontent.com/534619/36553844-3f9a863c-17b2-11e8-904a-29f6cd5f807a.png
430[authdocs]: https://developers.google.com/accounts/docs/OAuth2Login
431[bugs]: https://github.com/googleapis/google-auth-library-nodejs/issues
432[codecov-image]: https://codecov.io/gh/googleapis/google-auth-library-nodejs/branch/master/graph/badge.svg
433[codecov-url]: https://codecov.io/gh/googleapis/google-auth-library-nodejs
434[contributing]: https://github.com/googleapis/google-auth-library-nodejs/blob/master/CONTRIBUTING.md
435[copying]: https://github.com/googleapis/google-auth-library-nodejs/tree/master/LICENSE
436[david-dm-img]: https://david-dm.org/googleapis/google-auth-library-nodejs/status.svg
437[david-dm]: https://david-dm.org/googleapis/google-auth-library-nodejs
438[node]: http://nodejs.org/
439[npmimg]: https://img.shields.io/npm/v/google-auth-library.svg
440[npm]: https://www.npmjs.org/package/google-auth-library
441[oauth]: https://developers.google.com/identity/protocols/OAuth2
442[snyk-image]: https://snyk.io/test/github/googleapis/google-auth-library-nodejs/badge.svg
443[snyk-url]: https://snyk.io/test/github/googleapis/google-auth-library-nodejs
444[stackoverflow]: http://stackoverflow.com/questions/tagged/google-auth-library-nodejs
445[devconsole]: https://console.cloud.google.com/