概要
- Djangoフレームワーク+django-allauthパッケージで、Facebookログインを実装します
準備
- 環境構築 のリンクにあるように、docker compose で環境構築し、初期画面としてロケットの画像が出る状態にします
settings.py
の設定
-
基本は 公式ドキュメント の通りです
-
allauth、facebookログインの設定をします
-
INSTALLED_APPS
に"django.contrib.sites",
が必要ですが、公式ドキュメントには書かれていません
--- a/dj_fb_login/dj_fb_login/settings.py
+++ b/dj_fb_login/dj_fb_login/settings.py
@@ -37,6 +37,13 @@ INSTALLED_APPS = [
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
+ # sites
+ "django.contrib.sites",
+ # django-allauth
+ 'allauth',
+ 'allauth.account',
+ # Optional -- requires install using `django-allauth[socialaccount]`.
+ 'allauth.socialaccount',
+ # ... include the providers you want to enable:
+ 'allauth.socialaccount.providers.facebook',
]
MIDDLEWARE = [
@@ -47,6 +54,8 @@ MIDDLEWARE = [
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
+ # Add the account middleware:
+ "allauth.account.middleware.AccountMiddleware",
]
ROOT_URLCONF = "dj_fb_login.urls"
@@ -62,11 +71,20 @@ TEMPLATES = [
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
+ # `allauth` needs this from django
+ 'django.template.context_processors.request',
],
},
},
]
+AUTHENTICATION_BACKENDS = [
+ # Needed to login by username in Django admin, regardless of `allauth`
+ 'django.contrib.auth.backends.ModelBackend',
+ # `allauth` specific authentication methods, such as login by email
+ 'allauth.account.auth_backends.AuthenticationBackend',
+]
+
WSGI_APPLICATION = "dj_fb_login.wsgi.application"
@@ -125,3 +143,31 @@ STATIC_URL = "static/"
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
+
+
+# Site Setting for Login with Facebook.
+SITE_ID = 1
+
+# Provider specific settings
+SOCIALACCOUNT_PROVIDERS = {
+ "facebook": {
+ "METHOD": "oauth2",
+ "SDK_URL": "//connect.facebook.net/{locale}/sdk.js",
+ "SCOPE": ["email", "public_profile"],
+ "AUTH_PARAMS": {"auth_type": "reauthenticate"},
+ "INIT_PARAMS": {"cookie": True},
+ "FIELDS": [
+ "id",
+ "email",
+ "name",
+ "first_name",
+ "last_name",
+ "gender",
+ ],
+ "EXCHANGE_TOKEN": True,
+ "VERIFIED_EMAIL": False,
+ "VERSION": "v7.0",
+ #
+ "LOCALE_FUNC": lambda request: "ja_JP",
+ }
+}
データベースにallauthで必要なテーブルを作成
- Dockerコンテナ内で、データベースのマイグレーションを行います
docker exec -it django-fb-login-web-1 python manage.py migrate
Facebookアプリの審査に必要な仕組みの導入
- 開発者ページの「 App Review - Content 」によると、プライバシーポリシーのページを作る必要があります
- 同じく開発者ページの「 Developer Data Security Best Practices 」によると、利用者が退会したい場合の処理(アカウントの削除)ができる必要があるようです(利用者の住む国や地域によるかも知れません)
Facebookでアプリを作成
- Facebookでアプリを作成し、
App ID
とApp secret
をメモしておきます- Facebookログイン用のFacebookアプリを作成する をご覧ください
サイトURLの設定
-
https://localhost:5005/admin
を開いて、ログインして管理画面を表示します - 「SITES」-「Sites」をクリックして、
example.com
をlocalhost
に変更します- 実際のドメインがある場合は、読み替えてください(以下、同じ)
データベースにFacebook上のアプリを設定
-
https://localhost:5005/admin
を開いて、ログインして管理画面を表示します -
「SOCIAL ACCOUNTS」-「Social applications」の「Add」をクリックします
-
以下のように設定し、「Save」をクリックします
- Provider: Facebook
- Name: アプリ名
- Client ID: 上記で作成した
App ID
- Secret key: 上記で作成した
App secret
- Sites:
Available sites
から上記で作成したサイトlocalhost
を選択して、右向き矢印ボタンを押してChosen sites
に移す- (上記はDBの
socialaccount_socialapp
に入ります)
- (上記はDBの
- Saveボタンで保存します
-
以下のコマンドで、fixture用のyamlファイルを出力できます。ただし、アプリのID(client_id)やsecertが含まれてしまうので、ご注意ください。頻繁に再設定しない場合は、手動で上記の手順を行うのがよさそうです。
python manage.py dumpdata socialaccount.SocialApp --output socialapp_data.yml --format yaml
- model: socialaccount.socialapp
pk: 1
fields:
provider: facebook
provider_id: facebook
name: Myapp01
client_id: '1234567890'
secret: '9999999999'
key: ''
settings: {}
sites:
- 1
urlルーティングの追加
- 今回作成したプロジェクト内の
urls.py
に、allauthを使うパスを追加します- すでに
accounts/
が定義されている場合は、その下に追加します
- すでに
--- a/dj_fb_login/dj_fb_login/urls.py
+++ b/dj_fb_login/dj_fb_login/urls.py
@@ -15,8 +15,9 @@ Including another URLconf
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
-from django.urls import path
+from django.urls import include, path
urlpatterns = [
path("admin/", admin.site.urls),
+ path('accounts/', include('allauth.urls')),
+ path("accounts/", include("allauth.socialaccount.urls")),
]
ブラウザで表示確認
-
http://localhost:5005/accounts/login/
を開きます- adminで入ったままの場合は、
http://localhost:5005/accounts/logout/
を開いて、ログアウトします
- adminで入ったままの場合は、
- 下側にある「Or use a third-party」の「Facebook」リンクをクリックします
- 下側にある「Continue」ボタンをクリックします
- Facebookの認証画面が表示されます
- アプリIDやApp secretが間違っていると、エラーが出ます
- Facebookのアプリ側の設定が間違っていると「アクティブでないアプリです」「現在このアプリにアクセスできません。アプリの開発者は問題を認識しています。アプリが再びアクティブになった時点でログインできるようになります。」と表示されます
テンプレートの編集
-
公式サイトの templates をご覧ください
既存のテンプレートに「Login with Facebook」ボタンを追加する
以下を追加
{% load socialaccount %}
以下を追加
<div>
<a href="{% provider_login_url 'facebook' %}" class="btn-facebook">Signup with Facebook</a>
</div>
以下のスタイルシートを追加して、テンプレートから読み込み
.btn-facebook {
display: inline-block;
background-color: #1877F2;
color: white;
padding: 10px 20px;
text-align: center;
text-decoration: none;
border-radius: 5px;
}
.btn-facebook:hover {
background-color: #145dbf;
color: white;
}
Facebookログイン用のページを新規作成
-
templates/socialaccount/login.html
というファイルを新規作成します -
以下のように記述します
- 元の GitHubの該当リポジトリ からコピペして、postするボタンの部分を書き換えています
- 元は標準の灰色の小さいボタンだったため
- 元の GitHubの該当リポジトリ からコピペして、postするボタンの部分を書き換えています
{% extends "base.html" %} <!-- この辺は既存のテンプレートと合わせてください -->
{% load i18n %}
{% load allauth %}
{% load socialaccount %}
{% load static %}
{% block head_content %} <!-- この辺は既存のテンプレートと合わせてください -->
<link href="{% static 'css/btn_facebook.css' %}" rel="stylesheet">
{% endblock %}
{% block head_title %}
{% trans "Sign In" %}
{% endblock head_title %}
{% block content %}
{% if process == "connect" %}
{% element h1 %}
{% blocktrans with provider.name as provider %}Connect {{ provider }}{% endblocktrans %}
{% endelement %}
{% element p %}
{% blocktrans with provider.name as provider %}You are about to connect a new third-party account from {{ provider }}.{% endblocktrans %}
{% endelement %}
{% else %}
{% element h1 %}
{% blocktrans with provider.name as provider %}Sign In Via {{ provider }}{% endblocktrans %}
{% endelement %}
{% element p %}
{% blocktrans with provider.name as provider %}You are about to sign in using a third-party account from {{ provider }}.{% endblocktrans %}
{% endelement %}
{% endif %}
{% element form method="post" no_visible_fields=True %}
{% slot actions %}
{% csrf_token %}
<button type="submit" class="btn-facebook">
{% trans "Login with Facebook" %}
</button>
{% endslot %}
{% endelement %}
{% endblock content %}
スマフォでFacebookアプリを起動するように修正
- スマフォからのアクセス時にFacebookアプリを自動で起動するには、上記の
{% endblock content %}
の直前に、以下のコードを追加します- IDの
123456789012345
は、書き換えてください(3か所とも) - Android版のアプリを起動する際は、
fb://
で起動しなかったので、intent://
を使っています
- IDの
<script>
document.addEventListener("DOMContentLoaded", function() {
var userAgent = navigator.userAgent || navigator.vendor || window.opera;
var fbAppUrl = "intent://page/123456789012345#Intent;package=com.facebook.katana;scheme=fb;end";
var fbWebUrl = "https://www.facebook.com/123456789012345";
function openFacebookApp(url) {
var start = Date.now();
var timeout = setTimeout(function() {
if (Date.now() - start < 2000) {
window.location.href = fbWebUrl;
}
}, 1500);
window.location.href = url;
window.addEventListener('blur', function() {
clearTimeout(timeout);
});
}
if (/android/i.test(userAgent)) {
// Androidデバイスの場合
openFacebookApp(fbAppUrl);
} else if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) {
// iOSデバイスの場合
window.location.href = "fb://profile/123456789012345";
}
});
</script>