PostmanからX APIを使うことで、OAuth2.0の使い方を理解できたので解説してみます

# はじめに
システムを作ったり使ったりすると、**OAuth2.0**という仕組みに携わることがたまにありますね。

私はこれまで使う必要があるときは、たくさんある解説サイトを見つつ、ちょっと理解して、自分の使う目の前の問題をなんとか乗り越えて、その後は触れない（触れる必要がなくなる）、ということを繰り返してました。なので、あんまり理解してなかった。

けど今回、XのAPIをOAuth2.0で認証して呼び出してみようと思い、試行錯誤し、使い方を理解した（つもりになった）ので、そのお話です。PostmanというAPIを呼び出すツールを使ってます。

抽象化し、そして小学生でもわかるような違う言い方に置き換えています。鬱陶しいかもですが、カッコ書きで正しくは～の方を書いてみます。

# 理解の流れ
## 1. やりたいこと
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/c2b2d138-b734-6e2d-75be-8351d1b43edf.png)
ユーザーは、X島（Xサーバー）とデータをやり取りしたいです。
やり取りとは、物を送ったり（投稿）、物を受け取ったり（読み取り）です。

## 2. X島製（X社製）のロボットでないと入れない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/9366a4fa-6deb-6e9c-6139-97b2b11a8242.png)
ですがこの島は、人が直接運ぶ（人がブラウザで見る）か、そうでない場合はX島の裏の方にある工場（X Developers サイト）で作られたロボット（アプリ）のどちらかでしか、入れません（アクセスできません）。

今回は、ロボットによるアクセスをしたくて、そのときに、OAuth2.0という仕組みを使います。

まずここで、X島の工場でロボットを作成します（X Developersサイトで、アプリを作ります）

## 3. ロボットの入場はチケットが必要
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/13b4b94c-c1e1-aa79-0d82-ab7f90a0c93a.png)

X島製のロボットならすぐ入れるかというと、そうではなく、ロボットの場合はX島にあるプリンターで発行した入場チケット（トークン）を持ってないと入れません。

## 4. チケットの入手申請
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/d8454ba9-8461-5bbc-524f-dee379b945a5.png)
チケットをゲットするためには、確かにX島製のロボットであることを証明する必要があります。
作ったロボットから、ロボット自身の名前（Client ID）とパスワード（Client Secret）を取得することができるので、それをもって"確かにX島製のロボットであること"の証明とし、X島に「私が使うチケットをください」という申請（認可サーバーへ、Client IDとClient SecretのBasic認証でPOST）します。

## 5. ユーザーへアカウントを使っていいか確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/6ee6be68-e003-0940-dce4-2369c10513da.png)
ロボットから申請が出ると、X島からユーザーへ「こんなロボット（アプリ）がX島とやり取りしたいと言ってるけどいい？」という確認がされます。申請は待たせておいて、別ルートで確認します。

実際ここでよくあるのは、ブラウザに出る確認画面です。「自分で申請してるのに何で確認画面出るの？」って思う場面があると思いますが、それは申請してるのはロボットからXで、確認はXから人に対して、と別だからです。
ちなみに、Postmanを使った確認画面もあるけど、Xの場合は「知らないブラウザのようなものからOKと言われても信用できんな」って拒否られます。なので、あとで書くPostmanの設定画面でブラウザーで認可するにします。

で、ユーザーはOKと言ったとしましょう。

## 6. チケットを発券し、指定された島経由で、届く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/8307cc08-67a8-0a20-acdc-7520b0f47c10.png)
確認後、OKが出たのでチケット（トークン）を発券します。

送り先がちょっとややこしいです。

Postmanの場合は、X島と同じようにPostman本島（Postmanサーバー）があります。まずここへチケットが送られます。この島は実は、ロボットを作るときに言ってあります。「もしチケットをくれるならここへ送ってネ！」と。（この宛先が、Callback URI / Redirect URL）

そして、実はロボットは、Postman島群の１つの小さな島に巣（PostmanがインストールされているローカルPC）があって、本島（Postmanサーバー）から巣がある小島（ローカルPC）へ転送してもらいます。そうしてようやく、素にチケットが渡り、ロボットがチケットを使えます。

## 7. チケットを使ってロボットによるやり取り
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/f126de02-29f0-2b09-413f-9f8457b19582.png)
チケット（トークン）さえ手に入れれば、ロボットはそのチケットを使って出入りし、ローカルのPostman島とX島との間で、やり取りができるようになります。


# 省略した話
話をシンプルにするために省略したことが、大きく２つありますので、さらっと書いておきます。

## 1. チケットには、できることが書いてある
実はチケットの取得申請するとき、「私は～～をしたいので、それができるチケットをください」と、自分がほしい権限を合わせて申請します。"～～をしたい"のことをスコープと言います。もちろん権限がないことは、チケットを持っていてもできません。

具体的には、下記に書いてあります。

https://developer.x.com/en/docs/authentication/oauth-2-0/authorization-code

## 2. チケットには、使用期限がある
実はチケットは、２時間しか使えません。２時間経ったら、また申請しないといけない。
そのたびに、ユーザーが「OK！」とするのは大変なので、２度目以降の再発行（リフレッシュ）ができる手続きがあります。再発行手続きには、再発行用のチケット（リフレッシュトークン）が必要です。申請時のスコープで、`offline.access`を合わせて申請すると、もらえます。

再発行手続きはロボットだけでできるので、使用期限が切れたら再発行することをロボットにさせれば、現実的にはずっと使えるという仕組みです。諸事情でロボットの権限を変更したい場合に、権限変更前に発行したチケットはどんなに長くても２時間しか使えず、２時間後には絶対最新の権限になっているという具合です。


# Postmanでの設定方法
ここからは、正しいエンジニアの言葉で。

## 1. トークンを取得するためのPOST
Postmanの画面で、認可＞**新しいトークンの設定**に設定します。（v11.23.3 日本語版です）

- トークン名：任意の文字
- Grantタイプ：認可コード（PKCE利用）
- コールバックURL：（なし）ブラウザーで認可するにチェック
- 認可URL：https://twitter.com/i/oauth2/authorize
- アクセストークンURL：https://api.twitter.com/2/oauth2/token
- クライアントID：（X DevelopersのApps＞鍵アイコンの画面で入手）
- クライアントシークレット：（同上）
- コードチャレンジメソッド：SHA-256
- コード検証器：（空）空欄の場合、自動的に生成されます
- Scope：（上で書いたドキュメントを参考に）
    - 私は読み取りだけしたかったので、`users.read tweet.read offline.access` でした。スペース区切り。
- State：任意の文字列
- クライアント認証：Basic 認証ヘッダーとして送信

これを設定し、画面を下までスクロールして「新しいアクセストークンを取得」ボタンを押す。

正しく取得できたら上にスクロールして、**現在のトークン** のところにトークンが入っています。

## 2. API利用
トークンの取得後は、必要に応じてドキュメントに沿ったGETとかPOSTとかしていただければ。

https://developer.x.com/en/docs/api-reference-index

### 2.1. サンプル ユーザー名からユーザー情報を得る
サンプルとして、ユーザー情報を得るGETを書きます。この呼び出しのドキュメントはこちら。

https://developer.x.com/en/docs/x-api/users/lookup/api-reference/get-users-by-username-username

OAuth2.0 の 認可コード（PKCE利用） で認証し、権限（スコープ）は`tweet.read`と`users.read`が必要だと書いてあります。

URLは`https://api.x.com/2/users/by/username/:username`なので、`:username`のところをXの`@`の後ろの文字、私のIDの場合だと、`https://api.x.com/2/users/by/username/SmallPieces2023`でGETすると、下記を得ます。

```json: X APIからのレスポンスボディ
{
    "data": {
        "id": "1743825027165016064",
        "name": "Small Piece",
        "username": "SmallPieces2023"
    }
}
```

# おわりに
文章だけだとピンとこないタチで、どうしても絵を描きたくて、紙芝居のような形になりました。
X Appの認証設定は、OAuth1.0での接続情報もあったり使えたりするので、これは1.0の話、これは2.0の話、と試行錯誤しながら進めました。

OAuth2.0は、API呼び出しでよく出くわすので、まずこのPostmanとX APIで理解し、他の場合でまた出くわしたら、違いを認識してまた理解を深めたいと思います。

ではよきAPIライフを！
良いお年を！