公開前サービスの最終テストをしたいときなどは、本番と同じドメインで、Basic認証やDigest認証をかけたいことがある。セキュリティというよりは、正常に動作することを確認するため。また、Cookieを使った認証などとは別に動くので都合がよいことが多い。
ということで、Lambda@EdgeでBasic認証をした。何番煎じか分からないが、記録として残しておく。
コード
'use strict';
const BASICAUTH_USERNAME = 'username';
const BASICAUTH_PASSWORD = 'password';
const ENCODED_STRING = new Buffer(`${BASICAUTH_USERNAME}:${BASICAUTH_PASSWORD}`).toString('base64');
const AUTH_STRING = `Basic ${ENCODED_STRING}`;
const AUTH_REQUIRED_RESPONSE = {
body: '<h1>Authorization Required</h1>',
bodyEncoding: 'text',
headers: {
'www-authenticate': [{
key: 'WWW-Authenticate',
value: 'Basic realm="Authorization Required"'
}],
},
status: '401',
statusDescription: 'Authorization Required'
};
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request;
const authorization = request.headers.authorization ? request.headers.authorization[0].value : null;
if ((!authorization) || (authorization != AUTH_STRING)) {
callback(null, AUTH_REQUIRED_RESPONSE);
} else {
callback(null, request);
}
};
動作概要
- Lambda@Edgeでは、ふつうのLambdaと違って環境変数が利用できない。ということで、ユーザ名とパスワードがべた書きになっている。コードを管理するときは、CodeBuildでも使って環境変数に指定したユーザ名、パスワードを書き込むといった感じにするとよい
- Basic認証は
{ユーザ名}:{パスワード}
をBase64エンコードした文字列がAuthorization: Basic <エンコードした文字列>
と送信される。ヘッダが存在し、かつ文字列が一致するときは、何もせず、それ以外のときは、401 Authorization Required
のレスポンスを返却する