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

前回のブログ

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

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

xp-cloud.jp

xp-cloud.jp

 

今回は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>

 

トークンを使ってLINEログアウトAPIを実行します。

 

//ログアウトの時はトークンを使ってログアウトする
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によってトークンが無効化されているのが確認できます。

 

 

 

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

 

AWS無料相談会