この記事は、GitHub API v3 を利用する際のスコープの一覧(Scopes
)です。
- 「
Scope
???」という方はこちら→ #TS; DR
TL; DR (今北産業)
- GitHub API で利用できるスコープの和訳一覧を載せてます。
- GitHub API における「スコープ」とはアクセス権のようなものです。
(詳しくは TL; DR 参照) - 複数スコープを指定したい場合は、スペース区切り(
%20
1)で指定します。- 例:
?scope=user%20public_repo
- 例:
GitHub API で利用可能な「scope
」
基本的に GitHub の「scope
」は Allowed List
方式(ホワイト・リスト方式)です。
つまり「基本的に全てをブロック」しておき「許可されたものだけ通す」タイプです。GitHub の場合、scope
の指定がない場合は「該当するユーザーの公開情報のみ読み取り可能」な設定になっています。
そのため公開情報の閲覧以上の権限が必要な場合は、あらかじめ scope
の範囲をリクエスト URL に添えて、対象ユーザーから許可を得る必要があります。(詳しくは TS; DR 参照)
以下は(2018/03/20 時点の)GitHub の Scopes
仕様ページから一部を抜粋して翻訳・加筆したものです。
スコープ名 | スコープ対象 | 権限 | 備考 |
---|---|---|---|
(指定なし) | 公開ユーザープロファイル、公開リポジトリ情報、公開 gist | 読み取りを許可 | (指定なし、デフォルト) |
repo |
公開/非公開/Organization リポジトリ | 読み取り/書き込みを許可 |
repo コード/コミットステータス/招待/共同編集者、チームメンバーの追加/デプロイのステータス |
repo:status |
公開/非公開リポジトリ、コミットステータス | 読み取り/書き込を許可 |
repo:status このスコープは、コードへのアクセスを許可しないで、他のユーザーまたはサービスに非公開リポジトリのコミット状況へのアクセスを許可する場合のみ必要です。 |
repo_deployment |
公開/非公開リポジトリ、デプロイ・ステータス | 読み取りを許可 |
repo_deployment このスコープは、コードへのアクセスを許可しないで、他のユーザーまたはサービスにデプロイ・ステータスへのアクセスを許可する場合のみ必要です。 |
public_repo |
公開リポジトリおよび Organization | 読み取り/書き込みを許可 |
public_repo 公開リポジトリにスターを付ける場合にも必要です。 (コード、コミットステータス、共同作業者、およびデプロイ・ステータス) |
repo:invite |
リポジトリでコラボレーションするための招待状 | 招待状の受け入れ/拒否の機能を許可 |
repo:invite このスコープは、コードへのアクセスを許可しないで、招待へのアクセスを他のユーザーまたはサービスに許可する場合のみ必要です。 |
admin:org |
Organization、チーム、メンバーシップ | 完全な管理を許可 |
admin:org |
write:org |
Organization のメンバーシップ | 公開/非公開を許可 |
write:org |
read:org |
Organization やチームのメンバーシップ | 読み取りを許可 |
read:org |
admin:public_key |
公開鍵 | 完全な管理を許可 |
admin:public_key |
write:public_key |
公開鍵 | 作成、一覧表示、および詳細表示を許可 |
write:public_key |
read:public_key |
公開鍵 | 一覧と詳細の表示を許可 |
read:public_key (作成は含まない) |
admin:repo_hook |
公開/非公開リポジトリのフック | 読み取り/書き込み/ping/削除を許可 |
admin:repo_hook |
write:repo_hook |
公開/非公開リポジトリのフック | 読み取り/書き込み/ping を許可 |
write:repo_hook (削除以外を許可) |
read:repo_hook |
公開/非公開レポジトリのフック | 読み取り/ping を許可 |
read:repo_hook (書き込みと削除以外を許可) |
admin:org_hook |
Organization のフック | 読み取り/書き込み/ping/削除を許可 |
admin:org_hook 注: OAuth トークンは、OAuth アプリによって作成された Organization フックでのみ、これらのアクションを実行できます。個人のアクセストークンは、ユーザーが作成した組織のフックでのみ、これらの操作を実行できます。 |
gist |
Gist | 書き込みを許可 |
gist |
notifications |
ユーザー通知 | 読み取りを許可 |
notifications repo スコープもこれと同じアクセス権を提供します。 |
user |
ユーザーのプロファイル情報 | 読み取り/書き込みを許可 |
user user:email とuser:follow のスコープにも同じアクセス権が含まれます。 |
read:user |
ユーザーのプロファイル情報 | 読み取りを許可 |
read:user |
user:email |
ユーザーの電子メールアドレス | 読み取りを許可 |
user:email |
user:follow |
他のユーザー | フォロー/アンフォローを許可 |
user:follow |
delete_repo |
管理可能なリポジトリ | 削除を許可 |
delete_repo |
write:discussion |
チームディスカッション | 読み取り/書き込みを許可 |
write:discussion |
read:discussion |
チームディスカッション | 読み取りを許可 |
read:discussion |
admin:gpg_key |
GPGキー | 完全な管理を許可 |
admin:gpg_key |
write:gpg_key |
GPGキー | 作成/一覧表示/詳細表示を許可 |
write:gpg_key |
read:gpg_key |
GPGキー | 一覧/詳細表示を許可 |
read:gpg_key |
TS; DR (スコープを完全に理解した気になるコマケーこと)
実際に触れる GitHub API のスコープを利用したデモも後半で出てきますが、「ふいんき」で利用してセキュリティで失敗しないためにも、安心して使えるように最低限の基礎知識を先に紹介します。
スコープとは
API におけるスコープとはアクセス権のようなもの
英語の scope
(スコープ)には「対象を絞る」「指定された範囲」「それに注力」「それを注視」と言った意味合いがあります。
例えば、プログラムなどでは「スコープ」は「変数のスコープ」といった使われ方をします。関数内で宣言された変数は、関数の外からアクセスできないといった「範囲を示す」使われ方です。
GitHub API における「スコープ」(Scope
)とは「API で利用できる範囲を定めるために指定する項目」です。
顕微鏡の「スコープ」よりは、ゴルゴ(13)氏や、ボトムズのスコープドッグがターゲットに狙いを定める「スコープ」の方の意味合いに近く、スコープ内にあるものを狙います。スコープ外のものは眼中にありません。
つまり、実質的には API 版のアクセス権のようなイメージが近いかと思います。
アクセス・トークンとは
さて、GitHub に限らず API へのアクセスで重要なのがアクセス・トークンです。
GitHub OAuth App や GitHub App といった、GitHub の API を使った自作アプリの場合、まずはユーザーに承認してもらい、次にアプリは GitHub からアクセス・トークンを取得することになります。
もちろんユーザーが手動で発行したアクセス・トークン(プライベート・アクセストークンもしくはパーソナル・アクセストークン)をもらう方法でも可能です。
どの方法にしろアクセス・トークンを取得できたら、このアクセス・トークンを使い、ユーザーに替わってリポジトリやアカウントの操作をアプリから GitHub API 経由で行えます。
トークン(token
)とは
特定の世界、業界、コミュニティでしか通用しない「何か」によって価値が示された発行物をトークンと言います。
その「何か」は、物理的なもの・紙に書かれたもの・データなど、形態は関係ありませんが「プロトコルが同じ場合に有効なもの」です。
ここでいうプロトコルとは「事前の合意」です。
例えば、物理的なものではモノポリーやトランプなどのゲームで使われるチップだったり、イベント内でしか使えない入場コインや、パーティの食券などです。
モノポリーで使われるコインをパチスロに持って行っても使えないように、共通の価値観を持った間でしか価値がありません。吉野家のチケットを松屋に持って行っても使えないのも同様です。
そのため「コミュニティ内」や「価値観が同じ者同士」で、合意があれば特定のトークンを通貨の代わりとしても使うことは可能です。しかし、汎用的に物々交換の代わりには使われないためトークン自体は通貨のことではありません。
「発行したものを、発行側が失効したり、無効にできる」という点もトークンの 1 つの特徴です。
例えば、ポイント・カードの「ポイント」と「トークン」との違いですが、「なんとかポイント」の場合は、ポイント自体は無効にはできず「アカウントのポイント数の増減をしているだけ」です。逆に「シリアル番号 ●● 番のチケットは無効」といったことができるのがトークンです。
【学習ポイント】
「トークン」と言われたら「他では使えない、ここだけの発行物」と考えてください。
コンピューターにおけるトークンは、基本的に数値や文字列などの数桁〜数十桁の小さなデータ(数値)です。連番のこともあれば、ランダムな数値の場合もありますが、桁数が多いと扱い辛いことから HEX 文字列(16進数の数値の文字列)が多く使われます。
例えば、機械学習などでは文書をブツ切りにしたデータ(単語や文節など)やパターンに付けた ID のようなものをトークンと呼んだりします。ID と呼ばずにトークンと呼ぶのは、その処理限りの番号で、次の処理や他の学習モデルではその番号は意味を持たないからです。
連番の場合だとセキュリティ的に問題がある場合、つまり番号が予測されると処理が乗っ取られるようなケースでは、予測不可能で、かつ扱いやすいものという観点からハッシュ値が多く使われます。
そして「アクセス・トークン」は、いわばアクセスに必要な通行証や入場チケットのようなものです。データにアクセスするのに必要なものであるため「アクセス・トークン」と呼ばれます。
ただの数値でしかありませんが、ユーザと API 間で意味(価値)のあるものとして「トークン」と呼びます。GitHub API のアクセス・トークンでは Qiita API のアクセス・トークンとして使えないのもトークンの特徴です。
パスワードと似ており、用途も守秘性の重要度もほぼ同じです。違いは、一般的に「アクセス・トークンはアクセスを監視する側が発行する」のと、「自分で決められない」「長ったらしくて覚えられない」くらいの違いです。銀行のワンタイム・パスワードを、海外ではトークンと呼ぶのもそのためです。
「GitHub アカウントでログイン」は応用技
「GitHub ログイン」、つまり「GitHub のアカウントでログインできる仕組み」ですが、実は GitHub はダイレクトなログイン機能を提供しているわけではありません。
GitHub ログインを理解する前に、アクセストークンの取得方法について知る必要があります。具体的なサンプルは後述しますので、まずはザッと流れを見ましょう。
- あなたのアプリは、ユーザーを GitHub の認証ページにリンクで飛ばします。
この時、事前に GitHub に登録して発行した、あなたのアプリ ID(クライアント ID)もリンクの URL に含めておきます。 - ユーザーは GitHub にログインし、あなたのアプリを承認します。
- 承認されると GitHub は指定された URL に承認コード付きで飛ばし返します。
- あなたのアプリは、3の URL から承認コードを読み取り、GitHub にリクエストするとアクセストークンが取得できます。
上記の流れを OAuth といいます。
そして、上記のステップ 4 で「あなたのアプリがアクセス・トークンを取得できた」ということは、その前の1〜3の段階で「ユーザーは GitHub にログインできた」かつ「ユーザーはあなたのアプリを承認した」ということです。
このプロセスを経て、アクセス・トークンが取得できたらログインしたとみなす、「応用技」的な仕組みを OAuth ログインと言います。GitHub ログインは、この OAuth ログイン・タイプのログインを使ったものです。
逆に言うと「GitHub ログインを実装する」と言うことは「アクセス・トークンも取得できる」ということでもあります。本来はそれが目的の仕組みなんですが。
家の鍵を預けるようなもの
ここまでで、あなたのアプリはユーザーから許可(承認)をもらい、受け取ったコードを使って、GitHub にリクエストするとアクセストークンが発行される流れがザクっと理解できたと思います。
「GitHub アカウントを持つユーザーのみログインさせたい」と思うも、アクセス・トークンを取得できるということは、「ユーザーが GitHub で出来ることをアプリからでも出来てしまう」ということでもあります。
自分のサイトやサービスの「ログインの外部認証システム」として GitHub を利用したいだけなのに、ユーザーの変わりに GitHub の操作もできてしまうのです。
「アクセストークンの発行」は「ユーザーが利用しているサービスへの鍵を預る」という事と同意です。「パスワードと違うし」と舐めてかかると痛い目を見ます。
つまり、あなたのアプリが「どこまで操作させてもらえるか」を提示して、ユーザーから許可をもらうことが重要となります。
この、アクセス・トークンに紐づいた、操作できる範囲が「スコープ」になります。
いずれの利用法にしても、提示したスコープの範囲にユーザーが同意し許可を得られるとアクセストークンの発行依頼が可能になり、アクセストークンが発行されると、スコープ内の範囲でユーザーの代理で GitHub の操作がアプリから可能になります。
スコープの指定の仕方
さて、具体的なスコープの指定はリンク先の URL に含めます。
Web サイトやアプリなどで見る「GitHub でログイン」などのアレです。実際に触れるデモは後述しますが、以下は、その URL の例です。
https://github.com/login/oauth/authorize?client_id=$OAUTH2_CLIENT_ID&scope=user%20public_repo
上記 URL を分解すると以下のようになります。
- エンドポイント:
https://github.com/login/oauth/authorize
- クエリ①:
client_id
=$OAUTH2_CLIENT_ID
- クエリ②:
scope
=user public_repo
「クエリ①」の $OAUTH2_CLIENT_ID
の値ですが、あらかじめ GitHub 側で作成/登録した OAuth アプリもしくは GitHub アプリの設定にある「クライアント ID」と置き換えます。
🐒 ここで言う「クライアント」とは、あなたが作ったアプリのことで、アプリのユーザーのことではありません。「GitHub クライアント・アプリ」としてのアプリ ID と考えればいいと思います。
次に「クエリ②」ですが、アプリが求めるアクセス権の指定です。値が user
と public_repo
であることに注目します。
つまり、スコープに「user
」と「public_repo
」の読み書き許可を求めています。具体的にはスペース区切りで羅列したものを URL エンコード1したもの(user%20public_repo
)になります(その他のスコープの権限は上記一覧をご覧ください)。
この URL のリンク先(GitHub のサイト上)で、ユーザーは API のアクセス範囲(スコープ)を確認し、許可をします。
ユーザーの許可が得られると、GitHub のエンドポイントは、アプリ登録時にあらかじめ指定してあるリダイレクト先(コールバック先)に転送します。すでに認証済みの場合は、許可画面は表示されずストレートにリダイレクト先に転送されます。
いずれの場合も、認証(許可)済みの場合はリダイレクト時の URL クエリに code
に暫定的な値付きでリダイレクトされます。
https://mydomain.com/return/?staus=return&code=xxxxxxxxxxxxxxxxxxxxxx
あとは(リダイレクト先の)アプリ側が、この code
の値を別途 GitHub に POST
するとアクセストークンが取得できます。
- アクセストークンの取得に関する参考資料
- OAuth アプリを使用した REST API の認証 @ developer.github.com
- 【備忘録】GitHubのOAuth認証を使って取得したアクセストークンでGitHub APIを叩く @ Qiita
デモ
ここまでの一連の動きを実際に触れるように、ダミーの GitHub OAuth アプリを登録してみました。
下記リンクをクリックすると GitHub の認証画面に飛びます。その時の許可を求めている内容を確認してください。
- スコープを無指定(デフォルト)
- スコープに「
read:org
」(Organization の読み込み)を指定
いずれのリンクも、「Authorize KEINOS」ボタンを押すと、この Qiita 記事のページに戻ってくると思います。
この記事に戻ってきたら、記事の URL を確認し、クエリに code=xxxxxxxxxxxxxxxxxxxxxx
が付いているのを確認してみてください。
本来は、この code
の値を使って GitHub にリクエストしてアクセス・トークンを取得します。
しかしながら、登録したアプリの URL(リダイレクト先)をこの Qiita 記事にしているため、当然ながら何もおきません。あしからず。
後日「なんじゃこれ?」とならないように、確認後はアプリ登録を解除してください。解除は、下記リンク先の設定画面で「DummyAppToSeeOAuthWork」を削除(お猿のアイコンを Revoke
)します。
- Authorized OAuth Apps: https://github.com/settings/applications @ GitHub
- GitHub の [
Settings
]-[Application
]-[Authorized OAuth Apps
タブ] からも削除できます。身に覚えのないアプリ(サービス)がないか定期チェックをオススメします。
- GitHub の [
GitHub ログインやアクセストークン取得の具体的な方法については、この記事のスコープに関する範囲外なので割愛します。
詳しくは公式の「コールバックの設定」をご覧ください。個人的に、日本語のページより英語のページの方がわかりやすかったです。簡単に説明すると、取得した確認コード(code
)、クライアントID、クライアント・シークレットを
のエンドポイントに https://github.com/login/oauth/access_token
POST
します。
OAuth App 登録までの参考画像
OpenID とは
OpenID もしくは OpenID Connect
とは、これまでの OAuth ログインと同じなのですが、"openid
" という専用のスコープを用意したものです。
先にも述べましたが、アプリから見て「アクセストークンを取得する」というのは、ユーザーの家の鍵を預かるのと同じようなものです。ログインに限定した場合は「家の鍵と、名刺の入った棚の鍵」を預かったようなものです。
「相手の家に入れて(アクセストークンが使えて)、棚も開けられたので、そこにあった名刺(スコープが返したユーザー名やメアド)は鍵の持ち主のものである」ということをアプリ側が行っていることにお気づきでしょうか。
つまり、開けられる鍵(スコープ)を 1 つ間違えるとすべてコントロールできてしまうため、アプリ側もユーザ側も気を付けないといけないことが多く、怖い側面を持っています。
そこで、これまでの OAuth 仕組みから「なんちゃってログイン」の部分のみに限定し、その仕様に準拠していれば、どのサービスであっても同じプログラムでログインさせることができるようにしたものが OpenID
もしくは OpenID Connect
です。
具体的には、スコープに "openid" を用意し、API から得られる情報を明確に限定させた(制定した)ものです。
残念ながら GitHub API では openid
のスコープは用意されていません。
TIPS
ちなみに code
の値を使って取得したアクセス・トークンで API を叩いても動かない場合、スコープの範囲外の API 内容をリクエストした可能性があります。しかし、まずは返されたヘッダ(レスポンス・ヘッダ)情報を確認してみてください。
API を叩くには「curl https://api.github.com/hogehoge_api/?access_token=XXXXXXX
で GET
すればおk」と案内するだけの記事が多いのですが、実はこれだけでは取得できません。
そこで、curl
に --head
や -I
オプションを付けてレスポンス・ヘッダをみると、以下のような「ブラウザの User-Agent
が抜けている」といったメッセージが返されていたりします。
Request forbidden by administrative rules. Please make sure your request has a User-Agent header (http://developer.github.com/v3/#user-agent-required). Check https://developer.github.com for other possible causes.
所感(そのスコープ、狙いは定まってますか)
とあるサイトで「GitHubアカウントでログインできるよ!」というのでログインしようとしたら、なんか「リポジトリの書き込み権限」とか聞かれました。「不審なモバイルアプリじゃないんだから、最低限の権限にしなさいよ」と、ログインするのをやめました。
「そもそも、アクセス権限の指定ってできないからなのかな?」と調べると「スコープ」で行えることがわかりました。しかし、GitHub API の使い方に関する Qiita 記事は多いのですが、まとまった GitHub のスコープ仕様の情報がなかなかなく、「他にスコープで設定できる項目はないの?」と思って調べようとしても、すぐにヒットしなかったので取りまとめて記事にしてみました。
-
【URLエンコード/パーセントエンコードとは】「パーセントエンコーディング」@ Wikipedia ↩ ↩2