さすがにHttpリクエストをするためのライブラリは使いますよ。
お断り
筆者はOAuthなんてTwitterAPIで初めて知ったような認証認可初学者なので、情報には誤りがあるかもしれません。
誤った点があれば遠慮なく教えてください。
ステップ
公式ドキュメントのステップ番号とは対応していないので注意
- 🚶♂デベロッパーポータルからOAuth2.0を有効にし、
Client ID
とClient Secret
をメモする。 - 🚵アカウントの持ち主に開かせるURLを生成する
Client ID
-
redirect_uri
(OAuth2.0有効化時に登録したもののみ可能。) -
Scopes
細かく分けられた権限。各APIエンドポイントによって必要なスコープがある -
code_challenge
十分にランダムな文字列。
- 🚗URLを踏んだ先(Twitterのページ)でアカウントの持ち主に権限のリクエストを承認してもらい、リダイレクトURLのクエリから
code
を拾う - 🚅今までの情報を使ってアクセストークンを要求する
-
code
リダイレクトurlのコード -
redirect_uri
(ステップ2と同じもの) -
code_verifier
(ステップ2のcode_challenge
で使用した文字列) -
Client ID
とClient Secret
Basic Authorizationに使用
-
- 🚀Scope
offline.access
が有効の場合、トークンをリフレッシュできる。-
refresh_token
アクセストークンと一緒に取得したもの -
Client ID
とClient Secret
Basic Authorizationに使用
-
🚶♂️ステップ1 API管理画面で必要事項の登録
デベロッパーポータルからOAuth2.0を有効にします。
有効化時、リダイレクトURLの登録が必要となります。後のステップを読んで決めてください。わからなければ https://www.google.com
にしてもいいです。
有効化後に表示される Client ID
と Client Secret
をメモします。忘れても再発行できるので気楽に・・・
🚵 ステップ2 URL を作成する
アドレスは https://twitter.com/i/oauth2/authorize
です。?
以降のクエリパラメータは次です。
Key | Value |
---|---|
response_type |
code でいいです。もっと知りたい方はOAuth2.0に詳しい人に聞いてください。 |
client_id |
あなたの Client ID です。 |
redirect_uri |
ユーザーが承認した後リダイレクトされるURIです。デベロッパーポータルで登録したものしか使えません。(後から追加もできます) |
scope |
ユーザーに承認してもらう権限です。ここに一覧があるほか、ドキュメントの各API reference に必要なものが書いてあります。複数要求する場合はスペースで連結します。(最後にURLエンコードするのを忘れずに) |
state |
state でいいです。もっと知りた(略 |
code_challenge |
最後のステップでアクセストークンを要求する際に必要になります。推奨される文字数はOAuth2.0に詳しい人に(略 |
code_challenge_method |
plain でいいで(略 |
完成したURLをアカウントの持ち主に開いてもらいます。
例(わかりやすいように改行しています)
https://twitter.com/i/oauth2/authorize
?response_type=code
&client_id=MY_CLIENT_ID
&redirect_uri=https%3A%2F%2Fwww.google.com
&scope=tweet.read+tweet.write+list.read+list.write+users.read+offline.access
&state=state
&code_challenge=SlVQjHz2
&code_challenge_method=plain
🚗 ステップ3 リダイレクトURLからcode
を取得する。
やることは一つです。リダイレクトURLのクエリパラメーターに code=CODECODECODECODE
というものがあるので、これを取得してください。
方法によって様々なリダイレクトURIが考えられます。
-
自分でlocalhostのサーバーを立てて処理する
この場合はリダイレクトuriはhttp://localhost:8000
とかですかね。 -
URLスキームをレジストリで登録してプログラムで処理する
この場合はリダイレクトuriはmy-cool-app://
などになりますね。 -
適当なサイトにリダイレクトしてURLを標準入力にコピペする
一番簡単です。リダイレクト後のURLをユーザーにコピーさせて、プログラムに入力してもらいます。あとはプログラムで正規表現なりライブラリなりでクエリパラメータをパースしてcodeの値を手に入れます。
いずれの場合もURIの後ろにクエリ文字列 (?state=state&code=CODECODE
のようなもの) を付与したリンクが開かれますので、code
の値を取得してください。例えばURLに以下の正規表現でパターンマッチを取得することで、code
の値を取得できます。
code=([^?&]+)
(カッコの中が欲しいコードになります。)
🚅 ステップ4 code
をつかってアクセストークンを得る。
APIエンドポイント https://api.twitter.com/2/oauth2/token
に対して次のリクエストを POST
します。
headers
Key | Value |
---|---|
Authorization |
Basic + (スペース) + base64Encode(Client ID + : + Client Secret) |
Content-Type |
application/x-www-form-urlencoded |
Body (content または Payload とも)
以下の Key
と value
のペアをURLエンコードした文字列
Key | Value |
---|---|
code |
取得したコード |
grant_type |
authorization_code |
redirect_uri |
ステップ2 で使用したリダイレクトURL |
code_verifier |
ステップ2 の code_challenge と全く同じもの |
注意事項として、リダイレクトされた時点から30秒以内にトークンを要求しないと invalid_request
というメッセージとともに400番のレスポンスをされるということを書いておきます。
成功すると、json形式のレスポンスが帰ってきます。
{
"token_type": "bearer",
"expires_in": 7200,
"access_token": "ACCESS_TOKEN_ACCESS_TOKEN_ACCESS_TOKEN_ACCESS_TOKEN",
"scope": "list.write list.read tweet.write users.read tweet.read"
}
無事にアクセストークンを入手することができました!このアクセストークンは2時間のみ有効です。
これを使って、APIのリクエストヘッダの Authorization
に Bearer ACCESS_TOKEN
と設定することで、ユーザーとしてツイートしたりDMしたりすることができます。各APIによって必要なscopeが違うので注意しましょう。
🚀 ステップ5 refresh_token
で新しいアクセストークンを得る。
2時間じゃちょっと足りない!一度権限を許可したらずっとAPIを利用し続けたい!という人も居ると思います。
ステップ2でURLを作る際、scopes
を指定しました。これに offline.access
というスコープを追加すると、ステップ4のレスポンスjsonに refresh_token
という値が追加されます。これを用いて新たに2時間有効な access_token
を得ることができます。
ステップ4 とエンドポイント・ヘッダは同じですが、bodyが違います。
Body (content または Payload とも)
以下の Key
と value
のペアをURLエンコードした文字列
Key | Value |
---|---|
grant_type |
refresh_token |
refresh_token |
ステップ4で得た refresh_token
|
これで、ステップ4と同じ形式のレスポンスを受け取ることができます。
おわりに
以上になります。
- URLを作成する。
- ユーザーがログインして権限を承認する。
- リダイレクトURLから code の値を取得する。
- アクセストークンをリクエストする。
- 必要に応じてアクセストークンをリフレッシュする。
これらのステップでアクセストークンを取得し、バンバン自動ツイートしていきましょう!
最初にも書きましたが筆者はOAuth初学者です。誤っている点があれば遠慮なく教えてください。
最後までお読み頂きありがとうございました。
Pythonソース
自作のPython関数を雑に貼り付けます。大文字の変数は環境変数から読み込んだ定数です。
tweepy や oauth2lib などの認証をやってくれるライブラリは使いませんが、jsonパーサーやurl/base64のエンコード/デコードはライブラリにやってもらっています。
権限要求ページのURLを作る
def create_url():
challenge = ''.join([random.choice('abcdefghijklmnopqrstuvwxyz') for _ in range(64)])
with open('tmp/tw_challenge.txt', 'w') as f:
f.write(challenge) # 後で使うので保存
scopes = ['tweet.read', 'tweet.write', 'users.read', 'offline.access']
querys = {
'response_type': 'code',
'client_id': CLIENT_ID,
'redirect_uri': REDIRECT_URI,
'scope': ' '.join(scopes),
'state': 'state',
'code_challenge': challenge,
'code_challenge_method': 'plain'
}
return 'https://twitter.com/i/oauth2/authorize' + '?' + parse.urlencode(querys)
リダイレクトURLからcodeを取得する
def get_code_from_url(url):
parsed_url = parse.urlparse(url)
query = parsed_url.query
query_dic = parse.parse_qs(query)
return query_dic['code'][0]
codeからアクセストークンをリクエストする(リフレッシュ兼用)
def get_tokens(code, refresh_token=None):
auth = base64.b64encode(str(CLIENT_ID + CLIENT_SECRET).encode()).decode()
headers = {
'Authorization': auth,
'Content-Type': 'application/x-www-form-urlencoded'
}
if not refresh_token:
with open('tmp/tw_challenge.txt', 'r') as f:
challenge = f.read().split()[0] # code_challenge の読み込み
data = {
'code': code,
'grant_type': 'authorization_code',
'redirect_uri': REDIRECT_URI,
'code_verifier': challenge
}
else:
data = {
'grant_type': 'refresh_token',
'refresh_token': refresh_token
}
req = request.Request(
'https://api.twitter.com/2/oauth2/token',
headers=headers,
data=parse.urlencode(data).encode()
)
with request.urlopen(req) as res:
OA2token = json.loads(res.read())
return OA2token