Android
iOS
OAuth
oauth2

アプリの認証/認可どうしてるか知りたい

More than 3 years have passed since last update.

ネイティブアプリの認証にどういう方法があるのか調べたけど、いまいちどういう方法を取ればいいのか確信が持てない。

ウェブの時代

ウェブサービスではメールアドレスとパスワードを使った認証が多くて、Cookieを使ってセッション管理をする方法が一般的な実装になっている。
認可という概念はあんまり意識されてなくて、セッション情報により認証されたリクエストはすべて認可されるパターンが多い。

認証(AuthN)と認可(AuthZ)の違いが理解されづらいのはたぶんこのことが原因で、明確に使い分けてなかったからだ。

ウェブ時代のイメージ

なぜ使い分ける必要があるのか?

サービス間連携をカジュアルにセキュアにという気運があった。ウェブAPIをもっとオープンに利用したいしさせたい。
しかし認証情報を他人にあずけるのは好ましくないし、拒否反応を示すユーザも多いだろう。サービス側だって無用なリスクを負いたくはない。

全ての権限(認証情報)はあずけたくないが一部の権限はあずけたい。この要求を満たすには認証と認可の役割を分割し、認可情報の管理をすることで対応できそうだった。
それを標準化しようと考案されたのがOAuthで、後方互換性はないが次代バージョンのOAuth2は広く使われている。

認証の役割は小さくなり、認可を得るためのステップとなった。

認証と認可を分離させたイメージ

ネイティブアプリの認証/認可

ネイティブアプリの認証/認可についてどういう実装が良いのか。

認証

認証にソーシャルログインを用いるサービスが増えた。Facebook/Twitter/Google+など。

Twitterを除くとメジャーなIDプロバイダはOAuth2が使われていて、利用するための実装はすでに多くの知見が蓄積されているので困ることはないだろう。
OAuth2は認可のためのプロトコルなので認証に利用するには十分な注意を必要とするが、その点も多分に指摘されているので触れない。

独自のサービスアカウントを作る場合は、相変わらずメールアドレスとパスワードの組み合わせが多い。
メールアドレスはユーザ名に置き換えるパターンもあるが、認証情報については今のところそう悩む必要はないように思う。
メジャーなIDプロバイダやクリティカルなデータを取り扱うサービスでは、二段階認証が導入されている。

認可

Cookieを使っているアプリ。恐らく旧来のセッション管理。

  • Instagram
  • Evernote
  • MoneyForward

認可のための独自実装を考えなくてはならないが、多くのアプリはAPI提供をしていないし複雑な認可処理を必要としないので問題にならない。またOAuth2との共存が出来ないというわけじゃないので、必要となれば導入すればよい。
Cookieは洗替をアプリ側で意識することが少なくて楽だ。

OAuthやOAuth2を使ったアプリが増えてきた。公式アプリもパブリッククライアントの一種。(APIとアプリの提供者が同一)

  • Pinterest
  • Foursquare

OAuth2を使うとサーバを経由するブラウザ遷移型の認可コードによる実装が、client_secretをアプリ内に必要としないため堅実。
refresh_tokenによるaccess_tokenの洗替はきっと面倒くさい。

しかし認証処理のためにブラウザに遷移するのは他サービスのIDプロバイダを利用する場合ならともかく、公式アプリでやるのはどうなんだろう。

リソースオーナーパスワードクレデンシャルは旧来のセッション管理に近いが、このグラントでclient_idclient_secretを要求する理由が分からない。認証情報を握ってしまえば、クライアントの認証など必要ないのではないのか。
いずれにしてもclient_secretが漏れる状態は気持ち悪い。

OAuth2を拡張して認証情報とaccess_token(+refresh_token)を交換するグラントを実装してしまうのが手っ取り早いかなと考えている。
認証情報はメールアドレスとパスワード、またはIDプロバイダのaccess_tokenだ。