Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

CloudFront Lamba@EdgeでBasic認証する

More than 3 years have passed since last update.

2017/8: GA版にあわせて書き直しました

CloudFront + S3オリジン構成の場合、Basic認証を使ったコンテンツ保護が出来ませんでしたが、Lambda@Edgeによって可能になりました。

下記の機能を提供しています。

  • 一部のパスだけを認証の対象にできる。この例では、パスにsecretが含まれるものだけが認証の対象です
  • Authorizationヘッダがなかった場合に401ではなく403を返すことで、ブラウザの認証ダイアログが表示される
  • 認証エラー時にBodyを返却する
  • 複数のクレデンシャルに対応している

今のバージョンは、クレデンシャルがそのままハードコードされてるので、ソースの取り扱いにご注意を。
パスワードはハッシュをかけた方が安全ですが、これはTODOとします。

'use strict';

exports.handler = (event, context, callback) => {
  const request = event.Records[0].cf.request;

  const errorContent = '\
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">\
<html><head>\
<title>401 Authorization Required</title>\
</head><body>\
<h1>Authorization Required</h1>\
<p>This server could not verify that you are authorized to access the document\
requested.  Either you supplied the wrong credentials (e.g., bad password), or your\
browser doesn\'t understand how to supply the credentials required.</p>\
</body></html>\
';

  const credentials = {
    'user1': 'pass1234',
    'user2': 'pass5678'
  }

  if (request.uri.match(/secret/i)) {
    var authorities = request.headers.Authorization || request.headers.authorization
    if (authorities) {
      let authorized = false;
      for (let user in credentials) {
        var secret = new Buffer(user + ':' + credentials[user]).toString('base64');
        for (var i = 0; i < authorities.length; i++) {
          if (authorities[i].value.split(" ")[1] === secret) {
            authorized = true;
          }
        }
      }
      if (authorized) {
        console.log("match: " + authorities);
        callback(null, request);
      } else {
        console.log("not match: " + authorities);
        callback(null, {status: '403', statusDescription: '403 Forbidden',
                        headers: {
                          'content-type': [ { key: 'Content-Type', value: 'text/html; charset=UTF-8' } ]
                        },
                        body: errorContent.toString('utf8')
                       });
      }
    } else {
      // Client did not send authorization
      callback(null, {status: '401', statusDescription: '401 Unauthorized',
                      headers: {
                        'www-authenticate': [{ key: 'WWW-Authenticate', value: 'Basic' }]
                      }
                     });
    }
  } else {
    console.log("do nothing");
    callback(null, request);
  }
}
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away