Djangoでソーシャルアカウントを扱う

先日の番付メーカーではTwitterとFacebookのアカウントでログインできるようになっています。

ソーシャルアカウントを使うと、地味なくせに工数のかかるユーザ管理を実装せずにすむので助かりますね。ところがソーシャルアカウントを扱うのも楽チンとまでは言えません。そもそもOAuthの処理を実装するのも面倒ですし、TwitterとFacebookを両方扱うとなってくると割と大変です。加えてGoogle+だYahooだとなってくると頭が痛くなってきます。

Hextrisを作ったときは自前でTwitterのOAuthでのログイン処理を書いたのですが、今回はFacebookアカウントも扱うというので複雑度が3倍くらいになって面倒です。

これはアカン、なんか無いのと思って調べてみるとDjango-Social-Authというナイスモジュールが見つかりました。これはDjangoのアプリとして実装されているソーシャルアカウント管理モジュールで、今のところ20を超えるソーシャルサービスに対応しています。Twitter・Facebookどころか、EvernoteやらInstagramやらDropboxやらメボしいサービスが、ほぼ網羅されています。素晴らしいですね。というわけで簡単に使い方をメモしておきます。

ちなみに使用可能なサービス一覧はコチラで確認できます。

設定

インストールはpipで一発です。

$ pip install django-social-auth

次にsettings.pyに準備をします。下記ではTwitterとFacebookを扱う場合の設定を行っています。AUTHENTICATION_BACKENDSと、TWITTER_CONSUMER_KEYなどのサービス毎の設定項目は、当然ながら必要なサービスによって違ってくるので注意してください。各サービスに必要な設定項目はコチラからたどる事ができます。

# social_authアプリを追加
INSTALLED_APPS = (
    ...
    'social_auth',
)

# Context Processorを追加
TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    'social_auth.context_processors.social_auth_by_name_backends',
 )

# 必要なソーシャルサービスに応じて追加
AUTHENTICATION_BACKENDS = (
    'social_auth.backends.twitter.TwitterBackend',
    'social_auth.backends.facebook.FacebookBackend',
    'django.contrib.auth.backends.ModelBackend',
)

# 必要なソーシャルサービスに応じて認証に必要な情報を記述
TWITTER_CONSUMER_KEY         = 'your consumer key'
TWITTER_CONSUMER_SECRET      = 'your cosumer secret'
FACEBOOK_APP_ID              = 'your facebook app id'
FACEBOOK_API_SECRET          = 'your facebook api secret'
FACEBOOK_EXTENDED_PERMISSIONS = ['publish_stream']

# ログインを行うURLなどの設定
LOGIN_URL          = '/login/'
LOGIN_REDIRECT_URL = '/dashboard/'
LOGIN_ERROR_URL    = '/login-error/'
 

次にurls.pyにsocialauthアプリのビューを設定します。OAuth認証時に必要なコールバックやらがココで設定されています。

urlpatterns = patterns(
    '',

    url(r'', include('social_auth.urls')),
    ...
)

以上で設定が完了しました。設定を書くだけでソーシャルアカウントに対応できるなんて素晴らしいですね。

使い方

テンプレート内でログインボタンを作ります。settings.pyで設定したLOGIN_REDIRECT_URLとは別のURLにリダイレクトしたい場合は、nextパラメータを設定します。

<a href="{% url socialauth_begin 'twitter' %}">Twitterアカウントでログイン</a>
<a href="{% url socialauth_begin 'twitter' %}?next={{callback_url}}">Twitterアカウントでログイン</a>

ログイン後の処理を見てみます。ログイン時に新規ユーザの場合はDjangoのUserモデルが作成されます。そのためlogin_requiredデコレータを使えますし、username等のプロパティへのアクセスはrequest.userを通して行います。通常の処理と変わりません。またUserSocialAuthというモデルにアクセストークンが保持されていて、このトークンを使って各サービスのAPIにアクセスできます。

なおsessionオブジェクト内にsocial_auth_last_login_backendキーが追加されていて、最後にログインしたバックエンドの名前が保持されています。この情報を利用して複数のサービスに対応しながら、特定のサービスでログインした場合のみの処理などを追加できます。

@login_required
def some_view(request):
    print request.user.username
    # facebookでログインしてるときだけ
    if request.session['social_auth_last_login_backend'] == 'facebook':
        auth = UserSocialAuth.objects.filter(user=request.user).get()
        token = auth.tokens['access_token']
        # do something with this access token
    ...

少し違和感があるのが、ログアウト処理は自分で書く必要がある事です。モジュール側でやってくれたら良いのにと思いますが、何か理由があるのでしょう。素直に書くと以下のような処理でしょうか。

def logout(request):
    django_logout(request)
    return HttpResponseRedirect('/path/to/redirect')

他にも複数のサービスのアカウントを1つのユーザと紐づける等、必要そうな処理は大体備えていて、ほとんどユーザ管理回りでコード書かなくて良くなるので助かります。

まとめ

というわけでDjangoでソーシャルサービス使うときは、Django-Social-Auth使ったら良いんじゃないかなと思います。

Leave a Reply

Your email address will not be published. Required fields are marked *