前回のブログ
Lambda(Node.js)でLINEユーザープロフィールを取得する
今回はLINE認証トークンを無効化させるログアウト機能を紹介します。
全体的な流れ
ユーザープロフィールを表示
まずはおさらいも兼ねてユーザープロフィールを表示してみます。
前回使用したLambda関数を次のように変更してください。
var request = require('request'); exports.handler = async(event) => { var access_token; //LINE認証ページからはcodeが来るので、LINEの認証APIでトークンを取得 if (event.queryStringParameters.code) { var token = await postRequest( 'https://api.line.me/oauth2/v2.1/token', { 'grant_type': 'authorization_code', 'code': event.queryStringParameters.code, 'redirect_uri': '<API GatewayのURL>', 'client_id': '<Channel ID>', 'client_secret': '<Channel Secret>' } ); var tokenBody = JSON.parse(token.httpResponse.body); access_token = tokenBody.access_token; } //ユーザープロフィール取得 var profile = await getRequest( 'https://api.line.me/v2/profile', { 'auth': { 'bearer': access_token } } ); var profileBody = JSON.parse(profile.httpResponse.body); const response = { statusCode: 200, headers: { 'content-type': 'text/html; charset=utf-8' }, body: `<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>Login</title> </head> <body> <h3>access_token</h3> <p>${access_token}</p> <h3>pictureUrl</h3> <img src="${profileBody.pictureUrl}" style="width:100px"/> </body> </html> ` }; return response; }; var postRequest = (url, form) => { return new Promise((resolve) => { request.post({ url: url, form: form }, (err, httpResponse, body) => { resolve({ err: err, httpResponse: httpResponse, body: body }); } ); }); }; var getRequest = (url, header) => { return new Promise((resolve) => { request.get( url, header, (err, httpResponse, body) => { resolve({ err: err, httpResponse: httpResponse, body: body }); } ); }); };
"code"からトークンを作成し、ユーザープロフィールを取得しています。
動作を確認してみましょう
再読み込みする
トークンが生きている間は、何度でもユーザープロフィールを取得することができます。
Lambdaを変更して実際にやってみましょう。
var request = require('request'); exports.handler = async(event) => { var access_token; //LINE認証ページからはcodeが来るので、LINEの認証APIでトークンを取得 if (event.queryStringParameters.code) { var token = await postRequest( 'https://api.line.me/oauth2/v2.1/token', { 'grant_type': 'authorization_code', 'code': event.queryStringParameters.code, 'redirect_uri': '<API GatewayのURL>', 'client_id': '<Channel ID>', 'client_secret': '<Channel Secret>' } ); var tokenBody = JSON.parse(token.httpResponse.body); access_token = tokenBody.access_token; } //再読み込み時はトークンを使い回す if (event.queryStringParameters.access_token) { access_token = event.queryStringParameters.access_token; } //ユーザープロフィール取得 var profile = await getRequest( 'https://api.line.me/v2/profile', { 'auth': { 'bearer': access_token } } ); var profileBody = JSON.parse(profile.httpResponse.body); const response = { statusCode: 200, headers: { 'content-type': 'text/html; charset=utf-8' }, body: `<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>Login</title> </head> <body> <h3>access_token</h3> <p>${access_token}</p> <h3>pictureUrl</h3> <img src="${profileBody.pictureUrl}" style="width:100px"/> <a href="<API GatewayのURL>?access_token=${access_token}">再読み込み</a> </body> </html> ` }; return response; }; var postRequest = (url, form) => { return new Promise((resolve) => { request.post({ url: url, form: form }, (err, httpResponse, body) => { resolve({ err: err, httpResponse: httpResponse, body: body }); } ); }); }; var getRequest = (url, header) => { return new Promise((resolve) => { request.get( url, header, (err, httpResponse, body) => { resolve({ err: err, httpResponse: httpResponse, body: body }); } ); }); };
次の2つ、コードを追加しました。
URLパラメーターにトークンを乗せて画面を開き直すリンクを追加
<a href="<API GatewayのURL>?access_token=${access_token}">再読み込み</a>
URLパラメーターのトークンを使ってユーザープロフィールを取得できる処理を追加
//再読み込み時はトークンを使い回す if (event.queryStringParameters.access_token) { access_token = event.queryStringParameters.access_token; }
動きを見てみましょう。
再読み込みを押して画面を開き直してもユーザープロフィールが取れていることが確認できます。
ログアウトを行う
ではいよいよログアウトを実装してみましょう。
var request = require('request'); exports.handler = async(event) => { var access_token; //LINE認証ページからはcodeが来るので、LINEの認証APIでトークンを取得 if (event.queryStringParameters.code) { var token = await postRequest( 'https://api.line.me/oauth2/v2.1/token', { 'grant_type': 'authorization_code', 'code': event.queryStringParameters.code, 'redirect_uri': '<API GatewayのURL>', 'client_id': '<Channel ID>', 'client_secret': '<Channel Secret>' } ); var tokenBody = JSON.parse(token.httpResponse.body); access_token = tokenBody.access_token; } //再読み込み時はトークンを使い回す if (event.queryStringParameters.access_token) { access_token = event.queryStringParameters.access_token; } //ログアウトの時はトークンを使ってログアウトする if (event.queryStringParameters.logout_token) { access_token = event.queryStringParameters.logout_token; var profile = await postRequest( 'https://api.line.me/oauth2/v2.1/revoke', { 'access_token': access_token, 'client_id': '<Channel ID>', 'client_secret': '<Channel Secret>' } ); } //ユーザープロフィール取得 var profile = await getRequest( 'https://api.line.me/v2/profile', { 'auth': { 'bearer': access_token } } ); var profileBody = JSON.parse(profile.httpResponse.body); const response = { statusCode: 200, headers: { 'content-type': 'text/html; charset=utf-8' }, body: `<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>Login</title> </head> <body> <h3>access_token</h3> <p>${access_token}</p> <h3>pictureUrl</h3> <img src="${profileBody.pictureUrl}" style="width:100px"/> <h3>message</h3> <p>${profileBody.message}</p> <a href="<API GatewayのURL>?access_token=${access_token}">再読み込み</a> <a href="<API GatewayのURL>?logout_token=${access_token}">ログアウト</a> </body> </html> ` }; return response; }; var postRequest = (url, form) => { return new Promise((resolve) => { request.post({ url: url, form: form }, (err, httpResponse, body) => { resolve({ err: err, httpResponse: httpResponse, body: body }); } ); }); }; var getRequest = (url, header) => { return new Promise((resolve) => { request.get( url, header, (err, httpResponse, body) => { resolve({ err: err, httpResponse: httpResponse, body: body }); } ); }); };
追加したコードは3つです。
ログアウトのリンクを追加し、リンクが押されるとトークンをURLパラメータに設定して画面を再読み込みします。
<a href="<API GatewayのURL>?logout_token=${access_token}">ログアウト</a>
//ログアウトの時はトークンを使ってログアウトする if (event.queryStringParameters.logout_token) { access_token = event.queryStringParameters.logout_token; var profile = await postRequest( 'https://api.line.me/oauth2/v2.1/revoke', { 'access_token': access_token, 'client_id': '<Channel ID>', 'client_secret': '<Channel Secret>' } ); }
ユーザープロフィールの取得に失敗すると、失敗理由が"message"として返ってきますので表示するようにしました。
<h3>message</h3>
<p>${profileBody.message}</p>
動作を確認してみましょう。
ログアウトした後でユーザープロフィールの取得に失敗しています。
ログアウトAPIによってトークンが無効化されているのが確認できます。