Skip to content

Commit 3fa0aa3

Browse files
Eric Koledasqrrrl
authored andcommitted
Add support for additional JWT claims (#180)
* Add support for additional JWT claims. * Add IAP Service Acount sample, and update a few others
1 parent 6802ca5 commit 3fa0aa3

File tree

4 files changed

+104
-6
lines changed

4 files changed

+104
-6
lines changed

samples/CloudIAPServiceAccount.gs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* This sample demonstrates how to connect to an application protected by Google
3+
* Cloud's Identity-Aware Proxy (IAP), using a service account.
4+
* @see https://cloud.google.com/iap/docs/authentication-howto#authenticating_from_a_service_account
5+
*/
6+
7+
// A client ID and secret created for this script. It must be in the same Cloud
8+
// Console project as the IAP-secured application.
9+
var PRIVATE_KEY =
10+
'-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n';
11+
var CLIENT_EMAIL = '...';
12+
13+
// The OAuth client created automatically when you enabled IAP on your
14+
// applicaiton. Can be found by clicking "Edit OAuth Client" in the IAP
15+
// interface.
16+
var IAP_CLIENT_ID = '...';
17+
18+
// A URL endpoint for your IAP-secured application.
19+
var IAP_URL = '...';
20+
21+
/**
22+
* Authorizes and makes a request to an endpoint protected by the Cloud
23+
* Identity-Aware Proxy.
24+
*/
25+
function run() {
26+
var service = getService();
27+
if (service.hasAccess()) {
28+
var response = UrlFetchApp.fetch(IAP_URL, {
29+
headers: {
30+
// As per the IAP documentation, use the id_token, not the access_token,
31+
// to authorize the request.
32+
Authorization: 'Bearer ' + service.getToken().id_token
33+
}
34+
});
35+
var result = response.getContentText();
36+
Logger.log(JSON.stringify(result, null, 2));
37+
} else {
38+
Logger.log(service.getLastError());
39+
}
40+
}
41+
42+
/**
43+
* Reset the authorization state, so that it can be re-tested.
44+
*/
45+
function reset() {
46+
getService().reset();
47+
}
48+
49+
/**
50+
* Configures the service.
51+
*/
52+
function getService() {
53+
return OAuth2.createService('CloudIAPServiceAccount')
54+
// Set the endpoint URL.
55+
.setTokenUrl('https://accounts.google.com/o/oauth2/token')
56+
57+
// Set the private key and issuer.
58+
.setPrivateKey(PRIVATE_KEY)
59+
.setIssuer(CLIENT_EMAIL)
60+
.setAdditionalClaims({
61+
target_audience: IAP_CLIENT_ID
62+
})
63+
64+
// Set the property store where authorized tokens should be persisted.
65+
.setPropertyStore(PropertiesService.getScriptProperties());
66+
}
Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1+
/*
2+
* This sample demonstrates how to configure the library for Google APIs, using
3+
* end-user authorization (Web Server flow).
4+
* https://developers.google.com/identity/protocols/OAuth2WebServer
5+
*/
6+
17
var CLIENT_ID = '...';
28
var CLIENT_SECRET = '...';
39

410
/**
5-
* Authorizes and makes a request to the Google+ API.
11+
* Authorizes and makes a request to the Google Drive API.
612
*/
713
function run() {
814
var service = getService();
915
if (service.hasAccess()) {
10-
var url = 'https://www.googleapis.com/plus/v1/people/me';
16+
var url = 'https://www.googleapis.com/drive/v3/files?pageSize=1';
1117
var response = UrlFetchApp.fetch(url, {
1218
headers: {
1319
Authorization: 'Bearer ' + service.getAccessToken()
@@ -33,7 +39,7 @@ function reset() {
3339
* Configures the service.
3440
*/
3541
function getService() {
36-
return OAuth2.createService('GooglePlus')
42+
return OAuth2.createService('Google')
3743
// Set the endpoint URLs.
3844
.setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
3945
.setTokenUrl('https://accounts.google.com/o/oauth2/token')
@@ -50,7 +56,7 @@ function getService() {
5056
.setPropertyStore(PropertiesService.getUserProperties())
5157

5258
// Set the scope and additional Google-specific parameters.
53-
.setScope('profile')
59+
.setScope('https://www.googleapis.com/auth/drive')
5460
.setParam('access_type', 'offline')
5561
.setParam('approval_prompt', 'force')
5662
.setParam('login_hint', Session.getActiveUser().getEmail());

samples/GoogleServiceAccount.gs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
1+
/*
2+
* This sample demonstrates how to configure the library for Google APIs, using
3+
* domain-wide delegation (Service Account flow).
4+
* https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority
5+
*/
6+
7+
// Private key and client email of the service account.
18
var PRIVATE_KEY =
29
'-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n';
310
var CLIENT_EMAIL = '...';
11+
12+
// Email address of the user to impersonate.
413
var USER_EMAIL = '...';
514

615
/**
7-
* Authorizes and makes a request to the Google+ API.
16+
* Authorizes and makes a request to the Google Drive API.
817
*/
918
function run() {
1019
var service = getService();
1120
if (service.hasAccess()) {
12-
var url = 'https://www.googleapis.com/drive/v2/files?pageSize=1';
21+
var url = 'https://www.googleapis.com/drive/v3/files?pageSize=1';
1322
var response = UrlFetchApp.fetch(url, {
1423
headers: {
1524
Authorization: 'Bearer ' + service.getAccessToken()

src/Service.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,17 @@ Service_.prototype.setIssuer = function(issuer) {
265265
return this;
266266
};
267267

268+
/**
269+
* Sets additional JWT claims to use for Service Account authorization.
270+
* @param {Object.<string,string>} additionalClaims The additional claims, as
271+
* key-value pairs.
272+
* @return {Service_} This service, for chaining.
273+
*/
274+
Service_.prototype.setAdditionalClaims = function(additionalClaims) {
275+
this.additionalClaims_ = additionalClaims;
276+
return this;
277+
};
278+
268279
/**
269280
* Sets the subject (sub) value to use for Service Account authorization.
270281
* @param {string} subject This subject value
@@ -696,6 +707,12 @@ Service_.prototype.createJwt_ = function() {
696707
if (this.params_.scope) {
697708
claimSet.scope = this.params_.scope;
698709
}
710+
if (this.additionalClaims_) {
711+
var additionalClaims = this.additionalClaims_;
712+
Object.keys(additionalClaims).forEach(function(key) {
713+
claimSet[key] = additionalClaims[key];
714+
});
715+
}
699716
var toSign = Utilities.base64EncodeWebSafe(JSON.stringify(header)) + '.' +
700717
Utilities.base64EncodeWebSafe(JSON.stringify(claimSet));
701718
var signatureBytes =

0 commit comments

Comments
 (0)