Securing Cloud endpoints with Google id token

248 views
Skip to first unread message

ca...@engene.se

unread,
Dec 4, 2018, 2:49:38 AM12/4/18
to Google Cloud Endpoints
I'm having trouble securing my endpoints with a google-id-token. I'm writing in Nodejs and google does not have an example for node yet.
I'm not sure if the google_id_token I generate is correct or if the problem lies in the openapi.yaml
My openapi.yaml looks like this:
security:
- google_id_token: []
google_id_token:
authorizationUrl: ""
flow: implicit
type: oauth2
x-google-issuer: "https://accounts.google.com"
x-google-audiences: 'client-id'

Is this the right way to generate a google_id_token?
Calling nodeJS application:

const {JWT} = require('google-auth-library');
const keys = require('./auth.json');
const request = require('request');

async function main() {
const client = new JWT(
keys.client_email,
null,
keys.private_key,
);

const url = `https://www.googleapis.com/dns/v1/projects/${keys.project_id}`;
const res = await client.request({url});

const gToken = await client.createGToken();
console.log(gToken);
request({
headers: {
'Authorization': 'Bearer '+ gToken
},
method: 'GET'
}, function (err, res, body) {
console.log("ERROR: " + err );
console.log("TEST " + JSON.stringify(res));
});
}

main().catch(console.error);


Thankfull for any lead I can get!

Luke Garrison

unread,
Dec 4, 2018, 2:40:26 PM12/4/18
to ca...@engene.se, google-clou...@googlegroups.com
Hi, thanks for writing in. I'm not personally familiar enough with the Google-auth-library for nodejs to know if the JSON Web Tokens section is returning a JWT for the service account or an ID token for the service account. If that isn't working, you could try following the basic code flow to get a Google ID token from the Cloud Endpoints docs: https://cloud.google.com/endpoints/docs/openapi/service-account-authentication#using_a_google_id_token. The high level process is as follows:
  1. Create a JWT with an "iss" claim of your service account's email and an "aud" claim of "https://www.googleapis.com/oauth2/v4/token"
  2. Sign the JWT using the service account key
  3. Send the JWT to "https://www.googleapis.com/oauth2/v4/token"
  4. Extract the "id_token" from the response to #3
Before trying the above though, it is worth calling out that your openapi snippet above will not work as written since it is missing the "securityDefinitions" section. It should look like:

security:
- google_id_token: []
securityDefinitions:
google_id_token:
authorizationUrl: ""
flow: implicit
type: oauth2
x-google-issuer: "https://accounts.google.com"
x-google-audiences: 'client-id'

Also note that you don't need to specify the "x-google-jwks_uri" for Google ID tokens, so I would also recommend leaving that out of the spec just in case it is not the correct url.

-Luke

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-cloud-endpoints/3cf1d61b-64b7-462a-b8c5-403635ee99ab%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

ca...@engene.se

unread,
Dec 5, 2018, 2:31:29 AM12/5/18
to Google Cloud Endpoints
Thanks a lot for the thorough answer Luke!
I managed to generate a google_id_token in nodejs the way you described with help from the documentation. What I missed was to leave out the 'scope' part in the JWT signing and instead include 'target audience'. 
So in the end my JWT signing and google_id_token generation looks like this:

const jwt = require('jsonwebtoken'); // Auth0 JWT library
jwt.sign(
{
'iss': serviceAccount.client_email,
'sub': serviceAccount.client_email,
"target_audience": 'https://my_project_id.appspot.com',
'iat': issuedAt,
'exp': issuedAt + TOKEN_DURATION_IN_SECONDS,
},
serviceAccount.private_key,
{
algorithm: 'RS256',
header: {
'kid': serviceAccount.private_key_id,
'typ': 'JWT',
'alg': 'RS256',
},
}
);

const myJWT = issueJWT();
console.log(JSON.stringify(myJWT));

// Call to Google authorization server
request({
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: `grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=${myJWT}`,
method: 'POST'
}, function (err, res, body) {

const token = ((JSON.parse(res.body)).id_token);
console.log("Id_token: " + token);

request({
headers: {
'Authorization': `Bearer ${token}`
},
method: 'GET'
}, function (err, res, body) {

console.log(JSON.stringify(res));
})

})
Reply all
Reply to author
Forward
0 new messages