DjangoアプリにGoogleでログインできるようにする

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3001224/e24b6bc1-f8d2-5723-0ad1-3051bb492405.png)](https://asameshicode.com/django-login-with-google/)


こんにちは。今日はDjangoアプリにGoogleなどのソーシャルメディアアカウントを使ってログインする方法を紹介します。

今回使用するdjango-allauthライブラリを使用することにより、ソーシャルメディアでユーザーをサインアップさせることができます。

詳しいドキュメンテーションは[こちらを参照](https://django-allauth.readthedocs.io/en/latest/installation.html)してください。（英語ですが。）

完成したサンプルコードは[こちら（GitHub）](https://github.com/TraitOtaku/Django-google-signup)を参照してください。

あと、Googleクラウドのサービスは課金されるものになるのでテストが完了したら課金はオフにしておきましょう。（最初に登録した場合は無料のクレジットがもらえるはずですが。）


## **概要**

DjangoはPythonのウェブフレームワークで、データベースとの連携からAPIの作成まですべてカバーできる素晴らしいフレームワークです。今回のDjangoアプリのAuthentication（認証）はDjangoアプリであり、DjangoのREST APIを使ったものではありません。今後APIを使ったソーシャルメディアのログインの仕方も紹介したいのでご期待を！


## **今日の環境**



* Python 3.11
* [Django 4.1](https://www.djangoproject.com/)
* [django-allauth](https://github.com/pennersr/django-allauth)ライブラリ


## **django-allauthライブラリ**

django-allauthはGitHubで7.8kのスターが付いている中レベルの人気のライブラリです。Django自体が69.1kのスターでDjangoの中でも人気のあるライブラリといえるでしょうか。

**django-allauthライブラリの特徴**を上げます。



* ローカルのアカウントとソーシャルメディアのアカウントを同時にサインアップさせることができます。
* ローカルアカウントに一つ以上のソーシャルメディアのアカウントを接続させることができます。
* ソーシャルアカウントを外したい場合でローカルのアカウントを残したい場合はローカル用のパスワードを設定する必要があります。
* ソーシャルアカウント（Googleなど）を使って即座にサインアップできます。
* メールアドレスの管理ができる（複数の登録、メインのメールアドレスの登録）
* パスワードを忘れた場合のフローがあります。
* メールアドレスの証明のフローがあります。

2023年の3月時点でサポートされているプロバイダーです。記事の下の方にすべて記載したものがあります。



* **Amazon (OAuth2)**
* AngelList (OAuth2)
* Bitly (OAuth2)
* Dropbox (OAuth)
* Facebook (both OAuth2 and JS SDK)
* Feedly (OAuth2)
* **Github (OAuth2)**
* **Google (OAuth2)**
* **Instagram (OAuth2)**
* **LinkedIn (OAuth, OAuth2)**
* OpenId
* Paypal (OAuth2)
* Persona
* SoundCloud (OAuth2)
* Stack Exchange (OAuth2)
* Twitch (OAuth2)
* **Twitter (OAuth)**
* Vimeo (OAuth)
* VK (OAuth2)
* Weibo (OAuth2)など。。。
* （yahooなども追加されています。）

知っておきたい細かい特徴



* 複数のログイン方法をサポートできます。（メールアドレス、ユーザーネームでの認証）
* アカウントの証明方法をなし、もしくはメールアドレスで確認する方法がサポートされています。
* アクセストークンはデータベースに保管されます。
* 追加でサインアップの際に質問を追加することができます。
* Facebook, Twitterなどのライクはデータベースでコンフィグできます。（SocialApp モデルを参照）


## **Djangoアプリの作成**

では、下記のコマンドを使ってDjangoアプリをセットアップしていきます。


```python
#オプショナルで仮想環境を作成
pip install virtualenv
virtualenv env
source env/bin/activate
#WIndows
env\Scripts\activate
python -m pip install Django
django-admin startproject authapp
#authappは自分でつけたアプリ名です。
```


アプリができたらアプリのディレクトリに移動し、データベースを作成します。

そのままスーパーユーザー（アドミンのアカウント）を作成しましょう。


```python
cd authapp/
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver
```


では、最後のrunserverのコマンドでテストサーバーを起動し、ブラウザからアクセスしてみましょう。

問題がなければCtl+Cで一旦サーバーを止めて、次に進みます。


## **Django-allauthのインストール**

次にメインのdjango-allauthのライブラリをインストールします。


```python
pip install django-allauth
```


では、インストールができたらテキストエディタを開いてsettings.pyを編集していきます。

まずは変数TEMPLATESを見てください。これはいじる必要はありませんが、allauthがこの’django.template.context_processors.request’を使うことだけ知っておきましょう。


```py
TEMPLATES = [
   {
       'BACKEND': 'django.template.backends.django.DjangoTemplates',
       'DIRS': [],
       'APP_DIRS': True,
       'OPTIONS': {
           'context_processors': [
               # Already defined Django-related contexts here
               # `allauth` needs this from django
               'django.template.context_processors.request',
           ],
       },
   },
]
```


つぎにAUTHENTICATION_BACKENDS変数を追加します。


```python
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 e-mail
   'allauth.account.auth_backends.AuthenticationBackend',
]
```


‘django.contrib.auth.backends.ModelBackend’はDjangoのローカルアカウントでログインするための認証を設定するものです。

‘allauth.account.auth_backends.AuthenticationBackend’はallauthで使う方です。

次にINSTALLED_APPSを見てください。

ここにライブラリのアプリと、必要なソーシャルメディアのアプリを登録します。不要なものは外してください。


```python
INSTALLED_APPS = [
   ...
   # The following apps are required:
   'django.contrib.auth',
   'django.contrib.messages',
   'django.contrib.sites',
   'allauth',
   'allauth.account',
   'allauth.socialaccount',
   # ... include the providers you want to enable:
   'allauth.socialaccount.providers.agave',
   'allauth.socialaccount.providers.amazon',
   'allauth.socialaccount.providers.amazon_cognito',
   'allauth.socialaccount.providers.angellist',
   'allauth.socialaccount.providers.apple',
   'allauth.socialaccount.providers.asana',
   'allauth.socialaccount.providers.auth0',
   'allauth.socialaccount.providers.authentiq',
   'allauth.socialaccount.providers.azure',
   'allauth.socialaccount.providers.baidu',
   'allauth.socialaccount.providers.basecamp',
   'allauth.socialaccount.providers.battlenet',
   'allauth.socialaccount.providers.bitbucket',
   'allauth.socialaccount.providers.bitbucket_oauth2',
   'allauth.socialaccount.providers.bitly',
   'allauth.socialaccount.providers.box',
   'allauth.socialaccount.providers.cern',
   'allauth.socialaccount.providers.cilogon',
   'allauth.socialaccount.providers.clever',
   'allauth.socialaccount.providers.coinbase',
   'allauth.socialaccount.providers.dataporten',
   'allauth.socialaccount.providers.daum',
   'allauth.socialaccount.providers.digitalocean',
   'allauth.socialaccount.providers.dingtalk',
   'allauth.socialaccount.providers.discord',
   'allauth.socialaccount.providers.disqus',
   'allauth.socialaccount.providers.douban',
   'allauth.socialaccount.providers.doximity',
   'allauth.socialaccount.providers.draugiem',
   'allauth.socialaccount.providers.drip',
   'allauth.socialaccount.providers.dropbox',
   'allauth.socialaccount.providers.dwolla',
   'allauth.socialaccount.providers.edmodo',
   'allauth.socialaccount.providers.edx',
   'allauth.socialaccount.providers.eventbrite',
   'allauth.socialaccount.providers.eveonline',
   'allauth.socialaccount.providers.evernote',
   'allauth.socialaccount.providers.exist',
   'allauth.socialaccount.providers.facebook',
   'allauth.socialaccount.providers.feedly',
   'allauth.socialaccount.providers.figma',
   'allauth.socialaccount.providers.fivehundredpx',
   'allauth.socialaccount.providers.flickr',
   'allauth.socialaccount.providers.foursquare',
   'allauth.socialaccount.providers.frontier',
   'allauth.socialaccount.providers.fxa',
   'allauth.socialaccount.providers.gitea',
   'allauth.socialaccount.providers.github',
   'allauth.socialaccount.providers.gitlab',
   'allauth.socialaccount.providers.globus',
   'allauth.socialaccount.providers.google',
   'allauth.socialaccount.providers.gumroad',
   'allauth.socialaccount.providers.hubic',
   'allauth.socialaccount.providers.instagram',
   'allauth.socialaccount.providers.jupyterhub',
   'allauth.socialaccount.providers.kakao',
   'allauth.socialaccount.providers.keycloak',
   'allauth.socialaccount.providers.lemonldap',
   'allauth.socialaccount.providers.line',
   'allauth.socialaccount.providers.linkedin',
   'allauth.socialaccount.providers.linkedin_oauth2',
   'allauth.socialaccount.providers.mailchimp',
   'allauth.socialaccount.providers.mailru',
   'allauth.socialaccount.providers.mediawiki',
   'allauth.socialaccount.providers.meetup',
   'allauth.socialaccount.providers.microsoft',
   'allauth.socialaccount.providers.naver',
   'allauth.socialaccount.providers.nextcloud',
   'allauth.socialaccount.providers.odnoklassniki',
   'allauth.socialaccount.providers.openid',
   'allauth.socialaccount.providers.openid_connect',
   'allauth.socialaccount.providers.openstreetmap',
   'allauth.socialaccount.providers.orcid',
   'allauth.socialaccount.providers.patreon',
   'allauth.socialaccount.providers.paypal',
   'allauth.socialaccount.providers.persona',
   'allauth.socialaccount.providers.pinterest',
   'allauth.socialaccount.providers.pocket',
   'allauth.socialaccount.providers.quickbooks',
   'allauth.socialaccount.providers.reddit',
   'allauth.socialaccount.providers.robinhood',
   'allauth.socialaccount.providers.salesforce',
   'allauth.socialaccount.providers.sharefile',
   'allauth.socialaccount.providers.shopify',
   'allauth.socialaccount.providers.slack',
   'allauth.socialaccount.providers.snapchat',
   'allauth.socialaccount.providers.soundcloud',
   'allauth.socialaccount.providers.spotify',
   'allauth.socialaccount.providers.stackexchange',
   'allauth.socialaccount.providers.steam',
   'allauth.socialaccount.providers.stocktwits',
   'allauth.socialaccount.providers.strava',
   'allauth.socialaccount.providers.stripe',
   'allauth.socialaccount.providers.telegram',
   'allauth.socialaccount.providers.trainingpeaks',
   'allauth.socialaccount.providers.trello',
   'allauth.socialaccount.providers.tumblr',
   'allauth.socialaccount.providers.twentythreeandme',
   'allauth.socialaccount.providers.twitch',
   'allauth.socialaccount.providers.twitter',
   'allauth.socialaccount.providers.twitter_oauth2',
   'allauth.socialaccount.providers.untappd',
   'allauth.socialaccount.providers.vimeo',
   'allauth.socialaccount.providers.vimeo_oauth2',
   'allauth.socialaccount.providers.vk',
   'allauth.socialaccount.providers.wahoo',
   'allauth.socialaccount.providers.weibo',
   'allauth.socialaccount.providers.weixin',
   'allauth.socialaccount.providers.windowslive',
   'allauth.socialaccount.providers.xing',
   'allauth.socialaccount.providers.yahoo',
   'allauth.socialaccount.providers.yandex',
   'allauth.socialaccount.providers.ynab',
   'allauth.socialaccount.providers.zoho',
   'allauth.socialaccount.providers.zoom',
   'allauth.socialaccount.providers.okta',
   'allauth.socialaccount.providers.feishu',
   ...
]
```


次にSITE_IDを追加します。


```python
SITE_ID = 1
```


最後にオプショナルでソーシャルメディアのプロバイダーごとで細かい設定を追加することができます。

今回は省きますが参考のコードはこれになります。


```python
# Provider specific settings
SOCIALACCOUNT_PROVIDERS = {
   'google': {
       # For each OAuth based provider, either add a ``SocialApp``
       # (``socialaccount`` app) containing the required client
       # credentials, or list them here:
       'APP': {
           'client_id': '123',
           'secret': '456',
           'key': ''
       }
   }
}
```


次にurls.pyにaccountsのURLを追加します。


```python
from django.urls import path, include
urlpatterns = [
   ...
   path('accounts/', include('allauth.urls')),
   ...
]
```


これにより下記のことができるようになります。

django.contrib.auth.urlsが提供するローカルのDjangoアカウントで使える**<code>login</code>, <code>logout</code></strong>のURLは使用する必要はありません。

代わりに、**allauth**のライブラリが提供する`account_login`, `account_logout`, `account_set_password`のURLが使えるようになります。

ではインストールが完了したらallauthで使用するデータベースのテーブルを作ります。


```python
python manage.py migrate
#サーバーを起動します。
python manage.py runserver
```



## **使えるURL**

では、allauthのライブラリですでに設定されているURLを見てみます。ブラウザからhttp://127.0.0.1:8000/accounts/にアクセスしてみましょう。accounts/はdjango-allauthで指定されたURLですね。

そうすると下記のようにデフォルトで使えるURLが確認できます。


```python
admin/
accounts/ signup/ [name='account_signup']
accounts/ login/ [name='account_login']
accounts/ logout/ [name='account_logout']
accounts/ password/change/ [name='account_change_password']
accounts/ password/set/ [name='account_set_password']
accounts/ inactive/ [name='account_inactive']
accounts/ email/ [name='account_email']
accounts/ confirm-email/ [name='account_email_verification_sent']
accounts/ ^confirm-email/(?P<key>[-:\w]+)/$ [name='account_confirm_email']
accounts/ password/reset/ [name='account_reset_password']
accounts/ password/reset/done/ [name='account_reset_password_done']
accounts/ ^password/reset/key/(?P<uidb36>[0-9A-Za-z]+)-(?P<key>.+)/$ [name='account_reset_password_from_key']
accounts/ password/reset/key/done/ [name='account_reset_password_from_key_done']
accounts/ google/
```


では試しに、http://127.0.0.1:8000/accounts/signup/のURLにアクセスしてみます。


## **allauthライブラリのコンフィグ**

次に[django-allauthのコンフィグ](https://django-allauth.readthedocs.io/en/latest/configuration.html)を見てみます。

このようにサインアップのテンプレートが表示されました。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3001224/cfc48a26-4cde-a8f7-d001-88777cdeac89.png)



ここでDjangoのアドミンパネルでログインしている人は一旦ログアウトしておきましょう。

ログインしているユーザーがProfileページに誘導されてしまうのでサインアップページにアクセスできません。

（そこまで設定されているのでよいですが。）


## **Django-allauthのコンフィグ**

ここで、Django-allauthの**[コンフィグのページ](https://django-allauth.readthedocs.io/en/latest/configuration.html)**を見て何ができるか見ておきます。

例えば、サインアップの際にEmailがオプショナルになっているようなので下記の部分をsettings.pyに追加してEmailを必須にすることもできます。


```python
ACCOUNT_EMAIL_REQUIRED=True
```


そうするとEmailが必須になったことが分かりますね。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3001224/b6593e02-7d0b-de5f-bf8e-a639cef521dd.png)



## **Googleのシークレットキー**

ではアドミンパネルでSocial applicationsテーブルを見てみます。ここに新しいデータを追加してGoogleのコンフィグを完了させたいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3001224/90867b19-744b-f747-1344-42507a76c37b.png)



では必要なAPIキーをGoogleクラウドから作成しましょう。

[https://console.cloud.google.com/](https://console.cloud.google.com/)

もしGoogleクラウドコンソールに慣れていない人は色々なことができるので試してみてください。（前回紹介した[Googleマップを使ったカスタムマップの記事](https://asameshicode.com/custom-google-map/)も参考にしてください。）

今日は簡単に始められる方法を紹介します。

まずは下記のURLにアクセスしてください。

[https://developers.google.com/gmail/api/quickstart/js?hl=ja](https://developers.google.com/gmail/api/quickstart/js?hl=ja)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3001224/fd46c5e4-0bc8-70d4-72dc-2de512be2a4d.png)



ここでAPIの有効化のボタンを押します。

次にプロジェクトを確認タブの次へをクリックします。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3001224/e05c1f79-d8e1-267f-52c0-f05d4d18dfa0.png)



有効にします。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3001224/7ac29330-3c98-d42a-7fa2-fd2d948851dc.png)



これで右上のベルのマークを見るをプロジェクトにAPIが追加されたことが表示されます。それをクリックしてください。

そうするとダッシュボードにたどり着きます。

下からは、Googleクラウドから作成する方法を紹介します。

とりあえずは、左のメニューからAPIとサービス→認証情報をクリックします。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3001224/9c6eab6e-19e6-abb7-04cc-c5f41febfbf3.png)



では、このページから＋認証情報を作成をクリックします。

OAuthクライアントIDを作成します。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3001224/8f1b8973-682b-82d7-b810-a306d70fbb78.png)



質問に従い、認証情報を作成します。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3001224/db2dae34-5678-675a-cd61-4e10fcb5dbd1.png)



クライアントIDができたらクライアント名をクリックしてクライアントIDをコピーします。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3001224/8386f24c-7f7f-f2dd-4e2b-d3420d2d2f59.png)



では、コピーしたクライアントIDとシークレットキーをDjangoのSocial ApplicationsのGoogleデータにペーストします。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3001224/ebccb638-38bd-80fe-2e6e-8f3c4bd6ffbf.png)



ちなみにこれらの情報は絶対に他人にシェアしないようにしてください。画像のものは無効化されているので使い物になりません。


## **Googleでログインのテスト**

ではGoogleのアカウントでログインできるかテストしましょう。

http://127.0.0.1:8000/accounts/login/

のURLからGoogleのリンクを開きます。

そうするとおなじみのGoogleのアカウントでログインのページに飛ばされました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3001224/971ec0a1-5136-c4ea-6e01-d0ed7b793498.png)





ログインが完了するとhttp://127.0.0.1:8000/accounts/profile/のページにリダイレクトされましたね！

では、DjangoのアドミンパネルでUsersを参照すると先ほどGoogleでログインしたユーザーが追加されていることが証明できました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3001224/64207552-ac5d-84ca-758a-19bab508f825.png)




ちなみにすべてのログイン、ログアウト、サインアップ、プロフィールなどのテンプレートはDjango-allauthのライブラリの中にあります。実際に作成する場合はtemplatesディレクトリを作成してスタイルがあるものを作成することになるのでそれが次のステップになると思います。

では、お疲れ様です。