OAuth認証でTwitterとアプリを連携する
Twitterを使っている人なら「〇〇にアカウントへのアクセスを許可しますか?」という文字列を見たことがあると思います。
それの実装手順を紹介します。
先人の書かれた素晴らしい記事が既に存在してはいるのですが、Twitter Developer Portalがコロコロ中身を変えることもあって情報が古くなっていることもあり、自分で書くことにしました。
Pythonでの実装例も示しています。全て繋げると実際に実行できるようになっています。
そもそも何をやっているのか
アプリ側のAPI Key/API Key Secret(Consumer Key/Secret)を用いて、ユーザー側にOAuth TokenとOAuth Token Secretを発行しています。
その過程でPOST oauth/request_tokenとPOST oauth/access_tokenという2つのエンドポイントを経由します。
ちなみに
Twitterで言う「API Key」「API Key Secret」は様々な解説記事で見かける「Consumer Key」「Consumer Secret」と同義です。読み替えてもらって構いません。
手順
開発者登録をする
Twitter Developer Platformで開発者登録をします。英作文とかあったりして面倒臭いですがDeepLとかの翻訳ツールを駆使して乗り切りましょう。昔に比べたらUIもわかりやすくなっているので解説記事を読まずとも突破できると思います。
電話番号を認証したTwitterアカウントでないといけないので、そこだけ注意してください。
アプリを作る
ここではEarly AccessのAPI v2は使いません。
アプリ名を入力したら出てくるAPI KeyとAPI Key Secretは今後表示されない(再生成は可能)ので、ちゃんとメモしておきましょう。
Bearer Tokenは使いません。必要になったらそれだけ生成できるので今は放置でもいいと思います。
なお、アプリ側でOAuth Token/Secretを生成する必要はありません。
Callback URLとWebsite URLを決める
これは基本的には、どちらも開発しているWebサービスのURLにしましょう。
Website URLはこんな感じで右上のアプリ名の下に表示されます。
Callback URLには、OAuth TokenとOAuth Verifier(後述)がパラメータとしてくっついてきます。
詳しくは後述しますが、例えばhttps://callback.example.com
をCallback URLに指定した場合、
https://callback.example.com?oauth_token=token文字列&oauth_verifier=verifier文字列
という形で認証画面から移ってきます。
試したいだけだからといって信用できないサイトをCallbackに指定するのはやめましょう。この仕様を知っていれば悪用できてしまいます。 Webサービスでなくとも自分の管理しているサイトが良いでしょう。
最終手段ですが、存在しないURLを指定してもURLにひっついたパラメータの文字列をコピペすることはできます。
認証用URLを生成する
API KeyとAPI Key Secretを用いて、OAuthセッションを生成します。
そのセッションでoauth/request_tokenにPOSTします。このときパラメータにoauth_callback
というキーでCallback URLを指定する必要があります。詳細は公式ドキュメントを参照してください。
以下にPythonでのrequests_oauthlib
を用いた実装例を示します。
from requests_oauthlib import OAuth1Session
API_KEY = "取得したAPI Key"
API_KEY_SECRET = "取得したAPI Key Secret"
callback_url = "https://callback.example.com"
request_endpoint_url = "https://api.twitter.com/oauth/request_token"
authenticate_url = "https://api.twitter.com/oauth/authenticate"
session_req = OAuth1Session(API_KEY, API_KEY_SECRET)
response_req = session_req.post(request_endpoint_url, params={"oauth_callback": callback_url})
response_req_text = response_req.text
リクエストに成功すると、以下のような文字列が返ってきます(本当にただの文字列で、JSONではありません)。
oauth_token=token文字列&oauth_token_secret=secret文字列&oauth_callback_confirmed=true
ここで必要になるのはoauth_token
のキー名で返ってきたtoken文字列
の部分です。
&
や=
で文字列を分割してうまいこと取り出しましょう。
oauth_token_kvstr = response_req_text.split("&")
token_dict = {x.split("=")[0]: x.split("=")[1] for x in oauth_token_kvstr}
oauth_token = token_dict["oauth_token"]
取り出せたら、先述したエンドポイントにトークンをパラメータとして繋げます。それが認証用URLです。
分かりづらいですが、つまりこういうことです。
https://api.twitter.com/oauth/authenticate?oauth_token=token文字列
プログラム上でも、単純に繋げるだけです。
print("認証URL:", f"{authenticate_url}?oauth_token={oauth_token}")
Access TokenとAccess Token Secretを取得する
上の手順で認証を済ませると、Callback URLで指定した先に飛ばされます。先述の通り、URLにはパラメータがついています。
https://callback.example.com?oauth_token=token文字列&oauth_verifier=verifier文字列
ここで必要になるのはverifier文字列
にあたる部分です。サーバサイドでパラメータを受け取りましょう。
試したいだけの方は、ブラウザ上のURLバーからコピペしましょう。Callback URLを自分が管理するサイトにしている場合は、私のようにこんな感じでURLからパラメータの値を切り出してみても良いでしょう。
※別にhttps://qmainconts.dev/tokendetector
をCallback URLに指定していただいても構いませんが、動作は保証しません。私が信用できない場合はもちろん指定しないでください。
これで必要な情報が揃ったので、OAuthセッションを作ってoauth/access_tokenにPOSTします。
必要になるのはAPI Key、API Key Secret、OAuth Token、OAuth Verifierの4つです。
このとき、パラメータにはOAuth TokenとOAuth Verifierを含める必要があります(公式ドキュメント参照)。
ちなみに実装例ではOAuth Verifierだけをparams
に入れていますが、なぜかこれでも動きます。なぜなんでしょう…
oauth_verifier = input("OAuth Verifierを入力してください> ")
access_endpoint_url = "https://api.twitter.com/oauth/access_token"
session_acc = OAuth1Session(API_KEY, API_KEY_SECRET, oauth_token, oauth_verifier)
response_acc = session_acc.post(access_endpoint_url, params={"oauth_verifier": oauth_verifier})
response_acc_text = response_acc.text
成功すると、以下のような文字列が返ってきます。先程と同様、JSONではありません。
oauth_token=token文字列&oauth_token_secret=secret文字列&user_id=id文字列&screen_name=name文字列
ユーザー自身のUser IDとScreen Name、そしてTokenとSecretが返ってきます。oauth_token
、oauth_token_secret
と名前がついていますが、これがAccess TokenとAccess Token Secretです。
うまいこと切り出しましょう。
access_token_kvstr = response_acc_text.split("&")
acc_token_dict = {x.split("=")[0]: x.split("=")[1] for x in access_token_kvstr}
access_token = acc_token_dict["oauth_token"]
access_token_secret = acc_token_dict["oauth_token_secret"]
print("Access Token :", access_token)
print("Access Token Secret:", access_token_secret)
print("User ID :", acc_token_dict["user_id"])
print("Screen Name :", acc_token_dict["screen_name"])
これで作業は完了です。
最初に取得したAPI Key/Secretと、最後に取得したAccess Token/Secretの4つを使ってOAuthセッションを作り、TwitterのAPIを叩くことができます。
お疲れさまでした。
コード全体
載せたコードを全て繋げたものを載せておきます。
from requests_oauthlib import OAuth1Session
API_KEY = "取得したAPI Key"
API_KEY_SECRET = "取得したAPI Key Secret"
callback_url = "https://callback.example.com"
request_endpoint_url = "https://api.twitter.com/oauth/request_token"
authenticate_url = "https://api.twitter.com/oauth/authenticate"
session_req = OAuth1Session(API_KEY, API_KEY_SECRET)
response_req = session_req.post(request_endpoint_url, params={"oauth_callback": callback_url})
response_req_text = response_req.text
oauth_token_kvstr = response_req_text.split("&")
token_dict = {x.split("=")[0]: x.split("=")[1] for x in oauth_token_kvstr}
oauth_token = token_dict["oauth_token"]
print("認証URL:", f"{authenticate_url}?oauth_token={oauth_token}")
oauth_verifier = input("OAuth Verifierを入力してください> ")
access_endpoint_url = "https://api.twitter.com/oauth/access_token"
session_acc = OAuth1Session(API_KEY, API_KEY_SECRET, oauth_token, oauth_verifier)
response_acc = session_acc.post(access_endpoint_url, params={"oauth_verifier": oauth_verifier})
response_acc_text = response_acc.text
access_token_kvstr = response_acc_text.split("&")
acc_token_dict = {x.split("=")[0]: x.split("=")[1] for x in access_token_kvstr}
access_token = acc_token_dict["oauth_token"]
access_token_secret = acc_token_dict["oauth_token_secret"]
print("Access Token :", access_token)
print("Access Token Secret:", access_token_secret)
print("User ID :", acc_token_dict["user_id"])
print("Screen Name :", acc_token_dict["screen_name"])
Discussion