X(旧Twitter)をつかった認証機能
最近Webサービスを作ってみたいなと思って,とりあえずTwitterでのユーザ認証機能は必須だよなと思ったのでその備忘録です.
実行環境
- python = "^3.10"
- fastapi = "^0.115.12"
- requests-oauthlib = "^2.0.0"
シーケンス図
準備
まずはX開発者プラットフォームにログインします.
Project > User authentication settingsにアクセス
- App infoにCallback URIをいれる.
- ※ とりあえず
http://localhost:8000/callback
とか入れといてOK.
- ※ とりあえず
- Website URL には自分のtwitterアカウントのページでも入れといてください.
Project > Keys and tokensにアクセス
- Consumer Keysを生成して
API_KEY
とAPI_SECRET
をメモってください.
ソースコード
main.py部分は省略します.router部分以降だけ書きます.
python3
from ast import parse
from fastapi import APIRouter, Request
from fastapi.responses import JSONResponse, RedirectResponse
from requests_oauthlib import OAuth1Session
# 準備でメモしたやつを入れてね
X_API_KEY = "your_api_key"
X_API_SECRET = "your_api_secret"
REDIRECT_URL = "http://localhost:8000/callback"
router = APIRouter()
@router.get("/login", response_class=RedirectResponse)
async def login(request: Request):
x_session = OAuth1Session(X_API_KEY, X_API_SECRET, callback_uri=REDIRECT_URL)
res = x_session.post('https://api.x.com/oauth/request_token')
request_token = dict(parse.parse_qsl(res.content.decode("utf-8")))
session = request.session
session['oauth_token'] = request_token['oauth_token']
session['oauth_token_secret'] =request_token['oauth_token_secret']
return RedirectResponse(url=f"https://api.x.com/oauth/authenticate'?{parse.urlencode({'oauth_token': session['oauth_token']})}")
@router.get("/callback", response_class=JSONResponse)
async def callback(request: Request, oatuh_verifier: str, oauth_token: str):
session = request.session
x_session = OAuth1Session(X_API_KEY, X_API_SECRET, session['oauth_token'], session['oauth_token_secret'])
res = x_session.post('https://api.x.com/oauth/access_token', data={'oauth_verifier': oatuh_verifier})
access_token = dict(parse.parse_qsl(res.content.decode("utf-8")))
session['access_token'] = access_token['oauth_token']
session['access_token_secret'] = access_token['oauth_token_secret']
x_access_session = OAuth1Session(X_API_KEY, X_API_SECRET, session['access_token'], session['access_token_secret'])
user_info = x_access_session.get('https://api.x.com/2/users/me').json().get('data', {})
return JSONResponse(content=user_info)
login APIを実行すると,以下のようなJsonResponseが返ってくるはずです.
{
'name': 'Hoge',
'id': '11111111111111111',
'profile_image_url': 'https://pbs.twimg.com/profile_images/nya-nya.jpg',
'username': 'my_twitter_account'
}