あらすじ
今まで OAuth は「認証とか簡単にできてすごいんだなー」程度に思っていました。
しかし仕事でOAuth(に近い仕組み)を実装することになり、雰囲気でOAuthを使うわけにはいかなくなりました。
というわけで、理解しようぜOAuth! と意気込んで勉強を始めましたが……単なる OAuth 2.0 を認証に使うと、車が通れるほどのどでかいセキュリティー・ホールができる? 認証と認可は違う? OpenID Connectって?
本記事は、OAuth 2.0 初心者に向けた入門記事を目指しています。
対象読者
- OAuth 2.0 の雰囲気すらつかめてない人
- OAuth 2.0 の勉強を始めたい人
対象にしない読者
- OAuth 2.0 の雰囲気のさらに向こうへ進みたい人
- OAuth 2.0 を整理して理解したい人
おすすめ資料
一番お世話になりました。これが無ければいまだに OAuth 2.0 難民だったと言っても過言じゃないです。
今なら電子版が野口さん一人で買える! お得!
猫も杓子も公式文書。困ったときは公式を見ればとりあえず間違いは無いです。
ただし理解できるかは別問題。まー難しいこと……わからないところはググって情報を補完していくといいかもしれません。
OAuth 2.0について
認証と認可
まずは認証と認可について、この記事では以下のように定義します。
- 認証 …… 個人や団体等を特定すること
- 認可 …… 行動やリソースの利用などについて権限を与えること
例えば住民票やマイナンバーカードを見せれば、自分が「誰なのか」を特定する情報を相手に与えることができます。これが認証ですね。
またライブや映画のチケットを見せれば、自分がライブや映画を見る「権限がある」という情報を相手に与えることができます。これが認可です。
この両方の機能を備えているのが運転免許証や保険証になります。例えば運転免許証では、自分が「誰なのか」という証明と運転をする「権限がある」という証明の両方を行うことができます。
OAuth 2.0 の目的
次にOAuth 2.0 の目的について確認します。
OAuth 2.0 の資料で、OAuth 2.0 で解決したい問題について言及されています。
In the traditional client-server authentication model, the client
requests an access-restricted resource (protected resource) on the
server by authenticating with the server using the resource owner's
credentials. In order to provide third-party applications access to
restricted resources, the resource owner shares its credentials with
the third party. This creates several problems and limitations:
- Third-party applications are required to store the resource
owner's credentials for future use, typically a password in
clear-text.- Servers are required to support password authentication, despite
the security weaknesses inherent in passwords.- Third-party applications gain overly broad access to the resource
owner's protected resources, leaving resource owners without any
ability to restrict duration or access to a limited subset of
resources.- Resource owners cannot revoke access to an individual third party
without revoking access to all third parties, and must do so by
changing the third party's password.Compromise of any third-party application results in compromise of
the end-user's password and all of the data protected by that
password.OAuth addresses these issues by introducing an authorization layer
and separating the role of the client from that of the resource
owner. In OAuth, the client requests access to resources controlled
by the resource owner and hosted by the resource server, and is
issued a different set of credentials than those of the resource
owner.
ここで用語について確認しておきましょう。
- リソースオーナー(resource owner) …… リソース保持者。例:一般ユーザー
- リソース(resource) …… サーバーに保持している情報。例:ユーザーの個人情報
- サーバー(server) …… リソースを保持しているサービス。例:ツイッター
- クライアント(client) …… サードパーティアプリケーション。例:twicca
これらをもとに上記の英語を雑に翻訳すると、以下の通りになります。
従来ではクライアントがアクセス制限されたリソースを取得するために、リソースオーナーの認証情報を利用していた。そのために、以下の問題が発生していた。
- クライアントがリソースオーナーのパスワードを平文で保持していた
- パスワードに起因するセキュリティ脆弱性があるにもかかわらず、サーバーはパスワード認証の対応を求められた
- リソースオーナーはクライアントに対し、接続可能な期間やアクセスできるリソースを制限することができなかった
- リソースオーナーは特定のクライアントについてアクセス取り消しをすることができず、パスワード変更による全クライアントのアクセス取り消ししかできなかった
- 任意のクライントと連携するには、リソースオーナーのパスワードを利用し、全てのデータをそのパスワードで保持することになった
OAuth はリソースオーナーとクライアントの役割を異なる認可層で分離し、クライアントにはリソースオーナーと異なる認証情報を発行することで、これらの問題を解決する。
つまり、「クライアントに対し、リソースオーナーが管理しサーバーに保持されているリソースを安全に渡したい」ということです。
そしてそのための手段として、リソースを保持するサーバーからクライアントに認証情報を発行する手続きを規定しています。
これらをまとめると、OAuth 2.0 の目的は以下の通りです。
- サーバーがクライアントに対し認証情報を発行する手段を規定する
- リソースオーナーはクライアントがアクセスできる期間を制限できること
- リソースオーナーはクライアントがアクセスできるリソースを制限できること
- リソースオーナーは個別のクライアントに対しアクセス権限の破棄ができること
OAuth 2.0 のフロー例
それではフローを見ていきましょう。
ここではわかりやすいように、各用語に以下の名前をあてはめます。
- リソースオーナー → ユーザー
- クライアント → hogeアプリ
- サーバー → piyoサーバー
- リソース → piyoリソース
また前提として、以下の条件が必要になります。
- ユーザーはpiyoサーバーに対する認証情報を持つ
- ここでは「ユーザーがpiyoアプリにアカウントを持ち、ログインできる」とします
- ユーザーはプライベートなpiyoリソースをpiyoサーバーに保持している
ユーザーがhogeアプリに対してpiyoリソースを安全に提供したいとき、以下のようなOAuthフローが考えられます。
- フローを開始します
- hogeアプリはpiyoサーバーに「hugaアプリからのpiyoリソース要求だよ」といった情報を付与してユーザーをリダイレクトさせます
- piyoサーバーは要求に従い、まずユーザー認証を要求します(この場合はログイン)
- ユーザー認証が確認できた場合、piyoサーバーはユーザーに「hogeアプリにpiyoリソースを提供してもいいですか?」と確認します
- ユーザーが許可を出した場合、
認可コード
を発行し、ユーザーをリダイレクトさせます - 認可コードを受け取ったhogeアプリは、認可コードを利用してpiyoサーバーに
アクセストークンリクエスト
を送ります - piyoサーバーは、hogeアプリから送られた認可コードが正当なものであるか検証します
- 認可コードが正当だった場合、piyoサーバーはhogeアプリに
アクセストークン
を発行します
ここまでが一連の流れですね。
前述した通り、OAuth 2.0 の目的はクライアント(hogeアプリ)に認証情報を発行することなので、アクセストークンの発行により完了します。
hogeアプリはアクセストークンを使うことで、認可された範囲でpiyoリソースを取得することができるようになります。
以上がものすごくおおざっぱな説明です。なんとなくイメージできたでしょうか?
ここで例に出したフローは OAuth 2.0 で定義されている4つのフローのうち、代表的な認可コードフロー
と呼ばれるものです。
認可サーバーとリソースサーバー
先ほどの例ではサーバーを一つのものとして扱いましたが、一般的には2つの役割ごとに別個のサーバーとして扱われます。
それが認可サーバー
とリソースサーバー
です。
両者について、RFC6749では以下のように定義されています。
- authorization server
The server issuing access tokens to the client after successfully
authenticating the resource owner and obtaining authorization.- resource server
The server hosting the protected resources, capable of accepting
and responding to protected resource requests using access tokens.
認可サーバーはクライアントへのアクセストークン発行を、リソースサーバーは保護されたリソースの保持(およびアクセストークンを用いたリソースへのリクエスト処理)を担当します。
つまり、先ほどのフローでいうサーバーとは認可サーバー
のことを指します。
そして、最終的に得られたアクセストークンを使ってリソースサーバー
へアクセスすることによりリソースが得られます。
先ほどの図におけるサーバーを認可サーバー
に修正し、またフローの最後にリソースを取得する処理を加えると以下の図になります。
OAuth 2.0 の目的は認証情報発行処理を規定することですが、OAuth 2.0 を利用する人
の目的はリソースの安全な受け渡しです。
よって、ここまでがOAuth 2.0 を利用した場合のフローと言ってもいいかもしれません。
最後に、OAuth 2.0 で規定されている用語を使ってフローを書き直しておきましょう。
※上記フローでは必要最小限のパラメータしか記載していません。
OAuth 2.0 による課題解決
本記事の前半で、OAuth 2.0 の目的は以下の通りと説明しました。
- サーバーがクライアントに対し認証情報を発行する手段を規定する
- リソースオーナーはクライアントがアクセスできる期間を制限できること
- リソースオーナーはクライアントがアクセスできるリソースを制限できること
- リソースオーナーは個別のクライアントに対しアクセス権限の破棄ができること
ここで、OAuth 2.0 がこれらを満たすことができるか確認してみましょう。
- サーバーがクライアントに対し認証情報を発行する手段を規定する
これについては今まで説明してきた通り、OAuth 2.0 で認証情報発行フローを規定しています。OKですね。
- リソースオーナーはクライアントがアクセスできる期間を制限できること
- リソースオーナーはクライアントがアクセスできるリソースを制限できること
- リソースオーナーは個別のクライアントに対しアクセス権限の破棄ができること
クライアントのリソースに対するアクセス権限はアクセストークンによって管理されます。言い換えれば、特定のアクセストークンに対してアクセスの拒否やアクセス権限の破棄を行うことで、そのアクセストークンを持つクライアントからのアクセスを制限することができます。
そして、リソースオーナーにアクセストークン管理機能を提供すれば本条件を満たすことができます。
以上から、これらもOKとみていいでしょう。
すなわち、OAuth 2.0 を用いることにより、ただIDとパスワードをクライアントに渡すよりもはるかに安全なリソース管理が行えるようになります。
おわりに
OAuth 2.0 の学習を始める人にとってわかりやすい記事になっていれば幸いです。
ひとまず本記事はここで終わりますが、今後より詳しいセキュリティの問題等の記事を書いていこうと思います。
ちなみに、本記事でリソースオーナー - クライアント
間の認証について全く触れていないことにお気づきでしょうか?
OAuth 2.0 の規定においても上記認証についてはほとんど触れていません(stateが上記認証情報に該当するかもしれませんが……)。
OAuth 2.0 はあくまでリソースオーナー → クライアント
の認可処理とクライアント - サーバー
間の認証に関するものであるため、リソースオーナー - クライアント
間の認証については(もっと言うならリソースオーナー - サーバー
間の認証についても)対象外であると私は認識しています。
そこで出てくるのがOpenID Connectですが、これについてはまた別記事にしたいと思います。
参考資料
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
0件のコメント