⛓️

【Cloudfront】Authorizationヘッダー付きのリクエストで403が返ってくるのをなんとかする

2022/09/16に公開

はじめに

Basic認証付き(Cloudfront Functions)のCDNにAuthorizationヘッダーつけてリクエストしようとしたらハマった。
タイトルの通り、AuthorizatonヘッダーつけてCloudfrontのCDNにリクエスト投げると、プリフライト(OPTIONS)で403が返ってきてしまうので、なんとかする

結論

  • S3のCORSで「ExposeHeaders」に「Access-Control-Allow-Origin」を追加する
  • Cloudfrontのキャッシュキーとレスポンスヘッダーポリシーで許可するヘッダーを明示的に指定する
  • Cloudfront FunctionsでOPTIONSをパススルーさせる
  • Cloudfront Functionsでレスポンスヘッダーに「Access-Control-Allow-Origin」を追加する

やり方

S3

  • S3バケット > アクセス許可 > Cross-Origin Resource Sharing (CORS)
[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET",
            "HEAD"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": [
            "Access-Control-Allow-Origin"
        ]
    }
]

Cloudfront

  • Cloudfront > ディストリビューション > ビヘイビア > キャッシュキーとオリジンリクエスト > キャッシュキー設定
 const mediaCachePolicy = new cloudfront.CachePolicy(this, `${settings.resourcePrefix}-media-cache-policy`, {
      cachePolicyName: `${settings.resourcePrefix}-media-cache-policy`,
      headerBehavior: cloudfront.CacheHeaderBehavior.allowList('Authorization'),
    })

「Authorization」ヘッダーを明示的に追加

  • Cloudfront > ディストリビューション > ビヘイビア > レスポンスヘッダーポリシー
const medialResponseHeadersPolicy = new cloudfront.ResponseHeadersPolicy(this, `${settings.resourcePrefix}-media-response-header-policy`, {
      corsBehavior: {
        accessControlAllowCredentials: false,
        accessControlAllowHeaders: ['Authorization'],
        accessControlAllowOrigins: ['*'],
        accessControlExposeHeaders: ['*'],
        accessControlAllowMethods: ['GET', 'HEAD', 'OPTIONS'],
        originOverride: true,
      }
    });

「Authorization」ヘッダーを明示的に追加。

  • Cloudfront > 関数
function handler(event) {
    var request = event.request;
    var headers = request.headers;
    var method = request.method;

    var responseHeaders = {
        "access-control-allow-origin": { value: "*" },
    }

    if(method === "OPTIONS") {
        return {
            statusCode: 204,
            statusDescription: "NoContent",
            headers: responseHeaders
        };
    }
    var authString = "Basic base64EncodedString";

    if (typeof headers.authorization === "undefined" || headers.authorization.value !== authString) {
        return {
            statusCode: 401,
            statusDescription: "Unauthorized",
            headers: responseHeaders
        };
    }

    return request;
}

リクエストメソッドが「OPTIONS」の場合、Basic認証挟まず204ステータスで返却。

さいごに

こちらにも記載されている通り、安易に「*(All)」で全許可しちゃダメだなと思いました。
カスタムヘッダーを追加する場合も、同様の手順でできます。

Discussion