Python、DjangoでTwitter認証(Sign in with Twitter)するサンプル

スポンサーリンク

トップページから認証リンクを押すとサインインを求められ、ユーザーのアクセストークンをDBに保存して何らかの機能を提供するwebサービスを作る際のサンプル構成です。
(イメージとしては人事ったーみたいな感じの)

参考:Implementing Sign in with Twitter | Twitter Developers

使用パッケージ

Django
requests-oauthlib

URL構成

  • /
    • トップページ(/signin/へのリンクを貼る)
  • /signin/
    • ここにアクセスしたら認証ページにリダイレクト
  • /callback/
    • 認証から戻ってくるコールバックURL
  • /app/
    • アクセストークンを使用した機能を提供するページ

大まかな流れ

  1. ユーザーがトップページの認証リンクを踏む
  2. consumer keyとconsumer secretをAPIに送ってrequest token取得
  3. request tokenを含めた認証URLにユーザーをリダイレクト
  4. ユーザーが認証完了するとコールバックURLにリダイレクトされてくる
  5. コールバックURLに渡されたGETパラメータを元にアクセストークンを取得
  6. アクセストークンをDBに保存&セッションに保存して機能ページへリダイレクト
  7. 機能ページではセッションを持っていれば機能を提供、無ければサインインへリダイレクト

Model

とりあえず必要最低限

class User(models.Model):
    id = models.BigIntegerField(primary_key=True)
    access_token = models.CharField(max_length=255)
    access_token_secret = models.CharField(max_length=255)

Djangoデフォルトのidを使わずユーザIDをプライマリキーにしてみました。
twitterのIDは32bitを超えているのでBigIntegerFieldを使います。
アクセストークンは認証解除→再認証などで変更されるのでプライマリキーにはできません。

View

# coding: utf-8

from django.shortcuts import render, redirect
from requests_oauthlib import OAuth1Session

from myapp.models import *

CONSUMER_KEY = "(コンシューマキー)"
CONSUMER_SECRET = "(コンシューマシークレット)"

# トップページ(認証へのリンクを設置するページ)
def index(request):
    return render(request, 'myapp/index.html')

# 認証リンク
def signin(request):
    # request token取得
    callback_uri = "http://localhost:8000/callback/"
    oauth = OAuth1Session(
            CONSUMER_KEY,
            client_secret=CONSUMER_SECRET,
            callback_uri=callback_uri)
    request_token_url = "https://api.twitter.com/oauth/request_token"
    response = oauth.fetch_request_token(request_token_url)

    # 認証用URL作成
    redirect_url = "https://api.twitter.com/oauth/authenticate?oauth_token=" + response["oauth_token"]

    # 認証へリダイレクト
    return redirect(redirect_url)


# ユーザーが認証完了後にtwitterからリダイレクトされるURL
def callback(request):
    request_token = request.GET["oauth_token"]; # リクエストトークンは以前と同じもの
    verifier = request.GET["oauth_verifier"];
    oauth = OAuth1Session(
            CONSUMER_KEY,
            client_secret=CONSUMER_SECRET,
            resource_owner_key=request_token,
            verifier=verifier)
    access_token_url = "https://api.twitter.com/oauth/access_token"
    # アクセストークン取得
    response = oauth.fetch_request_token(access_token_url)

    # DBに追加or更新
    try:
        # レコードが存在するか確認
        user = User.objects.get(id=response["user_id"])
        if user.access_token != response["oauth_token"]:
            # アクセストークンが変わった場合更新
            user.access_token = response["oauth_token"]
            user.access_token_secret = response["oauth_token_secret"]
            user.save()
    except User.DoesNotExist:
        # 存在しなかったら追加
        user = User()
        user.id = response["user_id"]
        user.access_token = response["oauth_token"]
        user.access_token_secret = response["oauth_token_secret"]
        user.save()

    # セッションにトークンを保存
    request.session["access_token"] = response["oauth_token"]

    # リダイレクト
    return redirect("myapp.views.app")

# アクセストークンを使って機能を提供するページ
def app(request):
    access_token = request.session.get("access_token", None)
    if not access_token:
        # セッションにアクセストークンが無ければサインインに移行
        return redirect("myapp.views.signin")

    user = User.objects.get(access_token=access_token)

    # 以下、consumer key/secret、access token/secretの4つを使ってAPIを叩く

    print "access_token_key: " + user.access_token
    print "access_token_secret: " + user.access_token_secret

    return render(request, 'myapp/app.html')

色々エラー処理とか足りてないかもしれないですがとりあえずこんなイメージです。

その他

公式のSign in with Twitterボタン画像はここからダウンロードできます。
Sign in with Twitter Resources | Twitter Developers

スポンサーリンク
スポンサーリンク
Python
フォローする
Akashic Records

コメント

タイトルとURLをコピーしました