Hatena::ブログ(Diary)

岩本隆史の日記帳

2008-11-08

フォーム認証は本当に捨てられないのか

フォーム認証とは

2008年も暮れようかという現在、Webアプリを作る際に「そうだBasic認証を使おう」と思う人はほとんどいないでしょう。ユーザIDとパスワードを入力するログインフォームを用意し、セッションIDをcookieに保存する方法を選ぶのが定石だと思います。ユーザIDとパスワードの代わりにOpenIDを受け入れる方法も考えられますが、セッションIDをcookieに保存するという意味では、先の例と違いはありません。この「セッションIDをcookieに保存する方法」のことを、以下「フォーム認証」と呼ぶことにします。

Basic認証が使われない理由

なぜフォーム認証が選ばれるのか。逆にいうならば、なぜBasic認証*1が選ばれないのか。産業技術総合研究所の情報セキュリティ研究センターでは、Basic認証が使われない理由を下記のようにまとめています。

  1. ログアウト機能がないこと
  2. ログインせずに同じページのコンテンツを閲覧するという使い方(ゲストアクセス)ができないこと
  3. サーバ側からログイン状態を無効にする手段が存在しないこと
  4. ホストをまたがったシングルサインオンが実現できないこと
産総研 RCIS: プロトコルの設計に関する詳細のFAQ

また、まちゅダイアリーによれば、下記の問題点も指摘されています。

それぞれの問題点について、そうと知りつつBasic認証を採用するという立場で、以下つらつらと考えてみましょう。

ログアウト機能がない

フォーム認証を採用するWebアプリでは、ログアウト機能を設けるのが一般的です。なぜ設けるかといえば、第三者による不正利用(CSRF含む)をできるだけ防ぐためでしょう。

Basic認証の場合、ログアウトという概念そのものはありませんが、ブラウザを閉じることで、不正利用の防止効果が期待できます。そして、ブラウザを閉じるという行為が面倒であるからこそ、ログアウト機能の欠損が問題視されるわけです。ブラウザを閉じずにログイン状態(Basic認証のIDとパスワードを記憶している状態)をクリアする仕組みがブラウザに備わっていれば良いように思いますが、現状ではそうなっていません。

ログアウトボタンを押すのも、ブラウザを閉じるのも、どちらも1クリックで可能な行為です。Webアプリの利用終了時に毎回ログアウトするような几帳面なユーザは、Basic認証でも几帳面にブラウザを閉じてくれると期待したいところです。

ゲストアクセスができない

これはその通りなのですが、認証が必要なリソースと不要なリソースを同じURIで表現しないよう設計すれば解決する問題です。

サーバ側からログイン状態を無効にする手段が存在しない

フォーム認証を採用するWebアプリでは、セッションハイジャックを避けるため、cookieの有効期限を短くしたり、古いセッションデータを定期的に削除したりします。

Basic認証の場合は、パスワードを定期的に変えるようユーザに促す(あるいは強制する)しか手がなさそうです。

シングルサインオンが実現できない

単一ホストで収まるようURIを設計すれば、シングルサインオンは不要です。

Basic認証のダイアログが出るとユーザが引く

慣れてもらうよりほかないでしょう。

ログイン画面がカスタマイズできない

その通りですが、下手にデザインするよりもUI標準に従うほうがユーザビリティが向上する可能性も考えられます。

まとめ

「URI設計がうまくできるなら、Basic認証を忌避することはない」というのが今の私の意見です。Basic認証を採用することにより、100%RESTfulなWebアプリが作れるのではないかと期待しています。このあたりの話は改めて書くつもりです。

追記(2008-11-10)

id:tkawaさん、ブクマコメントありがとうございます。

http://d.hatena.ne.jp/kazuhooku/20080711/1215783708 とか

はてなブックマーク - URLメモ / 2008年11月10日

id:kazuhookuさんの書かれた、cookieを使って擬似的にログアウト機能を設ける手法ですね。ログアウト機能を実装したい方は、この手法の採用を検討すべきだと思います。私自身は、ログアウト機能の必要性をそこまで感じていないので、採用する予定は今のところありません。フォーム認証を避けることでcookie非依存というメリットが得られたのに、むざむざ手放すのはもったいない、という思いもあります。

追記その2(2008-11-11)

そもそもBASIC認証ってパスが平文で送られるからセキュリティ的にまずいんじゃなかったっけ?

Twitter / UK: そもそもBASIC認証ってパスが平文で送られるからセ ...

フォーム認証だろうとBasic認証だろうと、SSL/TLSで暗号化しなければ、IDもパスワードも平文で送られます。暗号化するのが無難でしょう。もしくはDigest認証を使うかですね。

追記その3(2008-11-12)

最近は大体タブブラウザなので、ページを利用しなくなった場合にそのタブのみを閉じてすませてしまう、という人もそれなりにいる気が。

はてなブックマーク - 週末ブックマーカ / 2008年11月12日

ですね。CSRF脆弱性のないアプリを作るのが大前提となります。また、離席時にブラウザを閉じないユーザは几帳面ではない、ということで。

追記その4(2008-11-13)

ここらへんふまえてHTTPに新しい認証方式を導入する方が望ましいと思うのだがなあ。そういう動きはないのかなあ

はてなブックマーク - 狐のブクマ / 2008年11月13日

Mutual認証に期待しています。フィッシング対策を目的に作られているプロトコルですが、上記1〜4の問題点が解消される見込みです。

追記その5(2008-11-13)

ベーシック認証? 10年前の技術でしょ、という感じ。モダンなウェブアプリに使えるはずがない。

Everyone%27s bookmarks for %22フォーム認証は本当に捨てられないのか - 岩本隆史の日記帳%22 on Delicious

「使えるはずがない」というのは思い込みじゃないか、というのがこの記事の主旨です。無理に分かれとはいいませんが。

*1:あるいはDigest認証。以下の文章でBasic認証としている部分はすべてDigest認証でも同じことがいえます。

ockeghemockeghem 2008/11/09 00:25 BASIC認証が使われないもう二つの理由
・CGIからはBASIC認証が制御しにくい
・毎回IDとパスワードの検証をするのでスケーラビリティ上の懸念がある
というのはどうですか。特に後者。

IwamotoTakashiIwamotoTakashi 2008/11/09 00:53 日本におけるRESTの第一人者である山本陽平さん(id:yohei)は「ステートレスであることでスケーラビリティが向上する」としています(下記資料の11ページ)。
http://blogs.ricollab.jp/webtech/wp-content/uploads/2008/03/rest_and_roa_for_ricoh.pdf
認証情報の頻繁な検証によるパフォーマンスの低下は考えられますが、それを補えるのがスケーラブルということではないかと思っています。

前者については、Rubyでパスワードまで受け取って処理するつもりでした。共用サーバだと厳しいでしょうねー。

ockeghemockeghem 2008/11/09 06:46 コメントありがとうございます。山本陽平さんの資料にはキャッシュのことについて詳しく書かれていますね。実は徳丸の書いた(共著)「Webアプリケーションのセキュリティ完全対策」には、BASIC認証とフォーム認証を比較した記述がありまして、「(BASIC認証は)ユーザIDとパスワードのチェックをリクエストのたびに行うことになる。キャッシュなど実装上の工夫は可能だが…(P72)」となっています。その時点ではそれ以上は突っ込んで考えいなかったのですが、RESTでは中心的な話題になるのですね。

IwamotoTakashiIwamotoTakashi 2008/11/09 11:09 おっしゃる通りです。私の場合、前述の通りWebアプリ側で認証処理を行うつもりなので、フォーム認証ならセッションIDを、Basic認証ならユーザIDとパスワードを、それぞれ受け取るだけの違いしかないと考えています。キャッシュの使い方はフォーム認証のときと同じようにするつもりです。
さきほど、Amazonマーケットプレイスでご著書を注文しました。楽しみです。