前回のブログ
Lambda(Node.js)でLINEユーザープロフィールを取得する
LINEログインで認証が完了するとアクセストークンが得られます。
そのアクセストークンを使用してユーザープロフィールを取得したりユーザーIDを取得したりするわけですが、アクセストークンは有効期間30日という制限があります。
基本的には31日目からは再ログインしてもらうことになるのですが、
40日目までなら再ログインしなくても新しいアクセストークンを得られます。
今回はその新しいアクセストークンを取得する方法をお伝えします。
まずはおさらい
LINEログインを行い、アクセストークン、リフレッシュトークン、ユーザープロフィールを表示する画面を作ってみましょう。
前回使用したLambda関数を次のように修正してください。
var request = require('request'); exports.handler = async(event) => { var access_token; var refresh_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; refresh_token = tokenBody.refresh_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>refresh_token</h3> <p>${refresh_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 }); } ); }); };
LINEログイン後、画面に”acceess_token”、”refresh_token”とユーザープロフィールのアイコンを表示しています。
トークンを更新する
トークンを更新する時は"refresh_token"を使用します。
Lambda関数を次のように変更してください。
var request = require('request'); exports.handler = async(event) => { var access_token; var refresh_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; refresh_token = tokenBody.refresh_token; } //リフレッシュの時はリフレッシュトークンを使ってアクセストークン更新 if (event.queryStringParameters.access_token) { var verify = await getRequest( 'https://api.line.me/oauth2/v2.1/verify?access_token=' + event.queryStringParameters.access_token ); var verifyBody = JSON.parse(verify.httpResponse.body); if (verifyBody.scope) { var token = await postRequest( 'https://api.line.me/oauth2/v2.1/token', { 'grant_type': 'refresh_token', 'refresh_token': event.queryStringParameters.refresh_token, 'client_id': '<Channel ID>', 'client_secret': '<Channel Secret>' } ); var tokenBody = JSON.parse(token.httpResponse.body); access_token = tokenBody.access_token; refresh_token = tokenBody.refresh_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>refresh_token</h3> <p>${refresh_token}</p> <h3>pictureUrl</h3> <img src="${profileBody.pictureUrl}" style="width:100px"/> <a href="<API GatewayのURL>?access_token=${access_token}&refresh_token=${refresh_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パラメータで"access_token"と"refresh_token"を渡しています。
<a href="<API GatewayのURL>?access_token=${access_token}&refresh_token=${refresh_token}">リフレッシュ</a>
アクセストークンを更新する処理
//リフレッシュの時はリフレッシュトークンを使ってアクセストークン更新 if (event.queryStringParameters.access_token) { var verify = await getRequest( 'https://api.line.me/oauth2/v2.1/verify?access_token=' + event.queryStringParameters.access_token ); var verifyBody = JSON.parse(verify.httpResponse.body); if (verifyBody.scope) { var token = await postRequest( 'https://api.line.me/oauth2/v2.1/token', { 'grant_type': 'refresh_token', 'refresh_token': event.queryStringParameters.refresh_token, 'client_id': '<Channel ID>', 'client_secret': '<Channel Secret>' } ); var tokenBody = JSON.parse(token.httpResponse.body); access_token = tokenBody.access_token; refresh_token = tokenBody.refresh_token; } }
まずはLINEトークン確認API"https://api.line.me/oauth2/v2.1/verify"にアクセストークンを渡して
このアクセストークンが本当に使える物なのかをチェックしています。
トークン発行から41日以上経った場合は、レスポンスにエラーメッセージが返ってきます。
続いてLINE認証API"https://api.line.me/oauth2/v2.1/token"に新しいアクセストークンを要求します。
URLを見れば分かりますが、これは最初に"code"から"access_token"を作ったAPIと同じ物になります。
「'grant_type': 'authorization_code'」を指定するとトークン更新モードになるようです。
実際の動きは次のようになります。