Lambda(Node.js)でLINEログインのアクセストークンを更新する

前回のブログ

WebアプリにLINEログイン機能を組み込む

Lambda(Node.js)でLINEユーザープロフィールを取得する

Lambda(Node.js)でLINEログアウトを行う

xp-cloud.jp

xp-cloud.jp

xp-cloud.jp

 

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'」を指定するとトークン更新モードになるようです。

 

実際の動きは次のようになります。

 

 

 

アプリケーション開発バナー