スポンサーリンク
AWSCloudFront

CloudFrontFunctionsでBasic認証/APIキー認証(リクエストヘッダー参照)

AWS

概要

CloudFrontFunctionsを利用して、クライアントからのリクエストに対してBasic認証やAPIKey認証(リクエストヘッダーを参照して突き合わせ)を実装する機会があったので、備忘録としてコードを残しておきます。

・CloudFrontFunctionsとは
CloudFrontディストリビューションへのアクセス時に、軽量のJavaScriptコードを実行する事が可能な仕組みです。

<公式の説明>

関数を使用してエッジでカスタマイズする - Amazon CloudFront
エッジ関数を使用して、Amazon CloudFront ディストリビューションをカスタマイズします。

構築手順

↓公式のリファレンスにそこそこ分かり易く記載されています。

※ザックリ書くとこんな感じです。(簡単!)

1.CloudFrontのページから「関数」選択

2.関数名を入力して、JavaScriptを記述→「変更を保存」

3.任意のディストリビューションに関連付け→「関数を発行」
 (初回だけ「関数を発行」してからディストリビューションに関連付け→「関数を発行」)

<公式のリファレンス>

チュートリアル: CloudFront Functions でシンプルな関数を作成する - Amazon CloudFront
このチュートリアルを完了すると、簡単な関数を作成して CloudFront Functions を使用できるようになります。

Basic認証

コード

var authUser = 'user'; // ユーザ名をべた書き
var authPass = 'pass'; // パスワードをべた書き

function handler(event) {
  // Basic Authenticate
  var request = event.request;
  var headers = request.headers;
  var authString = 'Basic ' + (authUser + ':' + authPass).toString('base64');

  if (
    typeof headers.authorization === "undefined" ||
    headers.authorization.value !== authString
  ) {
    return {
      statusCode: 401,
      statusDescription: "Unauthorized",
      headers: { "www-authenticate": { value: 'Basic realm="Message"' } }
    };
  }

  return request;
}

疎通確認

・curlからアクセス(以下はPOSTするケース)

$ curl -X POST --user user:pass https://<cloudfrontディストリビューションドメイン名>/xxx/yyy

・ブラウザからアクセス その1
↓のように下記URLへブラウザからアクセス

https://<cloudfrontディストリビューションドメイン名>/xxx/yyy

※コードにべた書きした「ユーザ名」と「パスワード」を入力して、「ログイン」を押下する事でアクセス可能

・ブラウザからアクセス その2
※URLに直接Basic認証情報を記述しておく方法

https://user:pass@<cloudfrontディストリビューションドメイン名>/xxx/yyy

APIキー認証(リクエストヘッダー参照)

コード

・リクエストヘッダー内の’xxx-api-key’に含まれる値で認証

var authApiKey = 'apikey'; // APIKeyをべた書き

function handler(event) {
  // ApiKey Authenticate
  var request = event.request;
  var headers = request.headers;

  if (
    headers['xxx-api-key'].value !== authApiKey
  ) {
    return {
      statusCode: 401,
      statusDescription: "Unauthorized",
    };
  }

  return request;
}

疎通確認

・curlからアクセス(以下はPOSTするケース)

$ curl -X POST -H "xxx-api-key:apikey" https://<cloudfrontディストリビューションドメイン名>/xxx/yyy

※その他Postmanなどのリクエストツールをご利用ください。

おまけ:リクエストパスで認証方法を分岐

コード

var authApiKey  = 'aaa';
var authBasicUser = 'bbb';
var authBasicPass = 'ccc';

function handler(event) {
  // Basic & APIKey Authenticate
  var request = event.request;
  var headers = request.headers;
  var uriTop = request.uri.split('/').slice(1,2).join(''); // ディストリビューションドメイン名以降のパスを'/'で分割した際の1つ目(/pass1/pass2/pass3ならpass1)
  var uriApi = request.uri.split('/').slice(3,4).join(''); // ディストリビューションドメイン名以降のパスを'/'で分割した際の3つ目(/pass1/pass2/pass3ならpass3)
  
  // 以下の分岐ではリクエストパスが[/pass1/*/pass3] or [/pass1/*/passX]の場合認証処理を実行

  // APIKey Auth
  if (uriTop === 'pass1' && uriApi === 'pass3') {
      if (headers['xxx-api-key'].value !== authApiKey ){
          return {
              statusCode: 401,
              statusDescription: "Unauthorized"
          };
      }
  }
  // Base Auth
  else if (uriTop === 'pass1' && uriApi === 'passX') {
      var authString = 'Basic ' + (authBasicUser + ':' + authBasicPass).toString('base64');
      if (typeof headers.authorization === "undefined" || headers.authorization.value !== authString) {
          return {
              statusCode: 401,
              statusDescription: "Unauthorized",
              headers: { "www-authenticate": { value: 'Basic realm="Message"' } }
          };
      }
  }
  else {
    return {
      statusCode: 401,
      statusDescription: "Unauthorized"
    };
  }

  return request;
}

コメント

タイトルとURLをコピーしました