OAuth2.0コトハジメ

はじめに

『世界のまん中が視たい』(意訳:Gmailをコンソールで読みたい)

コトは、そんな人類共通のささやかな夢からハジマッタ。

椎名林檎 - 自由へ道連れ from 真空地帯

今回はひとまず夢の実現は置いといて。

逸る命を抑えながら、名前しか知らない「OAuth2.0」について調べてみたよ。

しかも図まで描いてみた。

何かツッコミあればコメント下さいまし。

概要

OAuth2.0は認可のためのフレームワーク

「認証」とは、相手が誰なのかを確認すること。

「認可」とは、相手があるリソースへアクセスするのを許可すること。

OAuth2.0は、HTTPサービスをサードパーティ製アプリから利用することを想定した、「認可」フレームワークとのこと。

OAuth2.0を使うと何が嬉しいの?

OAuth2.0を使えば、HTTPサービスへの認証情報(IDやパスワードなど)をサードパーティ製のアプリに渡さなくて済む。

BASIC認証の場合

HTTPサービスを利用する場合、認証情報でサービスへ認証した後に個人的なリソースへアクセスできるようになる。

古典的な認証方式であるBASIC認証の場合、ユーザIDとパスワードという認証情報で認証する。

使用前に認証情報を直接入力させるアプリもあるけど、毎回入力するのって面倒だよね。

アプリによっては次回以降の入力を省くために認証情報を保存しておくかもしれない。
そしてそれが誰かに盗まれるかもしれない。

いや、そもそもそのアプリ自体、認証情報を盗むつもりの人が用意したトラップかもしれない。

いずれにせよ、認証情報が流出するリスクが増える
流出した場合、どこかの誰かが勝手にログインし、やりたい放題される危険がある。

OAuth2.0の場合

一方、OAuth2.0の場合、HTTPサービスへの認証情報をアプリに渡さない。

認証情報の代わりに、アクセス可能な範囲と有効期限が記されたチケットをアプリに渡す。
アプリはこのチケットを使って、HTTPサービスのリソースにアクセスできる。

もし仮に、このチケットが流出してしまったとしよう。
しかし、このチケットを使ってアクセスできるのは、予め許可した範囲内のリソースのみだ。
認証情報そのものが流出した場合よりは、被害範囲を限定できる
また、チケットには期限があり、リスクに晒される期間も限定できる

というのが、OAuth2.0を使う際のメリットとして大きく主張されているっぽい。

OAuth2.0を利用する流れ

OAuth2.0を利用する流れを図にしてみた。

f:id:hacolab:20200523105133p:plain

なお、以下の点に注意。

  • OAuth2.0の認可方式は4つ定義されている
    • 上図はそのうちの一つ「認可コードによる認可」
  • クライアントはPCネイティブアプリを想定
  • やりとりしているデータはあくまで抜粋
    • 具体的には各サービスの仕様を参照
  • リフレッシュトークンはオプション仕様
    • Googleは対応してるっぽいよ

OAuth2.0の標準仕様は以下を参照してね。
(以降、単に「仕様」といったらこの仕様のことだよ)

以降では、各フェーズを簡単に説明していく。

少し長めなので、興味がわいた人は読んでみて下さいな。

登場人物

今回の説明に出てくる人たち。

登場人物 人物紹介
リソースサーバーが提供するHTTPサービスの利用者。
クライアントからのリソースへのアクセスを認可するひとでもある。

あるHTTPサービスをクライアント経由で使いたいと考えている。
リソースサーバーが提供するHTTPサービスを利用するアプリケーション。

ネイティブアプリや、Webアプリ、その他の何かかもしれない。

HTTPサービス提供者とは別のサードパーティー製である場合、この子にHTTPサービスにログインするための認証情報を渡したくないというのが、OAuth2.0を使うモチベーションっぽい。
認可手続きの際に利用するアプリケーション。

一般的にはWebブラウザが想定されると思う。

公式も含め、OAuthの登場人物としてはあまり紹介されない不遇な子。
あるHTTPサービスを提供するひと。
もちろん、OAuthに対応しているサービスでなければならない。

Google系サービスとか、Twitterとか、Facebookとか。
OAuthによるリソースへのアクセスを認可する手続きを担うひと。

だいたいリソースサーバーを提供する会社が用意しているかと。

1. 事前準備

f:id:hacolab:20200522172922p:plain

OAuth2.0を利用するには、まずリソースオーナーは利用したいクライアントを認可サーバーに登録しなければならない。
登録が完了したら「クライアントID」を認可サーバーから発行してもらえる。

発行された「クライアントID」をクライアントに通知する方法はアプリによると思う。
上図では、ブラウザで表示された「クライアントID」をリソースオーナーがコピペするイメージ。

補足) GoogleAPIでのクライアント登録方法

GoogleAPIでOAuth2.0を利用する場合は、Google Consoleから登録するっぽい。
(プロジェクトを作成後、「認証情報を作成」メニューからっぽい)

下の記事が画面キャプチャ付きで分かりやすいかも。

qiita.com

しかし、GmailAPIなどの各API個別の設定画面にも「認証情報を作成」メニューがあるじゃないか。

どこから登録すべきなのか、僕は世界のまん中で愛を叫びたいくらい混乱している。

Gmailだけを使用するクライアントなら、個別APIで認証情報を作成した方がいいのかしら。

2. クライアントの認可

f:id:hacolab:20200522172926p:plain

概要で説明した通り、OAuth2.0ではリソースにアクセスする際に、スコープと有効期限が記されたチケットを使う。

仕様ではこのチケットのことを「アクセストークン」と呼んでいる。

それでは、OAuth2.0の肝である認可の流れと「アクセストークン」を受け取るまでの流れを見て行こう。

と、その前に。
上図では3つのエンドポイント(URI)が登場しているので、ちょっと意識して欲しい。

  • 認可エンドポイント(赤丸): 認可手続きを要求するURI
  • トークンエンドポイント(青丸): アクセストークンを要求するURI
  • リダイレクトエンドポイント(緑丸): 認可完了時の遷移先URI (仕様ではリダイレクトURIとも)

特に、認可サーバーといっても要求によって送り先が分けられている点は実際の利用時に注意したい。

認可

クライアントは「アクセストークン」を取得するため、まず先に認可してもらう必要がある。

認可の具体的な手順はアプリやサービスによると思う。
上図では、認可エンドポイントのURIをクライアントが生成して、それをWebブラウザで開いて認可手続きを行うイメージ。

クライアントが認可する工程に直接関わらないことによって、クライアントには認証情報を渡さなくて済むようになっている。

クライントは認可手続きが外部の何らかの方法で完了した後に、認可されたことを証明する「認可コード」というチケットを受け取ればいい。

補足) 認可コードを受け取る方法

面白いなと思ったのは、認可サーバーは認可完了時にクライアントが指定したURIにHTTPリダイレクトさせる点。
HTTPの302レスポンスと共に、パラメータとして「認可コード」を返すようになっている。

これはきっと「認可コード」をクライアントが受け取る方法は、クラアント開発者に委ねるということ。

その方法はもしかすると、リダイレクト先でWebブラウザに表示された「認可コード」を、ユーザーがコピペしてクライアントに教えるのかもしれない。

その方法はもしかすると、リダイレクト先から「認可コード」を自動でクライアントに通知するのかもしれない。

あー、選べる自由があるってステキ。

しかし、自由と一緒に、変なURIにリダイレクトさせられるリスクもやってきた。

あー、自由って難しい。。。

ただ、仕様では下のような対策が一部用意されているっぽい。

アクセストークンの取得

クライアントは「認可コード」を受け取ったら、それを認可サーバーのトークンエンドポイントに送る。
正しい「認可コード」であれば、「アクセストークン」「リフレッシュトークン」を受け取ることができる。

「リフレッシュトークン」は期限切れの「アクセストークン」を更新するときに使う。
詳細は後述「4. アクセストークンの更新」を見てね。

ちなみに「認可コード」の有効期限は短めで、仕様では10分以下推奨となっている。
期限切れの場合、再度認可を行うことになってしまう。

認可後の「アクセストークン」の取得はお早めに。

3. リソースアクセス

f:id:hacolab:20200522172931p:plain

リソースへのアクセスは簡単。

リソースサーバーに目的の操作リクエストと一緒に「アクセストークン」を送ればいい。

リソースサーバーは、「アクセストークン」の期限が有効なことや、リクエストが許可されたスコープ内であることを確認する。

問題なければ、リクエストされた操作を実行してレスポンスを返す。

補足) HTTPヘッダの参考例

ちなみに仕様では、リクエスト時のHTTPヘッダの例は以下のようになっている。
Bearerの後に「アクセストークン」を含めればいいっぽい。かんたん。

  GET /resource/1 HTTP/1.1
  Host: example.com
  Authorization: Bearer mF_9.B5f-4.1JqM

あくまで参考例なので、実際は各サービスの仕様を確認してねと。

4. アクセストークンの更新

f:id:hacolab:20200522172935p:plain

「アクセストークン」には有効期限がある。(Googleでは1時間っぽい)

期限が切れていると、リクエストは拒否されてリソースにはアクセスできない。
そんなときはトークンエンドポイントに「リフレッシュトークン」を送る。
そうすれば、新しい「アクセストークン」を受け取ることができる。

ただし「リフレッシュトークン」は仕様としてはオプション扱い。
対応有無は各サービスの仕様を確認しよう。

補足) Googleのリフレッシュトークン無効化条件

ちなみに、Googleは「リフレッシュトークン」に対応している。

Googleの場合、下記条件成立時に「リフレッシュトークン」が無効化されるっぽい。
無効になったときは、再度認可から行う必要があるかと。

  • ユーザーが認可を取り消した場合
  • リフレッシュトークンが6ヶ月間未使用の場合
  • 認証パスワードを変更し、スコープにGmailが含まれていた場合
  • リフレッシュトークンの最大数を超えた場合
    • 各クライアントのユーザーごとに50個まで? エイゴヨクワカラナイ
      • There is currently a limit of 50 refresh tokens per user account per client.
    • 普通はきっと超えないけど、開発者はテスト時に注意してねとのこと

developers.google.com

さいごに

以上がOAuth2.0(認可コードによる認可)の基本的な流れになる。

僕は全体の流れと、認可手続きの具体的な流れをイメージできるまで少し時間がかかった。

なので今回は、Webブラウザを予め登場人物に加え、画面1枚に収まるくらいの図を描いてみた。
スマホで見ると文字がちょっと小さいけど。

こんな記事でも、どこかの誰かの理解の助けになったのなら嬉しい。


それにしても、ネットの海にはOAuth2.0の説明記事が溢れかえっている。
日本語の記事も多くて、僕もたくさんお世話になった。

しかしいったいこれまで、似たような説明記事がどれだけ量産されてきたのだろう。

歴史は繰り返す。

そして今日も、オースの歴史が、また1ページ・・・

備考

  • 発音は『オーオース』が一般的っぽい
  • OAuth2.0の仕様発行は2012年と割と古い
  • OAuth2.0とOAuth1.0は別物っぽい
  • OAuth2.0を拡張したOpenID Connectなるものがあるっぽい

参考