はじめに
独自ドメインの小さなWebアプリを、AWSで以下のお安い構成でセットアップしてみました。
- Route53 (独自ドメインを管理)
- AWS Certificate Manager (ACM。SSL証明書を管理)
- CloudFront
- EC2
CloudFrontはキャッシュ用のエッジサーバとしてではなく、ACMと紐付けてSSLを利用したいため配置しています。
しかし、この構成にしたところアプリに実装していたOAuth認証が急に動かなくなりました。。。
最終的にCloudFrontの設定を見直して解決できたので、忘れないようにメモとして残しておきます。
同じように悩んだ人の参考になれば幸いです。
最終的な設定だけ見たい方は、まとめをどうぞ。
GoogleのOAuth認証が通らなくなった
もともと、静的なWebコンテンツを CloudFront+S3
の構成でSSLでホストしていたため、それに倣って CloudFront+EC2
もセットアップしてみました。
CloudFrontのキャッシュ設定はほぼデフォルトのままです。
いざアプリケーションでGoogleのOAuth認証してみると・・・
エラー 400: redirect_uri_mismatch
The redirect URI in the request, http://***.ap-northeast-1.compute.amazonaws.com/login/oauth2/code/google, does not match the ones authorized for the OAuth client.
GoogleのOAuthで設定したリダイレクトURIにマッチしないエラーとなりましたorz
上記のエラーメッセージを見ると、認証後のリダイレクト先がEC2のパブリックDNS
http://*****.ap-northeast-1.compute.amazonaws.com/...
になってしまっているようです。
確かにGoogleのOAuth設定で、リダイレクト先に独自ドメインのみを許可しているので、 それ以外のURIにリダイレクトできないのは正しい制御ではあるのですが・・・
なぜリダイレクト先がEC2のパブリックDNSになってしまう?
リダイレクト用のURIはアプリ側でホスト名を設定して生成しています。
つまり、 EC2に独自ドメインのホスト名が渡ってきていないことが問題のようです。
ホスト名はリクエストヘッダで指定するので、改めてCloudFrontの設定をみてみると・・・
怪しい設定がありました。
Cache Based on Selected Request Headers とは
この項目を調べるにあたり、以下の記事がとても参考になりました。
https://michimani.net/post/aws-about-cache-spec-of-cloudfront/#cache-based-on-selected-request-headers-1
どうやらCloudFrontはエッジサーバとしてコンテンツをキャッシュするために、デフォルトではリクエストヘッダの値を考慮しないだけでなく、 オリジンにリクエストヘッダを転送しないようです。
公式の説明文 を読むと、[None(Improves Caching)]
の説明には特に記載がないですが、 [All(すべて)]
には
代わりに、CloudFront はすべてのリクエストをオリジンに送信します。
とありました。
なるほど、こいつが元凶 この設定を見直す必要があったようです。
オリジンにリクエストヘッダを転送する設定
今回、オリジンはEC2のためキャッシュは不要、かつリクエストヘッダも転送して欲しいため [All]
に変更しました。
これで無事にEC2にホスト名を含むリクエストヘッダが転送されるはずです。
無事にアカウント選択画面まで進みました!
アカウントを選択してみると、、、
これはアプリ側で用意しているエラーレスポンスですが、つまり
Status Code: 401 Unauthorized
のようです。
GoogleのOAuthからアプリへのリダイレクトは成功していますが、アプリ側の処理で問題があるようです。
Forward Cookies と Query String Forwarding and Caching
意気消沈しながらも、改めてCloudFrontの設定をみてみると・・・
CookieやURIのクエリパラメータに関する設定がありました。
この項目も以下の記事に詳しく説明されていました。
これらの設定も、デフォルトではコンテンツをキャッシュするために値の考慮をしないだけでなく、
Cookieやクエリパラメータがオリジンに転送されないようです。
つまりこの設定もNone (Improves Caching)
だとオリジンに転送しないんですね。
オリジンにCookieとクエリパラメータを転送する設定
すべてのCookie、クエリパラメータをオリジンに転送して欲しいため**[All]
**に変更しました。
以上の設定で、無事にCookie
およびURIのクエリパラメータ
がオリジンに転送されるようになりました。
画面ショットは省きますが、これでCloudFront+EC2
の構成で無事にOAuth認証でログインが行えるようになりました
まとめ
CloudFrontをEC2などAppサーバの手前に配置する場合、以下の項目でオリジンへの転送の設定を行う必要があります。
-
Cache Based on Selected Request Headers
リクエストヘッダをオリジンに転送するため[All]
を指定 -
Forward Cookies
Cookieをオリジンに転送するため[All]
を指定 -
Query String Forwarding and Caching
クエリパラメータをオリジンに転送するため[Forward all, cache based on all]
を指定
参考