GitHub API の様々な認証方法についてそれぞれ調べてみた

# はじめに
 
最近 GitHub API を使う機会があり、認証方法が3種類あって少し迷ったので、自分なりに理解した内容を整理してみました。

GitHub公式のドキュメントは以下です。

https://docs.github.com/ja/rest/authentication/authenticating-to-the-rest-api?apiVersion=2022-11-28

# GitHub API の認証方法3種

オープンなリポジトリの操作など、認証をしなくても GitHub API を使える場合がありますが、大抵の場合は認証が必要になります。GitHub API を使用する際の認証方法は現在以下の3種類あります。（他にもあったら教えてください！）

- Personal Access Token（PAT）による認証
- OAuth app による認証
- GitHub App による認証

それぞれ簡単に説明していきます。

## Personal Access Token（PAT）による認証

Personal Access Tokenとは、その名の通り個人用のアクセストークンです。
GitHub の設定ページまたは以下リンクからトークン管理ページに飛べます。

[https://github.com/settings/tokens](https://github.com/settings/tokens)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325392/70974793-b3a3-1f78-8015-69b83e6f0560.png)

作成時に、名前と有効期限の設定、そしてトークンでアクセス可能な情報の種類を選択できます。

有効期限を無制限にすることも可能ですが、トークンが誤って流出した場合などで危険なので設定しておいた方がいいです。一方、有効期限を設定する場合は、有効期限が切れるたびに再生成が必要なので、忘れないようにする必要があります。

例えば企業が運営するWebサービスにこのトークンを使用する場合は、トークンの有効期限切れでサービスが止まってしまわないようにすることが必要です。またユーザーに紐付くので、トークン生成したメンバーが退職した場合なども考慮する必要があります。

このように、Personal Access Tokenは個人として使う分には問題ないですが、企業として使用する場合は注意が必要で、場合によっては後述の OAuth 認証や GitHub App を使った認証の方が適している場合があります。

生成したトークンを使う方法は簡単です。以下のようにヘッダーにトークンを指定して、APIのエンドポイントにリクエストを送るだけです。

```bash
$ curl -H "Authorization: token ここにトークンを入れる" https://api.github.com/user
```

以上をまとめると、Personal Access Token（PAT）を使った認証は以下のような認証方法となります。

- 設定ページで作成した、**個人に紐付くトークン** を使用する
- トークンを **ヘッダー** に指定することで API へアクセスできる
- **自分の** GitHubアカウントで閲覧可能な情報にアクセスできる
- 有効期限を設定が可能で、有効期限切れに注意

## OAuth app による認証

:::note warn

現在、OAuth app による認証よりも、後述の GitHub App による認証の方が推奨されているようです。

[GitHub Apps と OAuth アプリの違い - GitHub Doc](https://docs.github.com/ja/apps/oauth-apps/building-oauth-apps/differences-between-github-apps-and-oauth-apps)

:::

OAuth は、例えば自分が作ったWebアプリケーションでユーザーが GitHub アカウントでログインできる機能を作る際に役立つ認証方法です。Qiita も GitHub アカウントでログインできるようになっていますが、これも OAuth が使用されています。

https://help.qiita.com/ja/articles/qiita-release-account-coop

より正確には、OAuth は「ユーザーのGitHubアカウントの権限の一部」をWebサービスにも与えて、Webサービス側が「そのユーザーのGitHubの情報にアクセスする」ための仕組みです。

GitHub の設定ページまたは以下リンクから、OAuth app の作成ができます。

[https://github.com/settings/developers](https://github.com/settings/developers)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325392/74299e35-6ba4-a85a-4d19-5794dec6eac5.png)

アプリケーション名やホームページURL、コールバックURLなどを設定して作成すると、 `client_id` や `client_secret` が生成されます。

OAuth やコールバックURLについて知らない場合、以下の記事がOAuthについて丁寧に説明されているので、おすすめです。

https://qiita.com/TakahikoKawasaki/items/e37caf50776e00e733be

GitHub の OAuth app による認可の流れを簡単に説明すると、以下のようになります。

- 以下のようにURLを設定したリンクをWebアプリケーション上に用意する
    - `https://github.com/login/oauth/authorize?scope=(スコープ)&client_id=(client_id)`
- ユーザーがこのリンクから GitHub のページにアクセスし、連携を許可する
- コールバックURLにリダイレクトされてサーバーにコードが渡される
- 以下URLに渡されたコードや `client_id` `client_secret` をパラメータとして渡し、トークンを取得する
    - `https://github.com/login/oauth/access_token`

スコープの設定方法など、詳細は以下の公式ドキュメントに記載されているので、そちらも確認の上実装しましょう。

https://docs.github.com/ja/apps/oauth-apps/building-oauth-apps/authenticating-to-the-rest-api-with-an-oauth-app

トークンは PAT の時と同様に、ヘッダーに指定してAPIにリクエストを送ります。

```bash
$ curl -H "Authorization: Bearer OAUTH-TOKEN" https://api.github.com/user
```

以上をまとめると、OAuth app による認証は以下のような認証方法となります。

- **OAuth の認可フロー** で取得したトークンを使用する
- トークンを **ヘッダー** に指定することで API へアクセスできる
- **連携したユーザー** の指定したスコープの情報にアクセスできる
- 現在は **GitHub App による認証の方が推奨されている**

## GitHub App

GitHub App はできることが多いので、一言で説明することは難しいですが、GitHub API へのアクセスだけでなく、GitHub で発生するイベントに基づいて何か実行することも可能です。

ここでは自分で作った GitHub App を自分の GitHub アカウントにインストールし、APIにアクセスするためのトークンを取得する方法のみ説明します。

初めに以下から GitHub App を作成します。

[https://github.com/settings/apps](https://github.com/settings/apps)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325392/fd03c109-6fdd-6a1d-ed9c-acd86de95f64.png)

設定できる項目が多いですが、GitHub App の名前とホームページのURLを設定すればOKです。
作成後、以下の操作を行い必要な値を控えておきます。

- `Generate a private key` から、秘密鍵を生成する
- サイドバーの Public pageのリンクから、GitHub App をインストールする
    - インストール後、`https://github.com/settings/installations/XXXXXXXXXXXX` のようなページに飛ぶので、`XXXXXXXXXXXX` の部分をコピーしておく (後で `INSTALLATION_ID` として使います。)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325392/3435bdf4-87f9-0e76-d9f9-4c34228c7dc0.png)

これで必要な値がそろったので、次は認証に使うトークンの取得を行います。

取得の方法は以下の公式ドキュメントに記載されています。

https://docs.github.com/ja/apps/creating-github-apps/authenticating-with-a-github-app/generating-an-installation-access-token-for-a-github-app

トークンは以下のようにリクエストすることで、取得できます。
```
curl --request POST \
--url "https://api.github.com/app/installations/INSTALLATION_ID/access_tokens" \
--header "Accept: application/vnd.github+json" \
--header "Authorization: Bearer JWT" \
--header "X-GitHub-Api-Version: 2022-11-28"
```

`INSTALLATION_ID` は先ほど用意した値を使用します。JWT は以下に記載の方法で秘密鍵をもとに生成したJSON Web トークンを使います。

https://docs.github.com/ja/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-json-web-token-jwt-for-a-github-app

そうして取得したトークンを、PAT や OAuth app と同様に、以下のようにヘッダーに指定してAPIにリクエストします。

```bash
$ curl -H "Authorization: Bearer OAUTH-TOKEN" https://api.github.com/user
```

このように、GitHub App の認証は複雑なので、Octokit を使用してトークンを取得する方法がオススメです。

https://github.com/octokit

Octokit は GitHub API 用のライブラリで、JavaScript, C#, Rubyなどの言語に対応しています。JWTを以下のように渡すだけで、トークンの取得ができます。

```rb:RubyのOctkitを使用した例
client = Octokit::Client.new(bearer_token: jwt_token)
access_token = client.create_app_installation_access_token(INSTALLATION_ID).token
```

以上をまとめると、GitHub App による認証は以下のような認証方法となります。

- GitHubの個人アカウントだけでなく、**Organization でも GitHub App を作成できる**
- GitHub App をユーザーまたは Organization に **インストールする必要がある**
- **JWTの生成** など、トークンを取得する方法が少し複雑
- スコープや有効期間などの理由から、OAuth apps よりも**推奨されている**

# おわりに

認証・認可は複雑で、理解するまで少し時間がかかりますが、学べることは多いので、APIを使う際にぜひ自分なりに理解した内容を記事にまとめてみることがおすすめです。

僕もこの記事を書くことで、自分の中で曖昧だった部分の理解が深まりました。GitHub App の使い方についてはまだAPIを使う場合しかちゃんと理解できていませんが、他にも便利な使い方がありそうなので、また別の記事としてまとめようと思います。