ユーザー認証の手抜き

Webアプリ作っているといろんな局面でユーザー認証が必要になる局面がある。まじめにつくると果てしなく面倒だし、適当につくるとセキュリティ上問題になるので、要件に応じて適切に手抜きする必要がある。

適当なやつからしっかりしたやつまでなんとなくソートしていくとこんなかんじだと思う。

  • 認証なし
  • IPで弾く
  • Basic認証ソースコード、設定ファイルにパスワードベタ書き)
  • Basic認証(DBにUserテーブルをつくってパスワードを保存。追加はcliとかで手動)
  • login/logout画面作成。cookieなりmemcacheなりにセッションを保存
  • webからユーザーを追加できるように
  • password変更機能
  • OAuth
  • OpenID
  • mailを送ってリンクをクリックさせてメールアドレスの所有確認
  • メールアドレス変更機能
  • メールを使ってのパスワードリセット機能
  • OAuthで作ったアプリへの後からのメールアドレスとパスワード追加登録機能
  • 二段階認証

不特定多数のユーザーが登録する場合に開発として楽なのはid/password方式。
メールアドレス認証とかがない純粋なidだとすごい楽です。
こういうときOAuth選びがちだけど意外と使い勝手悪い。

OAuth使うと発生する問題

  • ライブラリの依存とか諸々ではまりやすい
  • OAuth provider (TwitterとかFBとかギッハブとか)に依存することになる
  • 複数のOAuth providerに対応すると1人のユーザーが複数アカウント重複してしまう可能性がでてきてめんどくさくなる
  • Native Appつくるときに認証でWebView開いて(myapp(web) -> Twitter -> myapp(web) -> myapp(native))みたいなcallbackの嵐をやるハメになる
  • Native Appのバイナリ内にサーバー側と同じConsumer Key/Consumer Secretを持つとセキュリティ上問題があるのでNativeでは持たないようにするなり、別のConsumer Keyを持つなりしないといけない
  • 更にマジメな話をするとアプリ内WebViewで外部サービスのパスワード入力させて認証させるのはfishingのおそれがあるのでアドレスバーが信頼できる外部ブラウザアプリに飛ばして認証させたほうが良い

追記

OAuthは認可であって認証ではないうんぬんの話は承知しておりますが現実としてその辺に詳しくないエンジニアの皆様は「Twitterで認証」とおっしゃられてますし、TwitterにOAuthで認可を得てverify_credential.jsonを叩いた結果からuser_idを取得するとそれは認証として問題なく使えてしまうという現実もあります(余計な権限の認可もついていますが、そっちもなんだかんだで使うし)。OAuth単独だと認証機能がないというのは事実なんですが一般的に言うOAuthとは要するにTwitterでありFacebookでありそれらのAPIと組み合わせることで認証機能を得ることができるし、IDな人たちが大好きなOpenIDの最新規格であるOpenID ConnectだってOAuthでaccess_token取得するついでにIdentityもついてくるというTwitter APIのverify_credentialを呼ぶ手間が省けて共通規格にしましたみたいなもんだし、日曜深夜にこんな長文書くハメになるのでOAuthがどうとか認証とか認可とかの議論やめたい。