2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

LambdaにBasic認証を追加する方法とLINEからAndroidで開けない問題の対応方法

Last updated at Posted at 2019-02-08

タイトルそのままです。
LambdaにBasic認証を追加する方法とLINEのアプリ内ブラウザからアクセスした際に発生する問題の対処法について記載します。
Basic認証だけならググれば簡単に出てくるのですが、後半の対処に時間がかかったので同じような状況の方の助けになれば幸いです。

LambdaにBasic認証を追加する

lambdaのコードとしては以下のようになります。シンプルなので説明は簡単なコメントだけにしておきます。
自分の場合はこれをCloudFrontに設定してページにBasic認証をかけるために使用しました。

basic_auth.js
'use strict';

exports.handler = (event, context, callback) => {
    // リクエストヘッダーなど取得
    const request = event.Records[0].cf.request;
    const headers = request.headers;

    // IDとパスワード
    const basicAuthId = 'id' // ID
    const basicAuthPath = 'password' // パスワード
    // Construct the Basic Auth string
    const authString = 'Basic ' + new Buffer(basicAuthId + ':' + basicAuthPath).toString('base64');

    // basic認証
    if (typeof headers.authorization == 'undefined' || headers.authorization[0].value != authString) {
            const body = 'Unauthorized';
            const response = {
                status: '401',
                statusDescription: 'Unauthorized',
                body: body,
                headers: {
                    'www-authenticate': [{key: 'WWW-Authenticate', value:'Basic'}]
                },
            };
            callback(null, response);
    }
    // 通ったら処理を継続
    callback(null, request);
};

LINEのAndroidで発生するポップアップ出ない問題

一見これだけでOKそうに見えるのですが、上記の実装だと、AndroidのLINEで開こうとするとベーシック認証画面を出さずに「Unauthorized」となって終了してしまいます。
どうやらこれはLINEのアプリ内ブラウザはポップアップをブロックしていることが原因のようです。
(iosでは発生しない)

対処法

そこでlambda側でandroidの場合はchromeで開くように実装します

exports.handler = (event, context, callback) => {
    // リクエストヘッダーなど取得
    const request = event.Records[0].cf.request;
    const headers = request.headers;
    const userAgent = headers['user-agent'][0].value

    if(userAgent.match("Android") && userAgent.match('LINE')) { // userAgentチェック
        const response = {
            status: '302',
            statusDescription: 'Found',
            headers: {
                location: [{
                    key: 'Location',
                    value: 'googlechrome://navigate?url=https://' + request.uri, // googlechromeで開く
                }],
            },
        };
        callback(null, response);
    }
    ...
}

ポイントは2つで
まずこの部分でブラウザがAndroidであることとLINEで開いていることをチェックします。
(このあとchromeで開かせるのでLINEであることをチェックしないと無限ループしてえらいことになります笑)

if(userAgent.match("Android") && userAgent.match('Line')) { ... }

2つ目はchromeで開かせる箇所でこのように書くことで、urlschemeで端末にchromeで開かせることができます。
(因みにはじめからLINEに
googlechrome://navigate?url=https://google.co.jp
を貼り付けて開かせればよくね?と思って試したんですが、上記のように上手くパースされずクリックできる青リンクにならなかったです。)

googlechrome://navigate?url=https://google.co.jp // chromeでhttps://google.co.jpを開く

のように書くことでAndroid端末でchromeで開かせることができます。(chromeがない場合はchromeのダウンロードページに飛びます)

因みに今回は不要ですがiOSの場合はこんな感じです。

googlechromes://apple.co.jp

これでLINEのブラウザにも対応したBasic認証が完成しました。最終的なコードは以下のようになります。


'use strict';

exports.handler = (event, context, callback) => {
    // リクエストヘッダーなど取得
    const request = event.Records[0].cf.request;
    const headers = request.headers;
    const userAgent = headers['user-agent'][0].value
    const domain = 'awsome.app'
    if(userAgent.match("Android") && userAgent.match('Line')) {
        const response = {
            status: '302',
            statusDescription: 'Found',
            headers: {
                location: [{
                    key: 'Location',
                    value: `googlechrome://navigate?url=https:${domain}//refe.love${request.uri}`, // googlechromeで開く
                }],
            },
        };
        callback(null, response);
    }

    // IDとパスワード
    const basicAuthId = 'id' // ID
    const basicAuthPath = 'password' // パスワード
    // Construct the Basic Auth string
    const authString = 'Basic ' + new Buffer(basicAuthId + ':' + basicAuthPath).toString('base64');


    // basic認証
    if (typeof headers.authorization == 'undefined' || headers.authorization[0].value != authString) {
            const body = 'Unauthorized';
            const response = {
                status: '401',
                statusDescription: 'Unauthorized',
                body: body,
                headers: {
                    'www-authenticate': [{key: 'WWW-Authenticate', value:'Basic'}]
                },
            };
            callback(null, response);
    }
    // 通ったら処理を継続
    callback(null, request);
};

LINE以外のブラウザについても同じようなHeaderを送っていればuserAgentのロジック書き換えるだけで対応できるはずです。
おためしあれ :confetti_ball:

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?