記事の要旨
仕事ではあまりセキュリティ周りには触らないのですが,OAuth2.0が出てくるたびに「どういう仕組みだっけ」と調べ直すのが非生産的なので,自分なりの整理を記事として残しておいたというページです.
基本的にこちらのページを読み解きつつ,理解できなかったものはインターネット上の解説を見て補足しています.
1. 認証と認可
OAuth(オーオース)は認可(Authorization)のための公式ルールのようなもの.
「認可」とはリソースへの各種操作権限を付与する行為という理解で良いと思う.例えばこの記事を編集できるのは俺だけで,それは俺が記事の編集権限を「認可」されているから.
似たような言葉として認証(Authentication)があり,これは対象の身元を証明するという行為.本人だけが知っている情報(パスワード)や持っているモノ(指紋,デバイストークン)などを用いて証明する形になる.
適切な認可のためには認証が必要なのは言うまでもない.例えば俺以外の第三者にこの記事の編集権限が与えられてはいけない.なので認証と認可は混同されがちであるが,後述の事情もあり,これらは切り離して議論することが求められる.
2. 「認可」を切り離したいという要求
たとえば新しいTwitterアプリがリリースされたとする.
当然ながらアプリとして機能するためには俺のアカウントで投稿する権限や,プロフィールを参照する権限が必要だ.つまりこのTwitterアプリは,Twitter社が有する俺に関するリソースへの各種権限の「認可」を求めている.
さて,どうすれば良いだろうか.1つの解は,このTwitterアプリに俺のTwitterアカウントのパスワードを教えてあげるという方法だ.これは認証と認可を一体としたやり方で,例えば以下のリスクをはらんでいる.
- このアプリ会社のセキュリティが不十分だった場合,俺のTwitterアカウントの認証情報が流出し得る
- このアプリ会社自体が悪質で,俺の個人情報を盗もうとしている可能性がある
アプリ会社としても,「認証」という高難易度かつ責任が伴う行為にはあまり関わりたくないというのが本音だろう.彼らが望んでいるのはあくまで権限の「認可」でしかない.
ここに認証と認可を分離したいという要求が発生し,そのうちの「認可」の部分をカバーしているのが,OAuth2.0ということになる.
3. OAuth2.0における用語と前提
OAuth2.0で出てくる用語は以下のとおり.例として架空のTwitterクライアントアプリ「ツイツイ」を用いる.Twitter API周りは詳しくないのでそこは「なんとなく」で留めておいて欲しい.
用語 | 意味 | 例 |
---|---|---|
リソースオーナー | リソースに対して認可を出せる存在 | 俺(nk5jp) |
クライアント | 認可を求めている存在 | Twitterアプリ「ツイツイ」 |
リソースサーバ | リソースを提供する存在 | Twitter社のリソース提供API |
認可サーバ | 一連の認可行為を取りまとめてくれる存在 | Twitter社の認可API |
また、OAuth2.0を実施する上で以下の前提が成り立っている.
- 認可サーバはリソースオーナーを認証できる.つまり俺が事前にTwitterにアカウントを登録している.
- 認可サーバはクライアントを認証できる.つまり事前にアプリ開発会社が認可のための登録をしている.
なお、OAuth2.0には4つのタイプがあるが,今回は「認可コード」の方式に絞ることとする.また,リソースオーナーの各種処理はユーザエージェントが代行するものだが,今回はその辺りの概念は割愛する.
4. 認可の流れ
4.1 認証エンドポイントへの転送
まずはクライアント(「ツイツイ」アプリ)がリソースオーナー,つまり俺を「認証エンドポイント」と呼ばれる場所まで案内する.認証エンドポイントというのは,認可サーバの窓口の1つだと思ってくれれば良い.
クライアントは俺に対して「手続が終わったらまた来てくださいね」とだけ伝えて,一旦退場していく.
4.2 認可の確認
認可サーバはまず,クライアントが連れてきたリソースオーナー(俺)が何者かを確認する.前提でも述べた通り,認可サーバ(Twitter社)はパスワード認証などの規定の手続きを経て,俺が俺であることを認証することができる.
無事リソースオーナー(俺)の身元を特定した認可サーバは,「ツイツイを名乗る人が貴方のリソースに関して色々な権限をくれと言っていたが,問題ない?」と聞いてくる.俺が「良いですよ」と答えれば,認可サーバは「じゃあこれを持って行ってください」と,「認可コード」と呼ばれる1度しか使えない合言葉を渡してくる.これで認証エンドポイントにおける処理はいったん終了.
4.3 認可の依頼
俺は認可コードを持って改めてクライアント(「ツイツイ」)の元を訪れる.現実にはこの辺りはリダイレクトなどで自動的に処理されている.認可コードを受け取ったツイツイは,それを持って今度は自分自身が「トークンエンドポイント」と呼ばれる認可サーバ上のもう1つの窓口を訪れる.
ここで認可サーバは,やってきたクライアントが「ツイツイ」であることを認証する(これが出来ることは前提で述べた通り).その上でツイツイは認可コードを提示する.認可サーバは以下のロジックで,申請の妥当性を判断する
- この男(クライアント)は間違いなくツイツイである
- この認可コードは,先ほどリソースオーナー本人(俺)に提供したコードと一致する
- そのときリソースオーナーを連れてきた申請者も自分をツイツイと名乗っていた
- この認可コードを先に提示してきた者は他にいない
妥当と判断したら,認可サーバはクライアントに「アクセストークン」を提供する.アクセストークンには「付与された権限の内容」と「有効期限」の情報が含まれている.
4.4 リソースの取得
無事アクセストークンをゲットしたツイツイは,リソースが必要であればアクセストークンを片手にTwitterのリソースサーバの元を訪れ,自信満々にアクセストークンを提示する.リソースサーバはそれが誰であれ,トークンの内容と有効期限が有効であれば正当に認可を受けた存在であると判定し,許される範囲でのリソース(Twitter上の俺のプロフィール情報など)を提供する.
5. 補足
言うまでもなく,アクセストークンが流出してしまうと勝手にツイートされてしまうなどの被害が生じる.よく「OAuth2.0を認証に使ってはいけない」と言われるのも,端的に言えばこのアクセストークンに「誰向けに発行した」という情報が含まれていないからだ.その辺りを補強した方式がOpenID Connect(OIDC)と呼ばれるものになる.
しかし,パスワードそのものが漏洩したわけではないので,OAuth2.0による認可は冒頭で述べたようなパスワードそのものを提供する方式と比較してセキュリティは保たれる.アカウントを乗っ取ろうにも「現在のパスワード」がわからないので変更できないというわけだ.