OAuth2.0による権限の委譲
皆さん、こんにちは。技術開発グループのn-ozawanです。
人間以外で唯一ダムを作る動物として有名なビーバーですが、そのダムが原因で水害に悩まされていたアメリカのアイダホ州は、ビーバーを312km先に離れた場所へパラシュート降下をさせて強制移住させたそうです。やることが豪快ですよね。
本題です。
システム開発をしていると一度はOAuth2.0を聞いたことはあるかと思います。OAuth2.0はユーザーが所有するリソースへのアクセス権限をクライアントへ委譲するための仕組みです。今日はそんなOAuth2.0についてのお話です。
目次
OAuth2.0
認証と認可
OAuth2.0は認証認可の仕組みとして広く知られています。厳密にはOAuth2.0は認可の仕組みであり、認証の仕組みではありません。そもそも認証と認可の違いは、認証とは「アクセスしてきた利用者が本人かどうかを確認すること」に対して、認可とは「アプリなども含む利用者にアクセス権限を与えること」になります。
OAuth2.0はクライアントアプリに、利用者が所有するリソースへのアクセス権限を与えることになりますので、認可の仕組みとなります。
権限の委譲とは?
権限の委譲とは何でしょうか?また、先ほど言った「利用者が所有するリソースへのアクセス権限を与えること」とはどういうことでしょうか?イマイチ、イメージを掴むのが難しいと思いますので、少し嚙み砕いて説明します。
皆さんはインスタグラムを利用されたことはありますか?ここではスマートフォンのカメラ機能で撮影した画像をアップロードして共有するシステムをイメージしましょう。

この場合、画像を管理するシステムは「リソースサーバー」であり、管理している画像を「リソース」と呼びます。リソースサーバーは画像を管理しているだけで、画像の所有者はアップロードした人になります。なので、画像をアップロードした人を「リソース所有者」と呼びます。
アップロードされた画像を利用したい別のシステムがあるとします。例えば画像を印刷するシステムとしましょう。

画像を印刷するシステムを「クライアント」と呼びます。クライアントは印刷するためにリソースサーバーへ画像を要求します。上の図では、リソースサーバーはクライアントへ画像を提供していますが、リソース所有者から許可を得ずに受け渡しをしています。リソース所有者へ確認もせずに又貸しをしている状態です。これはよくありません。もし、このクライアントが悪意を持っている場合、とんでもないセキュリティ事故に繋がります。
この仕組みを是正するために、必ずリソース所有者に許可を求めるシーケンスが必要です。リソース所有者とクライアントの間に認可サーバーを挟んでみましょう。

クライアントはリソースサーバーへ画像を要求する前に、まず認可サーバーに許可を求めます。認可サーバーはクライアントからの要請を受けて、リソース所有者へ「クライアントに画像へのアクセスを認めても良いか?(アクセス権限を委譲してもよいか?)」確認を取ります。ここでリソース所有者がOKを出せば次のステップに進みます。

リソース所有者からOKを取り付けた認可サーバーは、クライアントへアクセストークンを発行します。このアクセストークンはリソースサーバーへのアクセス許可状になります。クライアントは、このアクセストークンをリソースサーバーへ渡して、画像の提供を求めます。リソースサーバーは、受け取ったアクセストークンが「本当に認可サーバーから発行されたものなのか?」を検証し、問題なければクライアントへ画像を提供します。
上記の手続きを踏むことにより、リソース所有者の知らないところで、勝手にリソース所有者の画像(リソース)が悪用されることを防ぎます。OAuth2.0はRFC6749で定められており、上記の図で言うところの①と④が該当します。また、アクセストークンを利用する⑤と⑥はRFC6750として、OAuth2.0の関連仕様として定められています。なお、リソース所有者と認可サーバーがやり取りする②と③に関してはOAuth2.0の範囲外となっており、どうやってリソース所有者に確認するかは認可サーバーによります。
アクセストークンとリフレッシュトークン
アクセストークンは、リソース所有者が所有するリソースへのアクセスを許可する証明でもあり、クライアントがリソースサーバーのリソースへアクセスする際に必要になるものです。アクセストークンは認可における中核を担っており、OAuth2.0の仕様を一言で要約すると、アクセストークンを発行する仕組み、とも言えます。
アクセストークンはセキュリティに直結します。リソース所有者が一度許可したからと言って、いつまでもリソースにアクセスできる状況は好ましくありません。なのでアクセストークンには有効期限が設けられています。有効期限は認可サーバーによって異なります。Keycloakではデフォルトでは5分ほどですし、Microsoft ID Platformでは60分から90分をランダムに割り振ります。
アクセストークンの有効期限が切れた際には再発行してもらう必要があります。再発行時に必要となるのがリフレッシュトークンです。通常、アクセストークンとリフレッシュトークンはセットで発行されます。
認可コードによる付与方式
繰り返しになりますが、OAuth2.0は、認可サーバーからクライアントへ、アクセストークンを発行する仕組みです。あくまで仕組みであり、その手順(認可付与方式)を定めたものになります。
OAuth2.0では、世の中の幅広いユースケースに対応するために、4つの認可付与方式を用意しています。今回はその1つでよく使われる「認可コードによる付与方式」を紹介します。

各要素でのやり取りはHTTPで行われます。また、通信経路の暗号化としてTLSを用いることが推奨されています。
まず初めに、リソース所有者は認可サーバーの認可エンドポイントにリダイレクトされます。リダイレクトされた先では、認可サーバーとリソース所有者間で、リソースへのアクセス権限をクライアントに付与しても良いか、確認が行われます。
確認が取れた場合、認可サーバーは「認可コード」を発行し、リソース所有者をクライアントへリダイレクトさせます。そのリダイレクトでリソース所有者は認可コードをクライアントへ渡します。認可コードを受け取ったクライアントは、その認可コードを使って認可サーバーからアクセストークンを取得します。
何故、わざわざ認可サーバーはリソース所有者へ、アクセストークンではなく認可コードを渡すのかというと、リソース所有者にアクセストークンを渡さないためです。もしリソース所有者が第3者の端末で操作していた場合、第3者の端末にアクセストークンが保存されてしまい、情報漏洩が起きてしまいます。
おわりに
OAuth2.0は世の中の幅広いユースケースに対応するために、アクセストークンの受け渡し手順に特化して仕様が定められています。そのため、アクセストークンの中身がどうなっているのか、アクセストークンの検証方法など、多くの仕様がOAuth2.0で定められておらず、認可サーバーによって実装が異なります。その柔軟さが多くの環境でOAuth2.0が利用される要因でもあり、実際にOAuth2.0を構築する際のハードルになっていると感じます。
冒頭でも述べた通り、OAuth2.0では認証は想定していません。認証はOAuth2.0を拡張したOpen ID Connectで行います。次回はOpen ID Connectについてお話ししたいと思います。
ではまた。