0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

X APIを使用する

Last updated at Posted at 2025-05-05

OAuth 2.0 Flow with PKCE を使用して、X APIを利用できるようにした時の学びを備忘録として残そうと思います。

本記事では以下をカバーします。

  • X API使用のためのTwitter Developerアカウントの登録とセットアップ
  • OAuth2.0 Flow with PKCEを使用し、X APIのアクセストークンを取得
  • ターミナルからXへツイートする

*Xのアカウントはある前提です。

事前準備

以下の手順は、XのAPIを初めて使う方向けです。

まず、X Developer Portal を開き、Twitter Developerアカウントを登録をします。

スクリーンショット 2025-05-04 15.44.49.png

Basicタブを開き、下の方にSign up for Free Accountがあるのでそれをクリックします。

次に、X APIを使う理由を書き、規約に同意をします。
理由は最低250文字必要で日本語でも大丈夫かと思いますが、英語に機械翻訳した方が文字数を稼げますので、英語をお勧めします。

スクリーンショット 2025-05-04 15.46.24.png

登録が完了するとポータルサイトが開きます。
左メニューのProjects & Appsを開き、その中からプロジェクトをクリックするとこのような詳細ページが開きます。
ページ下部に「User authentication settings」があるので、Set upをクリックします。

スクリーンショット 2025-05-04 15.59.34.png

ユーザー認証設定ページが開くので、以下の通り設定してください。
App permissions: Read and write
Type of App: Native App
スクリーンショット 2025-05-04 16.12.51.png

App Info:
以下2つが必須なので、両方入れてください。

  • Callback URI / Redirect URL(認可コードを受け取るURLになります)
  • Website URL
    *どちらもテストだけであれば、ダミーのURLでもOKです。

スクリーンショット 2025-05-04 16.13.03.png

上記設定ができたら、Saveをクリックして保存します。
そうするとClientIDClient Secretが表示されると思いますので、メモ帳などに保存しておいてください。
*Client Secretに関しては忘れた場合、後から確認ができず、再生成しないといけないので注意です。

スクリーンショット 2025-05-04 16.16.48.png

次に、ターミナルを使って、ClientIDClient Secret:で繋いだ文字列を BASE64にエンコードします。

echo -n 'CLIENT_ID:CLIENT_SECRET' | base64

すると、こんな文字列が生成されると思いますので、実践パートで使うので控えておきます。

Ykd4------省略------4MTNkZQ==

BASE64とは?
64進数を意味する言葉で、すべてのデータを62種類のアルファベット(a~z, A~Z)と数字(0~9)、一2種類の記号(+,/)の64文字で表すエンコード方式。


これで事前準備は完了です。

OAuth 2.0 Flow with PKCEを使用し、アクセストークンを取得する

Step 1 認可リクエスト

*この認可リクエストが成功すると、認可Codeが返却されますが、この認可Codeの有効期間は30秒と短いので、あらかじめ次のStep2のトークンリクエストのCurlコマンドを用意しておいてください。

認可URLの以下2つの項目に、ご自身の情報をセットしてブラウザで開いてください。
・CLIENT_ID
・REDIRECT_URI(Developer Portalで登録したCallback URI / Redirect URLと必ず同じ!)

https://twitter.com/i/oauth2/authorize?response_type=code&client_id=<CLIENT_ID>&redirect_uri=<REDIRECT_URI>&scope=tweet.read%20tweet.write%20users.read%20offline.access&state=state&code_challenge=challenge&code_challenge_method=plain

URLにアクセスすると以下のような認可画面が開きますので、アプリにアクセスを許可(英:Authorize App) をクリックして認可します。
*未ログイン状態ならログイン後にこの画面が開きますが、もし開かない場合はもう一度上記のURLを開いてください。

スクリーンショット 2025-05-05 19.02.55.png

認可を実行すると、指定したリダイレクトURLへ遷移して、認可Codeが返却されます。

認可CodeはURLの中に含まれます。
https://www.example.com/?state=state&code=VGNibzFWSWREZm01bjN1N3dicWlNUG

Step 2 トークンリクエスト

Step 1で返却された認可Codeを使って、30秒以内にトークンのリクエストをします。
ターミナルで、以下のCurlを実行してください。

curl --location --request POST 'https://api.twitter.com/2/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic <BASE64に変換したClientIDとClient Secretの文字列>' \
--data-urlencode 'code=<Step 1で返却された認可Code>' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'redirect_uri=<Developer Portalで登録したCallback URI / Redirect URL>' \
--data-urlencode 'code_verifier=challenge' \
--data-urlencode 'client_id$<CLIENT_ID>'

成功した場合、アクセストークン、リフレッシュトークンがレスポンスで返却されます。

{
  "token_type":"bearer",
  "expires_in":7200,
  "access_token":"XXXXXXX",
  "scope":"tweet.write users.read tweet.read offline.access",
  "refresh_token":"YYYYYYYYY"
}

*30秒以上経って失敗してしまった場合は、再度Step1の認可リクエストをやり直してください。

これでユーザーに代わって、Xに投稿したりすることができるようになりました。

X APIにPOSTリクエストする

取得したアクセストークンを使って、XツイートAPIにPOSTリクエストを投げてみます。

curl -X POST 'https://api.twitter.com/2/tweets' \
--header 'Authorization: Bearer <アクセストークン>' \
-H 'Content-Type: application/json' \
-d '{"text": "Hello World 2025/5/4 Sunday!"}'

成功した場合、以下のようなレスポンスが返ります。idがツイートIDです。

{
  "data":{
    "id":"1918935953508556834",
    "edit_history_tweet_ids":["1918935953508556834"],
    "text":"Hello World 2025/5/4 Sunday!"
  }
}

x.comのアプリ側でも実際に投稿されているか確認して見ましょう。

OAuth スコープ

Step1の認可リクエストのURLです。
https://twitter.com/i/oauth2/authorize?response_type=code&client_id=<CLIENT_ID>&redirect_uri=<REDIRECT_URI>&scope=tweet.read%20tweet.write%20users.read%20offline.access&state=state&code_challenge=challenge&code_challenge_method=plain

OAuthスコープは、scope=tweet.read%20tweet.write%20users.read%20offline.accessの部分で、認可時にアプリが必要とする権限を定義しています。認可リクエストと共にこのスコープ情報が送信されます。

  • tweet.read:ツイートの参照
  • tweet.write:ツイート、リツイートの実行
  • users.read:アカウントを参照できる
  • offline.access:
    X APIのオフラインアクセス、つまり、ユーザーがログインしていない状態でもAPIを利用するためにリフレッシュトークンを使えるようにする。
    リフレッシュトークンは、有効期限が長く、アクセストークンを自動的に更新することができます。

公式ドキュメントのScopes

ユーザはスコープの許可を与えるかどうかを選択できるので、認可の画面にも以下のように表示されます。

スクリーンショット 2025-05-05 19.02.55.png

  • このアプリが実行できる処理
    • あなたの代わりに投稿したり、再投稿したりする。=tweet.write
    • アクセス権を取り消すまでアカウントにアクセスできます。=offline.access
  • このアプリが参照できる内容
    • あなたが表示できるすべての投稿(非公開アカウントの投稿を含む)です。=tweet.read
    • あなたが表示できるすべてのアカウント(非公開アカウントを含む)=users.read

認可コード横取り攻撃とPKCEの仕組み

認可コードを悪意のあるアプリに受領されると、利用者になりすましてアクセス権限を行使されてしまう認可コード横取り攻撃が可能になってしまう。

それを防ぐために、PKCE(Proof Key for Code Exchange) を使います。
PKCEは「アクセストークンを安全にやり取りするための、OAuth 2.0の拡張仕様」で、認可コードグラントフローのセキュリティを強化します。

Step1の認可リクエストのURLです。
https://twitter.com/i/oauth2/authorize?response_type=code&client_id=<CLIENT_ID>&redirect_uri=<REDIRECT_URI>&scope=tweet.read%20tweet.write%20users.read%20offline.access&state=state&code_challenge=challenge&code_challenge_method=plain

code_challenge=challenge
code_challenge_method=plain
の部分がPKCEの設定です。

code_challenge_methodplainの他にS256があります。
plainメソッドは入力を変更しないため、code_verifier と code_challenge の値は同じになります。

*本記事ではplainメソッドで、"challenge"という文字列を使っているので、code_verifier と code_challengeはどちらも"challenge"となります。

*S256 メソッドは入力の SHA-256 ハッシュを計算し、そのハッシュ値を Base64-URL エンコードします。

アプリはcode_challenge、code_challenge_methodを認可URLに含めることで、認可サーバーに送信され、認可サーバーは、これらを保管しておきます。

そして、アクセストークンリクエストの際にcode_verifierを付け加えます。

--data-urlencode 'code_verifier=challenge' \

認可サーバーはcode_verifierが正しいかどうかを、保管しておいたcode_challengeを元に検証し、code_verifierが正しければアクセストークンを返却し、間違っていれば何も返しません。

code_verifierは正規のアプリしか知ることはないので、第三者にアクセストークンを横取りされることがなくなる、という仕組みです。

図にまとめると以下の様になります。

Frame 2.png

X APIドキュメント

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?