python-social-auth/social-app-djangoで、WebサイトにGithubのOAuth認証を実装するまでのメモ

環境

DBはPostgresです。APIキー等の機密情報はpython-dotenvで管理します(参考:Djangoの環境変数管理をdirenvからdotenvに変えた話

1
2
3
4
5
6
7
8
$ python --version
Python 3.6.2

$ pip freeze
Django==2.0.5
python-dotenv==0.8.2
social-auth-app-django==2.1.0
social-auth-core==1.7.0

インストール

1
$ pip install social-auth-app-django

Githubでアプリケーション登録

Settings → Developer settingsでアプリ登録を行い、ClientIDClient Secretを生成します

1
2
3
4
// .envに設定
$ cat .env | grep SOCIAL
SOCIAL_AUTH_GITHUB_KEY=********************
SOCIAL_AUTH_GITHUB_SECRET=****************************************

settings.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
INSTALLED_APPS = [
'social_django', // ←追加
]

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ['webapp/templates'],
'APP_DIRS': True,
'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',
'social_django.context_processors.backends', // ←追加
'social_django.context_processors.login_redirect', // ←追加
],
},
},
]

// 追加(例)
LOGIN_REDIRECT_URL = '/?login=success'
LOGOUT_REDIRECT_URL = '/?logout=success'

// 追加
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'social_core.backends.github.GithubOAuth2', // ←追加
)

// 追加
SOCIAL_AUTH_GITHUB_KEY = os.environ.get('SOCIAL_AUTH_GITHUB_KEY')
SOCIAL_AUTH_GITHUB_SECRET = os.environ.get('SOCIAL_AUTH_GITHUB_SECRET')

webapp/urls.py

ログアウト処理は標準の認証機能と同じ物を使用するので、設定しておきます

1
2
3
urlpatterns = [
url(r'^accounts/logout/', auth_views.LogoutView.as_view()), // ←追加
]

migrate実行

1
$ python manage.py migrate

実行後、いくつかテーブルが作成されます

1
2
3
4
5
6
7
8
9
10
$ python manage.py showmigrations social_django
social_django
[X] 0001_initial (2 squashed migrations)
[X] 0002_add_related_name (2 squashed migrations)
[X] 0003_alter_email_max_length (2 squashed migrations)
[X] 0004_auto_20160423_0400 (2 squashed migrations)
[X] 0005_auto_20160727_2333 (1 squashed migrations)
[X] 0006_partial
[X] 0007_code_timestamp
[X] 0008_partial_timestamp
1
2
3
4
5
6
7
         tablename          | schemaname
----------------------------+------------
social_auth_association | public
social_auth_code | public
social_auth_nonce | public
social_auth_partial | public
social_auth_usersocialauth | public

ログインセッションのチェック処理

デコレータでログインセッションのチェックを実装します

1
$ vim webapp/decorators/social_required.py
1
2
3
4
5
6
7
def social_required(o_view):
def _wrapped_view(self, *args, **kwargs):
if self.request.user.id is not None:
self.auth_flg = True

return o_view(self, *args, **kwargs)
return _wrapped_view

View側でデコレータ呼び出し

1
$ vim webapp/views/index.py
1
2
3
4
5
6
7
8
9
10
11
12
13
// ※一部抜粋
from webapp.decorators.social_required import social_required // ← 追加

class IndexView(TemplateView):

auth_flg = False // ← 追加

@social_required // ← 追加
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["auth_flg"] = self.auth_flg // ← 追加

return context

テンプレート側

1
2
3
4
5
6
// ログインリンク(例)
{% if auth_flg == True%}
<a href="/accounts/logout/">ログアウト</a>
{% else %}
<a href="{% url "social:begin" "github" %}">ログイン</a>
{% endif %}