メモ
GitHub Appの代わりにOAuth appを構築することを検討してください。
OAuth appsとGitHub Appsの両方で OAuth 2.0 が使用されます。
GitHub Apps は、OAuth app と同様にユーザーに代わって動作することも、自身として動作することもでき、これはユーザー入力を必要としない自動化に役立ちます。 さらに、きめ細かいアクセス許可 GitHub Apps 使用し、アプリがアクセスできるリポジトリをより細かく制御し、有効期間の短いトークンを使用できるようにします。 詳細については、「GitHub アプリと OAuth アプリの違い」および「GitHub アプリの作成について」を参照してください。
GitHub's OAuth 実装では、Web ブラウザーにアクセスできないアプリに対して、標準の 承認コード付与の種類 と OAuth 2.0 デバイス承認付与 がサポートされています。
アプリケーションをテストする場合のように、標準的な方法でのアプリケーションの認可をスキップする場合は、非 Web アプリケーション フローを利用できます。
OAuth appを承認するには、アプリに最適な承認フローを検討します。
- Web アプリケーション フロー: ブラウザーで実行される標準 OAuth apps のユーザーを承認するために使用されます。 (暗黙的な許可の種類はサポートされていません。)
- デバイスフロー: CLI ツールなど、ヘッドレス アプリケーションに使われます。
Web アプリケーションフロー
メモ
GitHub アプリをビルドする場合でも、OAuth Web アプリケーション フローを使用できますが、セットアップにはいくつかの重要な違いがあります。 詳細については、「ユーザーに代わってGitHub アプリで認証する」を参照してください。
アプリケーションのユーザの認可のためのWebアプリケーションフローは以下のとおりです。
- ユーザーは、GitHub ID を要求するようにリダイレクトされます
- ユーザーは、GitHubによってサイトにリダイレクトされます
- アプリケーションはユーザのアクセストークンと共にAPIにアクセスします
1. ユーザーのGitHub ID を要求する
GET http(s)://HOSTNAME/login/oauth/authorize
このエンドポイントは、次の入力パラメーターを受け取ります。
| Query parameter (クエリ パラメーター) | タイプ | 必須 | 説明 |
|---|---|---|---|
client_id | string | 必須 | |
| 登録したときに GitHub から受け取ったクライアント ID。 | |||
redirect_uri | string | 強く推奨 | 認可の後にユーザが送られるアプリケーション中のURL。 |
| リダイレクト URL に関する詳細については、下を参照してください。 | |||
login | string | 省略可能 | サインインとアプリケーションの認可に使われるアカウントを指示します。 |
scope | string | コンテキスト依存 | |
| スコープのスペース区切りリスト。 | |||
scope が提供されていない場合、アプリケーションに対していかなるスコープも認可していないユーザーには、既定で空のリストが使用されます。 アプリケーションに対して認可したスコープがあるユーザに対しては、スコープのリストを含むOAuthの認可ページは示されません。 その代わりに、フローのこのステップはユーザがアプリケーションに認可したスコープ群で自動的に完了します。 たとえば、ユーザーが既に Web フローを 2 回実行しており、1 つのトークンで user スコープを、もう 1 つのトークンで repo スコープを認可している場合、3 番目の Web フローで scope が渡されなければ、user および repo スコープを持つトークンが返されます。 | |||
state | string | 強く推奨 | 推測不能なランダムの文字列。 クロスサイトリクエストフォージェリ攻撃に対する保護として使われます。 |
allow_signup | string | 省略可能 | 認証されていないユーザーに、OAuth フロー中にGitHubにサインアップするオプションが提供されるかどうか。 既定値は、true です。 ポリシーでサインアップが禁止されている場合は、false を使用します。 |
prompt | string | 省略可能 | |
select_account に設定されている場合、アカウント ピッカーを強制的に表示します。 アカウント ピッカーは、アプリケーションに HTTP 以外のリダイレクト URI がある場合、またはユーザーにサインイン済みのアカウントが複数ある場合にも表示されます。 |
現時点では、PKCE (Proof Key for Code Exchange) パラメーターcode_challengeおよびcode_challenge_methodはサポートされていません。
現時点では、CORS のフライト前要求 (OPTIONS) はサポートされていません。
2. ユーザーは、GitHubによってサイトにリダイレクトされます
ユーザーがリクエストを承認すると、GitHub によって、code パラメーター内の一時的な code と、state パラメーター内の前の手順で指定した状態とともに、お客様のサイトにリダイレクトされます。 一時コードは10分後に期限切れになります。 状態が一致しない場合は、リクエストがサードパーティによって作成されたものであるため、プロセスを中止する必要があります。
この code をアクセス トークンと交換します。
POST http(s)://HOSTNAME/login/oauth/access_token
このエンドポイントは、次の入力パラメーターを受け取ります。
| パラメーター名 | タイプ | 必須 | 説明 |
|---|---|---|---|
client_id | string | 必須 | お客様のGitHub用にOAuth appから受け取ったクライアント ID。 |
client_secret | string | 必須 | |
| GitHub から OAuth app 用に受け取ったクライアント シークレット。 | |||
code | string | 必須 | 手順 1 に対する応答として受け取ったコード。 |
redirect_uri | string | 強く推奨 | 認可の後にユーザが送られるアプリケーション中のURL。 これを使用して、code が発行されたときに最初に指定された URI と照合して、サービスに対する攻撃を防ぐことができます。 |
デフォルトでは、レスポンスは以下の形式になります。
access_token=gho_16C7e42F292c6912E7710c838347Ae178B4a&scope=repo%2Cgist&token_type=bearer
Accept ヘッダーに形式を指定した場合は、別の形式で応答を受け取ることもできます。 たとえば、Accept: application/json または Accept: application/xml です。
Accept: application/json
{
"access_token":"gho_16C7e42F292c6912E7710c838347Ae178B4a",
"scope":"repo,gist",
"token_type":"bearer"
}
Accept: application/xml
<OAuth>
<token_type>bearer</token_type>
<scope>repo,gist</scope>
<access_token>gho_16C7e42F292c6912E7710c838347Ae178B4a</access_token>
</OAuth>
3. アクセス トークンを使って API にアクセスする
このアクセストークンを使えば、ユーザの代わりにAPIへのリクエストを発行できます。
Authorization: Bearer OAUTH-TOKEN
GET http(s)://HOSTNAME/api/v3/user
たとえば、curlでは以下のようにAuthorizationヘッダを設定できます。
curl -H "Authorization: Bearer OAUTH-TOKEN" http(s)://HOSTNAME/api/v3/user
アクセス トークンを受信するたびに、トークンを使用してユーザー ID を再検証する必要があります。 アプリを承認するために送信するときにユーザーはサインインしているアカウントを変更できます。サインインするたびにユーザー ID を検証しないと、ユーザー データが混在するリスクがあります。
デバイスフロー
デバイスフローを使えば、CLIツールやGit資格情報マネージャーなどのヘッドレスアプリケーションのユーザを認可できます。
デバイス フローを使用してユーザーを認可および特定するには、まずアプリケーションの設定でデバイス フローを有効にする必要があります。 アプリでデバイス フローを有効にする方法の詳細については、「の GitHub Apps」と「OAuth apps」を参照してください。
デバイスフローの概要
- アプリケーションはデバイスとユーザの検証コードをリクエストし、ユーザがユーザ検証コードを入力する認可URLを取得します。
- アプリは、
http(s)://HOSTNAME/login/deviceでユーザー確認コードを入力するようにユーザーに求めます。 - アプリケーションはユーザ認証のステータスをポーリングします。 ユーザがデバイスを認可すると、アプリケーションは新しいアクセストークンと共にAPIコールを発行できるようになります。
手順 1: アプリがデバイスとユーザーの確認コードをGitHubに要求する
POST http(s)://HOSTNAME/login/device/code
アプリケーションは、次のステップでユーザに認可を求めるために使うユーザ検証コードと検証URLをリクエストしなければなりません。 このリクエストには、アプリケーションがアクセストークンの受け取りとユーザの認可のステータスチェックに使わなければならないデバイス検証コードも返されます。
このエンドポイントは、次の入力パラメーターを受け取ります。
| パラメーター名 | タイプ | 説明 |
|---|---|---|
client_id | string | |
| 必須。 アプリの GitHub から受け取ったクライアント ID。 | ||
scope | string | アプリがアクセスを要求しているスコープのスペース区切りのリスト。 詳しくは、「OAuth アプリのスコープ」をご覧ください。 |
デフォルトでは、レスポンスは以下の形式になります。
device_code=3584d83530557fdd1f46af8289938c8ef79f9dc5&expires_in=900&interval=5&user_code=WDJB-MJHT&verification_uri=https%3A%2F%2FHOSTNAME%2Flogin%2Fdevice
| パラメーター名 | タイプ | 説明 |
|---|---|---|
device_code | string | デバイス検証コードは40文字で、デバイスの検証に使われます。 |
user_code | string | ユーザ検証コードは、ユーザがブラウザに入力できるようにデバイスに表示されます。 このコードは8文字で、途中にハイフンがあります。 |
verification_uri | string | ユーザーが user_code: http(s):/を入力する必要がある確認 URL。 |
expires_in | integer | |
device_code と user_code の有効期限か切れるまでの秒数。 デフォルトは900秒、すなわち15分です。 | ||
interval | integer | デバイスの認可を完了するために新しいアクセス トークンのリクエスト (POST http(s):/) を発行する前に経過する必要がある最小秒数。 たとえばintervalが5であれば、5秒が経過するまでは新しいリクエストを発行できません。 5 秒間に複数のリクエストを発行すると、レート制限に達して slow_down エラーが返されます。 |
Accept ヘッダーに形式を指定した場合は、別の形式で応答を受け取ることもできます。 たとえば、Accept: application/json または Accept: application/xml です。
Accept: application/json
{
"device_code": "3584d83530557fdd1f46af8289938c8ef79f9dc5",
"user_code": "WDJB-MJHT",
"verification_uri": "http(s)://HOSTNAME/login/device",
"expires_in": 900,
"interval": 5
}
Accept: application/xml
<OAuth>
<device_code>3584d83530557fdd1f46af8289938c8ef79f9dc5</device_code>
<user_code>WDJB-MJHT</user_code>
<verification_uri>http(s)://HOSTNAME/login/device</verification_uri>
<expires_in>900</expires_in>
<interval>5</interval>
</OAuth>
ステップ2: ブラウザでユーザコードの入力をユーザに促す
デバイスにユーザー確認コードが表示され、 http(s)://HOSTNAME/login/deviceでコードを入力するようにユーザーに求められます。
手順 3: アプリがGitHubをポーリングして、ユーザーがデバイスを承認したかどうかを確認する
POST http(s)://HOSTNAME/login/oauth/access_token
アプリケーションでは、デバイスおよびユーザー コードが期限切れになるか、有効なユーザー コードでアプリケーションが認可されるまで、POST http(s)://HOSTNAME/login/oauth/access_token をポーリングするデバイス認可リクエストを発行します。 アプリケーションでは、レート制限エラーを避けるために、ステップ 1 で取得したポーリングの最小 interval を使います。 詳細については、「デバイス フローのレート制限」を参照してください。
ユーザは、15分(あるいは900秒)以内に有効なコードを入力しなければなりません。 15 分が経過すると、新たなデバイス認可コードを POST http(s)://HOSTNAME/login/device/code でリクエストしなければなりません。
ユーザが認可されると、アプリケーションはユーザの代わりにAPIにリクエストを発行するために利用できるアクセストークンを受け取ります。
このエンドポイントは、次の入力パラメーターを受け取ります。
| パラメーター名 | タイプ | 説明 |
|---|---|---|
client_id | string | |
| 必須。 | ||
| GitHub用にOAuth appから受け取ったクライアントID。 | ||
device_code | string | |
| 必須。 | ||
device_code 要求から開発者が受け取った POST http(s):/。 | ||
grant_type | string | |
必須。 付与タイプは urn:ietf:params:oauth:grant-type:device_ でなければなりません。 |
デフォルトでは、レスポンスは以下の形式になります。
access_token=gho_16C7e42F292c6912E7710c838347Ae178B4a&token_type=bearer&scope=repo%2Cgist
Accept ヘッダーに形式を指定した場合は、別の形式で応答を受け取ることもできます。 たとえば、Accept: application/json または Accept: application/xml です。
Accept: application/json
{
"access_token": "gho_16C7e42F292c6912E7710c838347Ae178B4a",
"token_type": "bearer",
"scope": "repo,gist"
}
Accept: application/xml
<OAuth>
<access_token>gho_16C7e42F292c6912E7710c838347Ae178B4a</access_token>
<token_type>bearer</token_type>
<scope>gist,repo</scope>
</OAuth>
デバイスフローのレート制限
ユーザがブラウザ上で検証コードをサブミットする場合、アプリケーションごとに1時間に50回のサブミットというレート制限があります。
リクエスト間で要求される最小の時間間隔 (つまり POST http(s)://HOSTNAME/login/oauth/access_token) 内で複数のアクセス トークン リクエスト (interval) を発行すると、レート制限に達し、slow_down エラー応答が返されます。
slow_down エラー応答によって、最後の interval に 5 秒が追加されます。 詳細については、「デバイス フローのエラー コード」を参照してください。
デバイスフローのエラーコード
| エラー コード | 説明 |
|---|---|
authorization_ | このエラーコードは、認可リクエストが保留中で、ユーザがユーザコードをまだ入力していない場合に生じます。 アプリケーションには、POST http(s):/ を超えない範囲で interval リクエストをポーリングし続けることが期待されます。この際には、リクエスト間に最小の秒数を空けることが必要です。 |
slow_down | |
slow_down エラーが返された場合、最小の interval、あるいは POST http(s):/ を使用するリクエスト間に必要な時間間隔に 5 秒が追加されます。 たとえば、開始時の間隔としてリクエスト間に最小で 5 秒が必要だった場合に、slow_down エラー応答が返されると、OAuth アクセス トークンを求める新しいリクエストの発行までに最短でも 10 秒待たなければならなくなります。 エラー応答には、使用する必要がある新しい interval 情報が含まれます。 | |
expired_token | デバイス コードの有効期限が切れた場合は、token_expired エラーが表示されます。 デバイスコードを求める新しいリクエストを発行しなければなりません。 |
unsupported_grant_ | OAuth トークン リクエストの urn:ietf:params:oauth:grant-type:device_ でポーリングする際には、付与タイプを POST http(s):/ として、入力パラメーターに含めなければなりません。 |
incorrect_client_ | デバイスフローでは、アプリケーションのクライアントIDを渡さなければなりません。これは、アプリケーションの設定ページにあります。 デバイス フローに client_secret は必要ありません。 |
incorrect_device_ | 渡されたdevice_codeが有効ではありません。 |
access_denied | 認可プロセス中にユーザーがキャンセルをクリックした場合、access_denied エラーが返され、ユーザーは検証コードを再度利用することができなくなります。 |
device_flow_disabled | アプリケーションの設定で、デバイス フローが有効になっていません。 詳細については、「デバイス フロー」を参照してください。 |
詳細については、「OAuth 2.0 Device Authorization Grant」(OAuth 2.0 デバイス認可の付与) を参照してください。
非Webアプリケーションフロー
テストのような限定的な状況では、非Web認証が利用できます。 必要に応じて、基本認証を使用して、personal access tokenの設定ページからpersonal access tokenを作成できます。 この手法を使えば、ユーザはいつでもアクセスを取り消せます。
リダイレクト URI
redirect_uri パラメーターは省略可能です。 省略した場合、GitHub は OAuth app で設定されたコールバック URL にユーザーをリダイレクトします。
設定。 指定する場合、リダイレクト URL のホスト (サブドメインを除く) とポートは、コールバック URL と完全に一致している必要があります。 リダイレクト URL のパスは、コールバック URL のサブディレクトリを参照していなければなりません。
CALLBACK: http://example.com/path
GOOD: http://example.com/path
GOOD: http://example.com/path/subdir/other
GOOD: http://oauth.example.com/path
GOOD: http://oauth.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
ループバック リダイレクト URL
オプションredirect_uriパラメーターは、デスクトップ コンピューターで実行されているネイティブ アプリケーションに便利なLoopback URL にも使用できます。 アプリケーションでループバック URL とポートを指定した場合、アプリケーションを認可した後、ユーザーは指定した URL とポートにリダイレクトされます。
redirect_uri は、アプリのコールバック URL で指定されたポートと一致している必要はありません。
http://127.0.0.1/pathコールバック URL については、アプリケーションがポートredirect_uriでリッスンしている場合にこの1234を使用できます。
http://127.0.0.1:1234/path
OAuth の RFC では、localhost の使用は推奨されておらず、代わりにループバック リテラル 127.0.0.1 または IPv6 ::1 を使うことが推奨されています。
の複数のトークンを作成する OAuth apps
ユーザ/アプリケーション/スコープの組み合わせに対して複数のトークンを作成し、特定のユースケースに対応できます。
これは、OAuth appがサインインにGitHubを使用し、基本的なユーザー情報のみを必要とする 1 つのワークフローをサポートしている場合に便利です。 別のワークフローはユーザのプライベートリポジトリへのアクセスを必要としていてもかまいません。 複数のトークンを使用すると、 OAuth app はユース ケースごとに Web フローを実行し、必要なスコープのみを要求できます。 ユーザーがアプリケーションのみを使用してサインインする場合、プライベート リポジトリへのアクセス権を OAuth app に付与する必要はありません。
ユーザー/アプリケーション/スコープの組み合わせごとに、1 時間あたり作成されるトークン数には 10 という上限があります。 アプリケーションで同じユーザーと同じスコープに対して 10 個を超えるトークンが作成された場合、同じユーザー/アプリケーション/スコープの組み合わせを持つ最も古いトークンが取り消されます。 ただし、時間単位のレート制限に達しても、最も古いトークンは取り消されません。 代わりに、ブラウザー内で再承認プロンプトがトリガーされ、ユーザーはアプリに付与しているアクセス許可を再確認するよう求められます。 このプロンプトは、アプリが 1 時間以内にユーザーに 10 個のトークンを要求する理由がほとんどないため、アプリが陥っている可能性のある無限ループを中断させることを目的としています。
警告
OAuth app からすべてのアクセス許可を取り消すと、ユーザーの代わりにアプリケーションで生成されたすべての SSH キー (配置キーを含む) が削除されます。
ユーザにアクセスをレビューしてもらう
ユーザーがアプリケーションの承認を確認して取り消すことができるように、 OAuth app の認証情報にリンクできます。
このリンクをビルドするには、アプリケーションの登録時にGitHubから受け取ったOAuth appのclient_idが必要です。
http(s)://HOSTNAME/settings/connections/applications/:client_id
ヒント
OAuth appがユーザーにアクセスできるリソースの詳細については、「ユーザのリソースを調べる」を参照してください。