npmのgoogleapisパッケージを利用します。 https://github.com/googleapis/google-api-nodejs-client
const { google } = require('googleapis');
googleapisパッケージのauth
は、いくつかの認証方法を提供してくれます。
const OAuth2 = google.auth.OAuth2;
OAuth2クライアントの生成は次の通り。 予め、Google Cloud Platform上でOauth2クライアントを払い出しておく必要があります。
const oauth2Client = new OAuth2(
$YOUR_CLIENT_ID,
$YOUR_CLIENT_SECRET,
$YOUR_REDIRECT_URL
);
REDIRECT_URLに認可コード(Authorization code)つきのリクエストが走るので、REDIRECT_URLに指定したエンドポイントで必要なパラメータを取れるようにしておきましょう。
もし、それが難しい場合にはurn:ietf:wg:oauth:2.0:oob
を指定しておけば、ブラウザのタイトルバーに認可コードを返すことができます。
このoauth2client
は、いくつかの機能を持ちます。
例えば、特定のscopeに対するOAuth2認可の要求URLは次で生成できるようになっています。
const authorizeUrl = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: 'https://www.googleapis.com/auth/plus.me'
});
access_type
には、online
とoffline
が設定できますが、違いは次の通り。
- online ユーザがブラウザ上にいなければ、アクセストークンをリフレッシュすることができない。
- offline ユーザがブラウザ上にいなくても、アクセストークンをリフレッシュすることができる(=Refresh Tokenが使用できる)。サーバサイド向け。
scope
はアクセスするGoogle APIのscopeを設定します。
response_typeはcode
(RFC 6749)で、最初からアクセストークンを取得することはできません。
(token
(RFC 6749 Code Flow)は、アクセストークンが直接返ってくる方式です。設定できるのかな?)
また、その他のパラメータとして、prompt
やstatus
があります。
通常、Googleにおいては、リフレッシュトークンは一度しか返ってきません。
promptにconsent
を割り当てると、強制的に承認が必要になります。
status
は、何らかの値をクエリ形式で保持し続けるときに使います。転送先リソースの指定、CSRF軽減、nonceの保持などに使えます。
生成されたURLは、次のようになります。
https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=$YOUR_CLIENT_ID&redirect_uri=$YOUR_REDIRECT_URI&scope=$SCOPE&access_type=offline"
このURLにアクセスすると、302が返ってきて、リダイレクト先が認可画面となります。
エンドユーザーは、すでにGoogleで認証が完了している状態(セッションをもっている状態)で、このauthorizeUrl
にアクセスすることで、認可を行うことができます。
つまり、この方式は 必ず1度はユーザーによるブラウザ操作を必要になります。
認可が行われると、先のREDIRECT_URIに認可コードが返ってくるので、そのコードを保持しましょう。
コードを取得するHTTPサーバの例は、次のとおりです。
const http = require('http');
const querystring = require('querystring');
const opn = require('opn');
const server = http.createServer(async (req, res) => {
if (req.url.indexOf('/oauth2callback') > -1) {
// acquire the code from the querystring, and close the web server.
const qs = querystring.parse(url.parse(req.url).query);
console.log(`Code is ${qs.code}`);
res.end('Authentication successful! Please return to the console.');
server.close();
// Now that we have the code, use that to acquire tokens.
const r = await oAuth2Client.getToken(qs.code);
// Make sure to set the credentials on the OAuth2 client.
oAuth2Client.setCredentials(r.tokens);
console.info('Tokens acquired.');
resolve(oAuth2Client);
}
}).listen(3000, () => {
// open the browser to the authorize url to start the workflow
opn(authorizeUrl);
});
これで受け取ることができます。
コードからアクセストークンを取得するには
oauth2Client.getToken(code, (err,token) => {
// callback
});
となります。
oauth2Client.setCredentials({
refresh_token: $YOUR_REFRESH_TOKEN
});
これで予め設定することが出来ます。
auth.on('tokens', (tokens) => {
auth.setCredentials(tokens);
});
これで期限が切れたトークンの更新が行なえます。
Google APIsのパッケージは、このauthインスタンスをパラメータにわたすことで、容易に認証済みリクエストを利用することができます。
const drive = google.drive({
version: 'v3',
auth: oauth2Client
});
簡単ですね。
サービスアカウントとは、Google Cloud Platform内で作成することのできる実際のユーザではないアカウントです。 このサービスアカウントによるJWT(Json Web Token)方式の認証も使用することが出来ます。
OAuth2クライアントと同じく、Google Cloud Platformの画面からクライアントを払い出します。 client_id、メールアドレス、証明書フィンガープリント、そしてクレデンシャル(秘密鍵)が入ったJSONを得ることが出来ます。
const JWT = google.auth.JWT;
利用するときは、次のようになります。
const keys = require('./jwt.keys.json');
const jwtClient = new JWT(
keys.client_email,
null,
keys.private_key,
['https://www.googleapis.com/auth/cloud-platform'],
);
トークンを取得するには、
jwtClient.authorize((err, tokens) => {
// callback
});
認証情報は、こちらもインスタンスをパラメータにわたすだけです。
const drive = google.drive({
version: 'v3',
auth: jwtClient
});