🐷

Heroku のトレイリングスラッシュのリダイレクトと Basic 認証によって Unauthorized になってしまう話(Chrome)

2022/12/21に公開

結論:Chrome は http 通信だとベーシック認証を拒否するっぽい。

詳しいわけではないので、間違っていたり詳細な情報があったりしましたらコメントいただけると幸いです。


Heroku は一部アドレスでトレイリングスラッシュを付与します。

どういうことかというと、https://example.herokuapp.com にアクセスするときはそのままですが、https://example.com.herokuapp.com/hoge にアクセスすると、https://example.herokuapp.com/hoge/ にリダイレクトされます。

と思いきや実際は、 http://example.herokuapp.com/hoge/ を経由して、https://example.herokuapp.com/hoge/ にリダイレクトされています。

これと Basic 認証が組み合わさると、Chrome で Unauthorized が表示されてしまう事があるようです。

なお、Firefox と Safari では Unauthorized にならず、ページが表示できていました。

この原因がなにか調査するために、処理の流れを Network タブを見て追ってみました。

Chrome の処理の流れを追う

  1. https://example.herokuapp.com/hoge にリクエストする。
  2. Basic 認証のプロンプトが開き、一度 401 Unauthorized を一回返す。
  3. https://example.herokuapp.com/hoge に Authorization ヘッダーを付与して再度リクエストする。
  4. 本来であれば認証が通ったので 200 を返すのかと思いきや、http://example.herokuapp.com/hoge/ へリダイレクトさせるように 301 を返す。
  5. http://example.com/hoge/ へリクエストする。
  6. 401 Unauthorized を返す。←なぜ?

Safari, Firefox の処理の流れを追う

  1. https://example.herokuapp.com/hoge にリクエストする。
  2. Basic 認証のプロンプトが開き、一度 401 Unauthorized を一回返す。
  3. https://example.herokuapp.com/hoge に Authorization ヘッダーを付与して再度リクエストする。
  4. 本来であれば認証が通ったので 200 を返すのかと思いきや、http://example.herokuapp.com/hoge/ へリダイレクトさせるように 301 を返す。
  5. http://example.com/hoge/ へリクエストする。
  6. https://example.com/hoge/ にリダイレクトするように 301 を返す。
  7. https://example.com/hoge/ へのクエストをする。この際、Authorizationヘッダーに認証情報を含んでいる。
  8. Authorizationヘッダーがあるので 200 を返す。

結論

もしかすると、Chrome は http の通信ではベーシック認証を無条件で拒否するのかもしれません。

試しに Chrome で http://example.herokuapp.com/hoge/ を開こうとしたところ、ベーシック認証のプロンプトすら表示されずに 401 Unauthorized となりました。

一方、Safari と Firefox では、ベーシック認証のプロンプトが表示されました。

この違いだと思います。

解決策

解決策1(一番良さそう)

.htaccess など apache の設定でトレイリングスラッシュを付与するようにする。

こうすれば Heroku による https から https へのリダイレクトをしなくて済みます。

解決策2

URL に Basic 認証のid と password を付与する。

https://id:password@example.com/hoge とする感じですね。

解決策3

Basic 認証を外す。

解決策4

a タグの href 属性の値をすべてトレイリングスラッシュ付きにする。

解決策は会社の方に教えていただきました!ありがとうございます!

感想

調査しながら記事を書いていたのでぐちゃぐちゃになってしまいました。こういう内容はスクラップが向いていますね。

結論をはっきりと言い切ることができませんでしたが、リクエストとレスポンスという基本的な概念を再確認できて良かったです。

GitHubで編集を提案

Discussion