djangoアプリケーションにおけるallauthを用いたユーザー認証機能の実装

今回のお題
-
今回は、allauthというライブラリを用いてユーザー認証機能を実装していきます。

位置付けはあくまでも自分用のメモですが、よろしければご覧ください。

目次
-

- 今回実装する内容
- 今回実装しない内容
- ライブラリの導入
- アプリの作成
- settings.pyの編集
- urls.pyの編集
- views.pyの編集
- ログイン状態に応じた表示の切り替え
- おまけ〜ルーティングnameの調べ方

今回実装する内容
-
今回実装する内容は、以下の通りです。

- メールアドレスとパスワードを用いたサインアップ機能
- メールアドレスとパスワードを用いたサインアウト機能
- ログアウト機能
- ホーム画面
- ログイン状態の有無に応じた表示の切り替え

とは言ったものの、ホーム画面以外のビューはallauthにてあらかじめ用意されているので、導入の流れを覚えてしまえばすぐに実装できるかと思います。


今回実装しない内容
-
以下の内容については、今回は取り扱いません。

- ユーザー登録時の入力項目の追加(年齢、電話番号など）
- ユーザー登録時のメールアドレス認証（登録したアドレス宛届いたメールのリンクを開くことで最終的なユーザー登録が完了するというやつです。）
- ログイン時の確認項目の追加・変更（メールアドレスの代わりにユーザー名でログインできるようにすると言ったことは今回はしません）
- SNS認証
- ユーザー情報やパスワードの変更
- crispyを用いたユーザー認証関連のテンプレートの編集(crispyについては[こちら](https://qiita.com/keishi04hrikzira/items/e38d583f4a370315629c))

では、早速やっていきます。

:::note
軽く調べたところ、allauthの導入にあたりユーザー管理用のアプリケーションをプロジェクト内に立ち上げるパターンとアプリを立ち上げないパターンがあるそうです。

プロジェクト内に複数のアプリを立ち上げてユーザー認証機能を使い回すことを考えて、今回はaccountsという専用のアプリを立ち上げることにします。

また、ビューについては関数ベースのものを使用します。
:::

ライブラリの導入
-
まずはライブラリを導入します。

仮想環境内で以下のコマンドを実行してください。

```shell
% pip install django-allauth
```
これで必要なライブラリがインストールされます。

インストールした内容についてはlib/python3.x/sitepackages以下に作成されるallauthディレクトリに格納されます。

アプリの作成
-
次に、ユーザー管理用のアプリを作ります。

```shell
% python manage.py startapp accounts
```

settings.pyの編集
-
アプリが作れたので、settigs.pyを編集します。

```python
INSTALLED_APPS = [
    # ...省略...
    # allauth
    "accounts",
    "django.contrib.sites",
    "allauth",
    "allauth.account",
    "allauth.socialaccount",# allauthここまで
]

# MIDDLEWAREの次あたりに以下を追加
# allauthの認証設定
AUTHENTICATION_BACKENDS = [
    "django.contrib.auth.backends.ModelBackend",
    "allauth.account.auth_backends.AuthenticationBackend",
]

# allauthの設定
SITE_ID = 1 

# サインアップ・ログイン・ログアウト時のリダイレクト先URL
LOGIN_REDIRECT_URL = "/myapp" # "/"が抜けると相対パス扱いになるので注意
ACCOUNT_LOGOUT_REDIRECT_URL = "/accounts/login/"

# 認証方式の設定。今回はメールアドレスとパスワード
ACCOUNT_AUTHENTICATION_METHOD = "email"
ACCOUNT_USERNAME_REQUIRED = False # ユーザー名を登録するかどうか。サインアップ画面でユーザー名を要求するかどうかはこの変数の切り替えのみで決まる。

# ユーザー登録時のメールアドレス認証(none=送信しない、mandatory=送信する)
ACCOUNT_EMAIL_VERIFICATION = "none"
ACCOUNT_EMAIL_REQUIRED = True
```
補足は適宜コメントで入れているのであまり問題はないかなと思います。

強いて言えば以下の認証設定ですかね。

```python
AUTHENTICATION_BACKENDS = [
    "django.contrib.auth.backends.ModelBackend",
    "allauth.account.auth_backends.AuthenticationBackend",
]
```
私もあまりわかっていないのですが、
>djangoの認証はdjango.contrib.auth.authenticate関数で行われている。
この関数が呼び出されるとAUTHENTICATE_BACKENDSとして設定された関数を順に実行し、認証が成功すればその時点で認証されたユーザーを返す。

という仕組みだそうです。

二つ目の"allauth.account.auth_backends.AuthenticationBackend"はallauthライブラリの中に用意されている認証機能なので、これを呼び出しリストの中に追加しているというわけですね。

何はともあれ設定ファイルが作れたので、ディスパッチャを編集していきます。

urls.pyの編集
-
アプリケーション側(accounts)にurls.pyを作成したのち、以下のようにファイルを編集します。

```python:urls.py(プロジェクト側)
urlpatterns = [
  path("home/", include("accounts.urls")),
  path("accounts/", include("allauth.urls")),# namespaceをつけることは非推奨
]
```
```python:urls.py(アプリケーション側)
urlpatterns = [
  path("", views.home, "home"),
]
```
ログインやサインインのページに行くためのホーム画面には/homeというurlを対応させました。

また、allauthライブラリのallauth.urls.pyにはログインやサインアップなどの各種ユーザー認証ページへのルーティングがあらかじめ用意されているので、/accountsというリクエストは全てそちらに振り分けられるようにしています。

:::note alert
上記でもコメントしましたが、allauth.urlsへのルーティングにnamespaceを設定するのはお勧めできません。
allauthにあらかじめ用意されているテンプレートは全てnamespaceを使わない前提で記述されており、その部分の書き直しが大量に発生するためです。
:::

さて、これでルーティングが完了したので残るはviewsとテンプレートですね。

と言ってもほとんどはallauthが用意してくれているので、自分で作るのはhome画面周りぐらいです。

viewsの編集
-

```python:accounts/views.py
def home(request):
  return render(request, "accounts/home.html")
```
簡単と言えば簡単ですし、冗長と言えば冗長ですね。

最も、クラスベースのビューであればこの辺りも解決するのですが・・・

ログイン状態に応じた表示の切り替え
-
home画面のテンプレートについては、特にこれといった必須項目がないので省略します。

代わりに、ログイン状態に応じた表示内容の変更方法を解説します。

```django
{% if user.is_authenticated %}
```
上記のように記述することで、テンプレートの表示内容をログイン状態に応じて変更できます。

おまけ〜ルーティングnameの調べ方
-
ログインやサインアップなどに対応するルーティングnameは、lib.python.site-packages.allauth.account.urls.pyに記述されています。

```python:accounts.urls.py
    # ルーティングname一例
    path("signup/", views.signup, name="account_signup"),
    path("login/", views.login, name="account_login"),
    path("logout/", views.logout, name="account_logout"),
```
使用頻度の高いものは覚えてしまって構わないと思いますが、もしわからなくなっても上記のファイルを調べれば大丈夫です。

終わりに
-
以上でallauthの導入が完了しました。

ただ、冒頭で触れたようにまだまだ追加実装の余地は山のようにあるので、そちらについてもいずれ取り上げます。