ぺい

渋谷系アドテクエンジニアの落書き

GithubのOAuth2.0の仕様について理解する(Githubログイン)

あの楽ちんなGithubログインボタン

結構前からですが、他のSNSサービスや比較的数多くのアカウント登録数を持っているサービスが採用しているOAuth2.0ですけど、自分が関わっているプロダクトで使う必要が出てきたので、仕様と使い方にGithubの公式ドキュメントを読みながらまとめてみた。
OAuth | GitHub Developer Guide

公式ドキュメントの大体合ってる日本語訳

※実際の翻訳と異なることが多少あります。大体そんな感じという日本語訳です。

OAuth2は外部アプリケーションがユーザーのGithubアカウントが持っているプライベートな情報にパスワードなしで情報にアクセスすることが出来るプロトコルです。トークンは特定のタイプのデータに限定でき、ユーザーはそのトークンをいつでも消せるということらしい。このトークン仕組みははBasic認証よりも良いですよ?みらいなことが書いてある。

つまり、トークンとやらを発行して、そのトークンを使うことで許可された範囲で操作出来るよってことらしい。Basic認証よりイケてるからみんな使ってこうぜ!的なことが言いたいのだと思う。

全ての開発者は、これを利用する前にアプリケーションの登録をする必要があります。登録されたOAuthアプリケーションのには、固有のClient IDとClient Secretが割り当てられます。
※このClient Secretは絶対に共有しないでください! 開発者の自身で使用するための個人アクセストークンを作成したり、以下に紹介するフローを実装することで、他のユーザーがアプリケーションを許可することが出来ます。

ここで出たClient Secretは間違って、Githubとかに上げると悪用されるので、公開しないようにしてくださいという意味だと思われる。

GithubのOAuth実装は、authorization code grant typeをサポートしています。開発者は以下で説明するWebアプリケーションフローを実装して、認証コードを取得し、それをトークンに交換する必要があります。(implicit grant typeはサポートしていません)

Webアプリケーションでのフロー

f:id:tikasan0804:20170502231453p:plain 大体こんな感じだと思う。

1.ユーザーはリダイレクトでGithubへアクセスする

GET https://github.com/login/oauth/authorize

設定できるパラメーター

*は必須という意味です。

Name Type 説明
client_id * string 登録時にい発行されたクライアントID
redirect_uri string 承認後にユーザーのリダイレクト先。(アプリケーションURL)
scope string scopeスペースで区切られたスコープのリスト。scopeは空の場合は、アプリケーションのscopeを許可していないユーザーの空リストにデフォルトで設定されます。アプリケーションのscopeを承認したユーザーの場合は、scopeのリストを含むOAuth認証ページは表示されません。その代わり、このフローでは、ユーザーのアプリケーションに対しての承認を自動的に処理する。
state string サイト間のやり取りをする際のCSRF対策に使うランダムな文字列。これが漏れると攻撃されるので、取扱には気をつけたい。
allow_signup string 認証されていないユーザーに、OAuthフロー中にGithubにサインアップするオプションを提供するかどうかを設定する。つまり、認証フローに入る前からGithubにログイン済みのユーザーしか許可しないかどうかを決定するようです。もし、許可する場合はデフォルトで設定されているtrueで、許可したくない場合はfalseとするようです。

補足

redirect_uri
リダイレクトのURLには以下のようなルールがあります。

OAuth | GitHub Developer Guide

CALLBACK: http://example.com/path

GOOD: http://example.com/path
GOOD: http://example.com/path/subdir/other
BAD:  http://example.com/bar
BAD:  http://example.com/
BAD:  http://example.com:8080/path
BAD:  http://oauth.example.com:8080/path
BAD:  http://example.org

示されている例が少し分かりにくかったので、ありそうな例を書きました。

http://localhost/login

◯http://localhost/login/callback
×http://localhost/callback

scope

OAuth | GitHub Developer Guide

このscopeというのは、アプリケーションから取得または操作を許可する範囲のことを指している。
例えば、何も設定をしないno scopeの場合は、公開されている情報に読み取り専用でアクセスを許可されたり、user:emailなどにすると、ユーザーがGithubに登録しているメールアドレスへアクセスが出来るなど。様々なレベルのscopeがあるので、必要に応じて設定すると良いらしい。

2.Githubからアプリケーションにリダイレクトする

POST https://github.com/login/oauth/access_token

ユーザーがリクエストを受け入れると、Githubcodeパラメーターの一時コードと1の手順で指定したstateをパラメーターに指定したアプリケーションにリダイレクトされます。この時にstateが違った場合は攻撃の可能生が高いため、OAuthのフローを中止するべきです。

設定できるパラメーター

*は必須という意味です。

Name Type 説明
client_id* string アプリケーション登録時に発行されたclient_id
client_secret* string アプリケーション登録時に発行されたclient_secret
code* string 1の手順の応答で受け取る。tokenとの引き換え券のようなもの。
redirect_uri string 承認後にユーザーがリダイレクトされるアプリケーションのURL。リダイレクトのルールは先程紹介したものと同じです。

POST https://github.com/login/oauth/access_tokenへのレスポンス

access_token=e72e16c7e42f292c6912e7710c838347ae178b4a&scope=user%2Cgist&token_type=bearer 

Accept ヘッダーに応じて、様々な形式で受け取ることが出来ます。

 Accept: application/json {"access_token":"e72e16c7e42f292c6912e7710c838347ae178b4a", "scope":"repo,gist", "token_type":"bearer"} Accept: application/xml <OAuth> <token_type>bearer</token_type> <scope>repo,gist</scope> <access_token>e72e16c7e42f292c6912e7710c838347ae178b4a</access_token> </OAuth>
3. tokenを使ってAPIへリクエストする

ここまでのフローで受け取ったaccess_tokenでAPIへリクエストが出来ます。
tokenは以下のようなパラメーターで渡すパターン。

GET https://api.github.com/user?access_token=...

HeaderのAuthorizationを使って渡すことも出来ます。

Authorization: token OAUTH-TOKEN

curlコマンドでは以下のようになります。

curl -H "Authorization: token OAUTH-TOKEN" https://api.github.com/user

なんとなく分かった気がする。