やったこと
Djangoを使用したwebアプリケーションでLINEログインを実装したので記録を残します。
こちらの記事に従って、
- LINEアカウントでのログイン
- LINEアカウント表示名の取得
- LINEプロフィール画像の取得
をできるようにしました。
前提環境
PC: MacBook Air M2
OS: macOS Ventura Ver. 13.2.1
Homebrew: 4.0.9
Docker: 20.10.23
docker-compose: v2.15.1
使用技術
インフラ: Docker
バックエンド: Python (Django REST framework)
フロントエンド: TypeScript (React)
設定内容
setting.py
チャネルIDとチャネルシークレットは.envファイルから取得しています。
SOCIAL_AUTH_LINE_KEY = os.environ.get('SOCIAL_AUTH_LINE_KEY')
SOCIAL_AUTH_LINE_SECRET = os.environ.get('SOCIAL_AUTH_LINE_SECRET')
ログイン/ログアウト後は後ほど記載するテンプレートを表示しています。
LOGIN_REDIRECT_URL = "/account_management/complete/line"
LOGOUT_REDIRECT_URL = "/account_management/complete/line"
Pipelineを使用してユーザー表示名とプロフィール画像URLをDjangoユーザーモデルに紐づけています。
SOCIAL_AUTH_PIPELINE = (
"social_core.pipeline.social_auth.social_details",
"social_core.pipeline.social_auth.social_uid",
"social_core.pipeline.social_auth.social_user",
"social_core.pipeline.user.get_username",
"social_core.pipeline.social_auth.associate_by_email",
"social_core.pipeline.user.create_user",
"social_core.pipeline.social_auth.associate_user",
"social_core.pipeline.social_auth.load_extra_data",
"social_core.pipeline.user.user_details",
"auth_management.pipeline.set_user_data",
)
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.db import models
class CustomUserManager(BaseUserManager):
"""
Custom manager for CustomUser
"""
def create_user(self, email, password=None, **extra_fields):
"""
Create and return a regular user with an email and password.
"""
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password=None, **extra_fields):
"""
Create and return a superuser with an email and password.
"""
user = self.create_user(email, password, **extra_fields)
user.is_staff = True
user.is_superuser = True
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
user.save(using=self._db)
return user
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True, blank=True, null=True)
username = models.CharField(max_length=200, unique=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
sns_icon_url = models.URLField(blank=True, null=True)
objects = CustomUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
def icon_url(self):
"""
ユーザーのSNSアイコン画像URLを返す。
1. SNS認証時にプロフィール画像を取得できた場合: sns_icon_url
2. SNS認証時にプロフィール画像を取得できない場合: デフォルト画像
"""
if self.sns_icon_url:
return self.sns_icon_url
else:
return staticfiles_storage.url('config/初期プロフィール画像.png')
def set_user_data(backend, strategy, details, response, user=None, *args, **kwargs):
"""
SNS認証時にプロバイダから取得したデータをプロフィールに設定する。
"""
if backend.name == "line":
# ユーザー名を取得。取得できなかった場合はuserIdをユーザー名とする。
username = response.get('displayName', response['userId'])
# アイコン未設定の場合は空文字を設定する。
icon_url = response.get('pictureUrl', '')
user.username = username
user.sns_icon_url = icon_url
user.save()
ライブラリのインストール
social-auth-app-djangoはrequirements.txtに記載し、docker-composeのビルド時にインストールしました。
Django==4.2
djangorestframework==3.14.0
django-currentuser
social-auth-app-django
mysqlclient==2.2.0
ログインURL
URL /account_management/login
でLINEログイン画面を表示します。
from django.urls import path, include
from django.contrib import admin
from django.contrib.auth import views as auth_views
from social_django.views import auth
from . import views
urlpatterns = [
path('', include('social_django.urls', namespace='social')),
path('login', auth, name='line-login', kwargs={'backend': 'line'}),
path('logout', auth_views.LogoutView.as_view(), name='logout'),
path('complete/line', views.complete_line, name='complete_line')
]
from django.shortcuts import render
def complete_line(request):
context = {}
return render(request, 'account_management/complete_line.html', context)
コールバックURL
コールバックURLはaccount_management/complete/line/
とし、
下記テンプレートを表示しました。
<h1>LINEログイン完了画面</h1>
{% if user.is_authenticated %}
<p>ユーザー名: {{ user.username }}</p>
<img src="{{ user.icon_url }}">
<a href="{% url 'logout' %}">ログアウト</a>
{% else %}
<p>ログインしていません。</p>
{% endif %}
LINEログインに成功すると、ユーザー名とプロフィール画像が表示されます。