Reputation: 20304
I have a problem authenticating a REST request to Google APIs. Usually, Google have client packages that do it for you.
Now, I am using Document Translation service, which is still in preview, so I can not use the package. Docs are really confusing when it comes to authenticating a REST request. When I am using a package, I am giving it a JSON credentials file with this template:
{
"type": "xxx",
"project_id": "xxx",
"private_key_id": "xxx",
"private_key": "xxx",
"client_email": "xxx",
"client_id": "xxx",
"auth_uri": "xxx",
"token_uri": "xxx",
"auth_provider_x509_cert_url": "xxx",
"client_x509_cert_url": "xxx"
}
Can I send a REST request and just use some of this data to authenticate, just like when I use the client packages? I saw in a few places that I should generate a token with this data and use a token to authenticate. Do I need to generate and use a token? If yes, how to create a token in NodeJS?
Upvotes: 0
Views: 483
Reputation: 201378
I believe your current situation and your goal as follows.
I think that it's yes.
I think that it's yes. In order to use Google APIs using the service account, it is required to retrieve the access token using the service account. The sample script for retrieving the access token from the service account without googleapis for Node.js is as follows.
In this case, 2 libraries of crypto
and request
are used. And, please set privateKey
and clientEmail
. This script is from this post.
const cryptor = require('crypto');
const request = require('request');
const privateKey = "-----BEGIN PRIVATE KEY-----\n###-----END PRIVATE KEY-----\n"; // private_key of JSON file retrieved by creating Service Account
const clientEmail = "###"; // client_email of JSON file retrieved by creating Service Account
const scopes = ["https://www.googleapis.com/auth/drive.readonly"]; // Sample scope
const url = "https://www.googleapis.com/oauth2/v4/token";
const header = {
alg: "RS256",
typ: "JWT",
};
const now = Math.floor(Date.now() / 1000);
const claim = {
iss: clientEmail,
scope: scopes.join(" "),
aud: url,
exp: (now + 3600).toString(),
iat: now.toString(),
};
const signature = Buffer.from(JSON.stringify(header)).toString('base64') + "." + Buffer.from(JSON.stringify(claim)).toString('base64');
var sign = cryptor.createSign('RSA-SHA256');
sign.update(signature);
const jwt = signature + "." + sign.sign(privateKey, 'base64');
request({
method: "post",
url: url,
body: JSON.stringify({
assertion: jwt,
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
}),
}, (err, res, body) => {
if (err) {
console.log(err);
return;
}
console.log(body);
});
https://www.googleapis.com/auth/drive.readonly
is used. About this, please modify the scopes for your actual situation.When above script is run, the following value is returned. You can use the access token from this value and can use the Google APIs using this access token.
{
"access_token":"###",
"expires_in":3599,
"token_type":"Bearer"
}
Upvotes: 1