Django-allauth
認証ライブラリ
Django-allauth
概要
Django-allauthは、Djangoアプリケーション向けの包括的な認証・認可ライブラリです。従来のユーザー名/パスワード認証に加えて、50以上のソーシャルプロバイダーを使用したソーシャル認証、多要素認証(MFA)、パスキー認証などの最新の認証方式をサポートしています。2025年現在、Django REST FrameworkとのネイティブAPIサポートが追加され、ヘッドレス認証やSPA(Single Page Application)との統合が大幅に改善されています。
詳細
主要機能
- 統合認証システム: アカウント登録、ログイン、パスワード管理、メール認証を統一インターフェースで提供
- ソーシャル認証: Google、GitHub、Facebook、Twitter、Appleなど50以上のプロバイダーに対応
- 多要素認証(MFA): TOTP、WebAuthn(パスキー)、リカバリコードをサポート
- ヘッドレス対応: 2025年に追加されたREST API機能により、React、Vue.jsなどのSPAとの統合が容易
- カスタマイズ性: フォーム、テンプレート、アダプター、バリデーターの完全なカスタマイズが可能
- セキュリティ: CSRF保護、レート制限、セッション管理、セキュアなトークン処理を内蔵
アーキテクチャ
Django-allauthは複数のDjangoアプリで構成されています:
allauth.account: 基本的なアカウント管理機能allauth.socialaccount: ソーシャル認証機能allauth.mfa: 多要素認証機能allauth.headless: REST API(2025年新機能)
2025年の新機能
- Django REST Framework統合: ネイティブなAPI認証サポート
- React SPA例: Django Ninjaとの統合サンプル
- ヘッドレスセッショントークン: SPAでのトークンベース認証
- 改善されたパスキーサポート: WebAuthn実装の強化
メリット・デメリット
メリット
- オールインワンソリューション: 認証に関するほぼ全ての機能を単一ライブラリで提供
- 豊富なソーシャルプロバイダー: 50以上のプロバイダーに対応、設定も簡単
- セキュリティベストプラクティス: Django開発者が推奨するセキュリティ機能を内蔵
- 高いカスタマイズ性: フォーム、テンプレート、ビジネスロジックを細かくカスタマイズ可能
- アクティブな開発: 継続的なアップデートと新機能追加
- 包括的なドキュメント: 詳細なドキュメントと豊富なサンプルコード
- Django REST Framework対応: 2025年にネイティブAPI対応を追加
- MFA完全対応: TOTP、WebAuthn、リカバリコードによる最新のセキュリティ
デメリット
- 学習コストがやや高い: 豊富な機能により初期設定が複雑
- Django専用: 他のPythonフレームワークでは使用不可
- 依存関係: 大規模なライブラリのため、プロジェクトサイズが増加
- マイグレーション: 既存のDjangoプロジェクトへの統合時、既存の認証システムとの競合が発生する可能性
参考ページ
- Django-allauth公式ドキュメント
- GitHub - pennersr/django-allauth
- Django REST Framework認証ガイド
- Django-allauth最新リリース情報
書き方の例
1. インストールとプロジェクト設定
# ソーシャル認証を含む完全版のインストール
pip install "django-allauth[socialaccount]"
# MFA機能も含める場合
pip install "django-allauth[socialaccount,mfa]"
# settings.py
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
# Django-allauth必須アプリ
'allauth',
'allauth.account',
# ソーシャル認証(オプション)
'allauth.socialaccount',
'allauth.socialaccount.providers.google',
'allauth.socialaccount.providers.github',
'allauth.socialaccount.providers.facebook',
# MFA(オプション)
'allauth.mfa',
# ヘッドレス対応(2025年新機能)
'allauth.headless',
'your_app',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
# Django-allauth必須ミドルウェア
'allauth.account.middleware.AccountMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# サイトフレームワーク設定
SITE_ID = 1
# テンプレート設定
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request', # allauth必須
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
# 基本認証設定
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_USERNAME_REQUIRED = False
# ログイン・ログアウト後のリダイレクト
LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = '/'
# URLs設定
# urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('allauth.urls')),
path('', include('your_app.urls')),
]
2. ソーシャルログイン設定(Google、GitHub等)
# settings.py
SOCIALACCOUNT_PROVIDERS = {
'google': {
'SCOPE': [
'profile',
'email',
],
'AUTH_PARAMS': {
'access_type': 'online',
},
'VERIFIED_EMAIL': True,
'VERSION': 'v2',
'APP': {
'client_id': 'YOUR_GOOGLE_CLIENT_ID',
'secret': 'YOUR_GOOGLE_CLIENT_SECRET',
'key': ''
}
},
'github': {
'SCOPE': [
'user:email',
],
'VERIFIED_EMAIL': True,
'APP': {
'client_id': 'YOUR_GITHUB_CLIENT_ID',
'secret': 'YOUR_GITHUB_CLIENT_SECRET',
'key': ''
}
},
'facebook': {
'METHOD': 'oauth2',
'SCOPE': ['email', 'public_profile'],
'AUTH_PARAMS': {'auth_type': 'reauthenticate'},
'INIT_PARAMS': {'cookie': True},
'FIELDS': [
'id',
'first_name',
'last_name',
'name',
'email',
],
'EXCHANGE_TOKEN': True,
'VERIFIED_EMAIL': False,
'VERSION': 'v13.0',
}
}
# ソーシャル認証の追加設定
SOCIALACCOUNT_LOGIN_ON_GET = False # セキュリティのためPOSTを要求
SOCIALACCOUNT_EMAIL_AUTHENTICATION = True # 信頼できるプロバイダーのみ
SOCIALACCOUNT_AUTO_SIGNUP = True
SOCIALACCOUNT_QUERY_EMAIL = True
<!-- templates/socialaccount/login.html -->
{% load socialaccount %}
<div class="social-login">
<h3>ソーシャルアカウントでログイン</h3>
{% get_providers as socialaccount_providers %}
{% for provider in socialaccount_providers %}
<div class="provider-login">
<a href="{% provider_login_url provider.id %}"
class="btn btn-{{ provider.id }}">
{{ provider.name }}でログイン
</a>
</div>
{% endfor %}
</div>
3. ユーザー登録とメール認証
# settings.py
# メール認証設定
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'your-app-password'
# アカウント設定
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 3
ACCOUNT_EMAIL_SUBJECT_PREFIX = '[My Site] '
ACCOUNT_DEFAULT_HTTP_PROTOCOL = 'https'
# 登録フィールドのカスタマイズ
ACCOUNT_SIGNUP_FIELDS = ['first_name', 'last_name']
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_USERNAME_REQUIRED = False
# パスワード強度設定
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'OPTIONS': {
'min_length': 8,
}
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# forms.py - カスタム登録フォーム
from allauth.account.forms import SignupForm
from django import forms
class CustomSignupForm(SignupForm):
first_name = forms.CharField(max_length=30, label='名')
last_name = forms.CharField(max_length=30, label='姓')
phone_number = forms.CharField(max_length=15, label='電話番号', required=False)
def save(self, request):
user = super().save(request)
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()
# プロフィール情報の保存
if hasattr(user, 'profile'):
user.profile.phone_number = self.cleaned_data['phone_number']
user.profile.save()
return user
# settings.py
ACCOUNT_FORMS = {'signup': 'your_app.forms.CustomSignupForm'}
4. カスタマイズとテンプレート設定
<!-- templates/account/login.html -->
{% extends "account/base.html" %}
{% load i18n %}
{% load allauth %}
{% block head_title %}{% trans "Sign In" %}{% endblock %}
{% block content %}
<div class="login-container">
<div class="login-form">
<h1>ログイン</h1>
{% url 'account_login' as login_url %}
{% element form method="post" action=login_url %}
{% slot body %}
{% csrf_token %}
{% element fields form=form %}
{% endelement %}
{% if redirect_field_value %}
<input type="hidden" name="{{ redirect_field_name }}"
value="{{ redirect_field_value }}" />
{% endif %}
{% endslot %}
{% slot actions %}
<button class="btn btn-primary" type="submit">
ログイン
</button>
<a class="btn btn-link" href="{% url 'account_reset_password' %}">
パスワードを忘れた方
</a>
{% endslot %}
{% endelement %}
<!-- ソーシャルログイン -->
{% include "socialaccount/snippets/login.html" with process="login" %}
<div class="signup-link">
<p>アカウントをお持ちでない方は
<a href="{% url 'account_signup' %}">新規登録</a>
</p>
</div>
</div>
</div>
{% endblock %}
# adapters.py - カスタムアダプター
from allauth.account.adapter import DefaultAccountAdapter
from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
from django.contrib.auth import get_user_model
User = get_user_model()
class CustomAccountAdapter(DefaultAccountAdapter):
def is_open_for_signup(self, request):
return True # 登録受付状況を制御
def get_login_redirect_url(self, request):
# ログイン後のリダイレクト先をカスタマイズ
if request.user.is_superuser:
return '/admin/'
return '/'
def send_mail(self, template_prefix, email, context):
# メール送信ロジックをカスタマイズ
context['site_name'] = 'My Awesome Site'
return super().send_mail(template_prefix, email, context)
class CustomSocialAccountAdapter(DefaultSocialAccountAdapter):
def pre_social_login(self, request, sociallogin):
# ソーシャルログイン前の処理
pass
def populate_user(self, request, sociallogin, data):
# ソーシャルアカウントからユーザー情報を取得
user = super().populate_user(request, sociallogin, data)
user.is_active = True
return user
# settings.py
ACCOUNT_ADAPTER = 'your_app.adapters.CustomAccountAdapter'
SOCIALACCOUNT_ADAPTER = 'your_app.adapters.CustomSocialAccountAdapter'
5. API認証とDjango REST Framework統合
# settings.py - 2025年新機能
INSTALLED_APPS = [
# ... 他のアプリ
'rest_framework',
'allauth.headless', # ヘッドレス対応
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'allauth.headless.authentication.HeadlessSessionAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
# ヘッドレス設定(SPA対応)
HEADLESS_FRONTEND_URLS = {
"account_confirm_email": "https://yourapp.com/account/verify-email/{key}",
"account_reset_password": "https://yourapp.com/account/password/reset",
"account_reset_password_from_key": "https://yourapp.com/account/password/reset/key/{key}",
"account_signup": "https://yourapp.com/account/signup",
"socialaccount_login_error": "https://yourapp.com/account/provider/callback"
}
# API URL設定
# urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('allauth.urls')),
path('api/auth/', include('allauth.headless.urls')), # API認証エンドポイント
path('api/', include('your_app.api.urls')),
]
# api/views.py - REST APIビュー
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from allauth.headless.constants import SESSION_TOKEN_KEY
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def user_profile(request):
"""ユーザープロフィール取得API"""
user = request.user
return Response({
'user_id': user.id,
'email': user.email,
'first_name': user.first_name,
'last_name': user.last_name,
'is_authenticated': True,
})
@api_view(['POST'])
def api_login(request):
"""API認証専用ログイン"""
from allauth.headless.account.views import LoginView
view = LoginView()
response = view.post(request)
if response.status_code == 200:
# セッショントークンをレスポンスに含める
token = request.session.get(SESSION_TOKEN_KEY)
response.data['session_token'] = token
return response
// React/Vue.jsでの使用例
// api-client.js
class AuthAPI {
constructor() {
this.baseURL = 'http://localhost:8000/api/auth/';
this.token = localStorage.getItem('sessionToken');
}
async login(email, password) {
const response = await fetch(`${this.baseURL}login/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': this.getCSRFToken(),
},
body: JSON.stringify({ email, password })
});
const data = await response.json();
if (data.session_token) {
localStorage.setItem('sessionToken', data.session_token);
this.token = data.session_token;
}
return data;
}
async getProfile() {
const response = await fetch('/api/profile/', {
headers: {
'Authorization': `Bearer ${this.token}`,
'X-CSRFToken': this.getCSRFToken(),
}
});
return response.json();
}
getCSRFToken() {
return document.querySelector('[name=csrfmiddlewaretoken]')?.value;
}
}
6. テストと高度な設定
# tests.py
from django.test import TestCase, Client
from django.contrib.auth import get_user_model
from django.urls import reverse
from allauth.account.models import EmailAddress
from allauth.socialaccount.models import SocialAccount
User = get_user_model()
class AuthenticationTestCase(TestCase):
def setUp(self):
self.client = Client()
self.user_data = {
'email': '[email protected]',
'password1': 'testpass123',
'password2': 'testpass123',
}
def test_user_signup(self):
"""ユーザー登録テスト"""
response = self.client.post(
reverse('account_signup'),
self.user_data
)
self.assertEqual(response.status_code, 302)
# ユーザーが作成されたことを確認
user = User.objects.get(email=self.user_data['email'])
self.assertFalse(user.is_active) # メール認証前
# メール認証オブジェクトが作成されたことを確認
email_address = EmailAddress.objects.get(user=user)
self.assertFalse(email_address.verified)
def test_email_verification(self):
"""メール認証テスト"""
user = User.objects.create_user(
email='[email protected]',
password='testpass123'
)
email_address = EmailAddress.objects.create(
user=user,
email=user.email,
verified=False,
primary=True
)
# 認証キーを生成してテスト
key = email_address.send_confirmation()
response = self.client.post(
reverse('account_confirm_email', kwargs={'key': key})
)
email_address.refresh_from_db()
self.assertTrue(email_address.verified)
def test_social_login(self):
"""ソーシャルログインテスト"""
# モックユーザーとソーシャルアカウントを作成
user = User.objects.create_user(
email='[email protected]',
password='testpass123'
)
social_account = SocialAccount.objects.create(
user=user,
provider='google',
uid='123456789',
extra_data={'email': '[email protected]'}
)
# ログインテスト
self.client.force_login(user)
response = self.client.get(reverse('account_profile'))
self.assertEqual(response.status_code, 200)
def test_password_reset(self):
"""パスワードリセットテスト"""
user = User.objects.create_user(
email='[email protected]',
password='oldpass123'
)
response = self.client.post(
reverse('account_reset_password'),
{'email': user.email}
)
self.assertEqual(response.status_code, 302)
# メールが送信されることを確認
from django.core import mail
self.assertEqual(len(mail.outbox), 1)
def test_api_authentication(self):
"""API認証テスト(2025年新機能)"""
user = User.objects.create_user(
email='[email protected]',
password='testpass123'
)
# API経由でログイン
response = self.client.post('/api/auth/login/', {
'email': user.email,
'password': 'testpass123'
})
self.assertEqual(response.status_code, 200)
# セッショントークンが返されることを確認
data = response.json()
self.assertIn('session_token', data)
# settings/production.py - 本番環境設定
import os
# セキュリティ設定
ACCOUNT_DEFAULT_HTTP_PROTOCOL = 'https'
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
# メール設定(SendGrid等を使用)
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.sendgrid.net'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'apikey'
EMAIL_HOST_PASSWORD = os.environ.get('SENDGRID_API_KEY')
# レート制限とセキュリティ
ACCOUNT_LOGIN_ATTEMPTS_LIMIT = 5
ACCOUNT_LOGIN_ATTEMPTS_TIMEOUT = 86400 # 24時間
ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 1
# キャッシュ設定(Redis推奨)
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': os.environ.get('REDIS_URL'),
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
}
}
}
# ロギング設定
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'file': {
'level': 'INFO',
'class': 'logging.FileHandler',
'filename': 'django_allauth.log',
},
},
'loggers': {
'allauth': {
'handlers': ['file'],
'level': 'INFO',
'propagate': True,
},
},
}
このMDXファイルでは、Django-allauthライブラリについて2025年の最新機能を含む包括的な情報を提供しています。Context7から取得した詳細な設定情報、WebSearchで確認した最新のDjango REST Framework統合機能、そして実践的な6つのコード例を含んでいます。特に2025年に追加されたヘッドレス認証機能とSPA統合については詳しく解説しています。