DjangoでTwitter OAuth

こちらの記事に便乗して投稿です．DjangoでもTwitter認証を試してみます．

【備忘録】pyramidでtwitter OAuth
[http://qiita.com/maueki/items/02f001440ce409641a50](http://qiita.com/maueki/items/02f001440ce409641a50)

# Djangoの標準ユーザ認証

Twitter認証の前に，Djangoにはユーザ認証がはじめから用意されています．まずはそちらを見ていきます．

## 環境準備

まずはdjangoをインストール．

```bash
$ pip install django
```

今回はバージョン1.10.5で試しました．Pythonは3.5.2です．
続いてDjangoのプロジェクト作成と管理者ユーザを作成．

```bash
$ django-admin startproject myoauth
$ cd myoauth
$ python manage.py migrate
$ python manage.py createsuperuser
```

続いてアプリを作成しておきます．

```bash
$ python manage.py startapp app
```

`settings.py`のINSTALLED_APPSに作成したアプリを追加します．（ついでにロケールの設定くらいは変更しておくといいかも）

```py3:setting.py
INSTALLED_APPS = (
    :
    'app.apps.AppConfig',
)

LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'
```

このあたりの詳細は，本家のチュートリアルを見るとわかりやすいです．
[https://docs.djangoproject.com/ja/1.9/intro/tutorial01/](https://docs.djangoproject.com/ja/1.9/intro/tutorial01/)

## ログイン・ログアウトページ

`urls.py`にログイン，ログアウトのurlとviewを指定．viewは標準で用意されています．(viewはMTVパターンでのviewです．)

```py3:urls.py
import django.contrib.auth.views

urlpatterns = [
    :
    url(r'^login/$',
        django.contrib.auth.views.login,
        {
            'template_name': 'app/login.html',
        },
        name='login'),
    url(r'^logout/$',
        django.contrib.auth.views.logout,
        {
            'template_name': 'app/logout.html',
        },
        name='logout'),
]
```

login.htmlはこんな感じで用意します．

```html:login.html
:
<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<table>
<tr>
    <td>{{ form.username.label_tag }}</td>
    <td>{{ form.username }}</td>
</tr>
<tr>
    <td>{{ form.password.label_tag }}</td>
    <td>{{ form.password }}</td>
</tr>
</table>

<input type="submit" value="login" />
<input type="hidden" name="next" value="{{ next }}" />
</form>
:
```

setting.pyにログイン後にリダイレクトされるURLと，後述する制限付きのページにアクセスしたときに移動するURLを記述します．

```py3:setting.py
LOGIN_REDIRECT_URL = '/'
LOGIN_URL = '/login/'
```

## ログイン状態のチェック

viewに`login_required`デコレータを付けると，ログインしている場合のみに制限をかけることができます．ログインされていない場合はsetting.pyで設定したLOGIN_URLに遷移します．

```py3:views.py
from django.contrib.auth.decorators import login_required

@login_required
def private(request):
    ...
```

```py3:urls.py
urlpatterns = [
    :
    url(r'^private/$', app.views.private, name='private'),
]
```

そのほか`user_passes_test`デコレータを使えば，ラムダでユーザに対する任意のチェックを付けることができます．下の例はスーパーユーザー権限に限定しています．

```py3:views.py
from django.contrib.auth.decorators import user_passes_test

@user_passes_test(lambda u: u.is_superuser)
def private(request):
    ...
```

# Twitter認証

次にTwitter認証を試してみます．

## アプリケーション登録

前準備としてTwitterの開発者用ページからアプリケーションの登録を行います．
[https://apps.twitter.com](https://apps.twitter.com)

* Consumer Key
* Consumer Secret

この2つの鍵が必要になります．

## OAuth用ライブラリを追加

いろいろと選択肢はあるようですが，今回は`social-auth-app-django`を使いました．TwitterのほかFacebookやGitHubも同じように使えます．

```bash
$ pip install python-social-auth[django]
```

今回試したバージョンは1.0.0になります．

```py3:setting.py
INSTALLED_APPS = (
    :
    'social_django',
)

TEMPLATES = [
    {
        :
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'django.template.context_processors.media',
                'django.template.context_processors.static',
                'social_django.context_processors.backends',
                'social_django.context_processors.login_redirect',
            ],
        },
    },
]

AUTHENTICATION_BACKENDS = [
    'social_core.backends.twitter.TwitterOAuth',
    'django.contrib.auth.backends.ModelBackend',
]

SOCIAL_AUTH_TWITTER_KEY = 'Consumer Key'
SOCIAL_AUTH_TWITTER_SECRET = 'Consumer Secret'

```

Twitter認証へとばすボタンはこんな感じに用意できます．

```html:login.html
<button type="button" onclick="location.href='{% url 'social:begin' 'twitter' %}'">Twitter</button>
```

```py:urls.py
urlpatterns = [
    :
    url(r'', include('social_django.urls', namespace = 'social')),
]
```

アプリを追加したので，最後にmigrateしておきます．

```bash
$ python manage.py migrate
```

これでTwitter認証ができます．認証後はDjangoの標準ユーザモデルにも追加されるので，ログイン状態のチェックなどは標準のユーザ認証と同じに行うことができます．