[PYTHON] [Note d'étude] Intégration OAuth2 entre les projets django

introduction

Cet article était Article très utile pour étudier le flux d'intégration OAuth2 entre deux projets django créés dans l'environnement local. Ceci est un résumé avec quelques notes ajoutées pour moi-même, faisant référence à projects-oauth2 /). À l'exception des changements dans le style d'écriture d'URLconf et de django.contrib.auth en raison de la mise à jour de django, l'article original est presque détourné.

Cible

Créez deux projets Django (test_provider, test_consumer) dans votre environnement local et obtenez des informations de profil (factices) avec OAuth2

Aperçu du projet

Code source

test_provider

test_consumer

Structure du répertoire

test-oauth
│
├── test_consumer
│   ├── templates
|   |   └──index.html
|   |
│   ├── test_consumer
|   |   ├── __init__.py
|   |   ├── settings.py
|   |   ├── urls.py
|   |   └── wsgi.py
|   |
|   ├── testprovider
|   |   ├── __init__.py
|   |   ├── provider.py
|   |   ├── urls.py
|   |   └── wsgi.py
|   |
│   ├── manage.py
│   └── db.sqlite3
├── test_provider
|   ├── templates
|   |   └──registration
|   |      └──login.html
|   |
|   ├── test_provider
|   |   ├── __init__.py
|   |   ├── settings.py
|   |   ├── urls.py
|   |   └── wsgi.py
|   |
|   ├── db.sqlite3
|   └── manage.py
|
├── .gitignore
├── Pipfile
└── Pipfile.lock

environnement

Développement du fournisseur OAuth2

Création de projet


mkdir test-oauth
$ cd test-oauth
$ pipenv --python 3.8
$ pipenv install django, django-oauth-toolkit, django-cors-headers
$ pipenv shell

(pipenv)$ django-admin.py startproject test_provider
(pipenv)$ cd test_provider

Modifier test_provider / settings.py

Ajouté à INSTALLED_APPS

settings.py


INSTALLED_APPS = [
    #ajouter à
    'oauth2_provider',
    'corsheaders',
]

Ajouté à MIDDLEWARE_CLASSES

settings.py


MIDDLEWARE = [
    #ajouter à
    'corsheaders.middleware.CorsMiddleware',
]

Comme mentionné dans les Documents officiels, Il semble que vous deviez l'écrire sur le middleware intégré `` django.middleware.common.CommonMiddleware ''.

Ajouter à la fin

settings.py


CORS_ORIGIN_ALLOW_ALL = True

Modification de test_provider / urls.py

test_provider/urls.py



from django.contrib import admin
from django.urls import path, include
from .views import profile_view, top_view

urlpatterns = [
    path('admin/', admin.site.urls),
    path('o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
    path('', top_view),
    path('accounts/', include('django.contrib.auth.urls')),
    path('api/profile/', profile_view, name='profile'),
]

Puisque je veux le créer rapidement, la fonction de connexion utilise ** django.contrib.auth **, qui est une fonction d'authentification intégrée, et lance les modèles d'URL et les vues dans leur intégralité (les modèles doivent être créés par vous-même).

Créez test_provider / views.py

test_provider/views.py


from django.http import JsonResponse
from oauth2_provider.views.generic import ProtectedResourceView
from django.http import HttpResponse


def top_view(request):
    return HttpResponse("It works!")

class ProfileView(ProtectedResourceView):
    def get(self, request, **kwargs):
        user = request.resource_owner

        return JsonResponse({
            'user_id': user.id,
            'email': user.email,
            'date_joined': user.date_joined,
            'secret_message': 'This is secret message',
        })


profile_view = ProfileView.as_view()

Ici, une vue qui affiche simplement la première page et une vue qui renvoie JSON des informations utilisateur sont définies.

Enregistrez l'application Oauth sur le site d'administration

(pipenv)$ python manage.py migrate
(pipenv)$ python manage.py createsuperuser
(pipenv)$ python manage.py runserver

Enregistrez l'application OAuth à l'avance pour obtenir l'ID client et le secret client de l'application. À ce moment-là, enregistrez également l'URL de rappel de l'application Web. Connectez-vous une fois au site d'administration (http://127.0.0.1:8000/admin/) pour accéder à la page des paramètres du fournisseur. http://127.0.0.1:8000/o/applications/ Ouvrez et ajoutez l'application OAuth avec laquelle travailler.

Éléments de réglage Définir la valeur
Name n'importe quoi
client Type Confidential
Authorization grant type Authorization code
Redirect urls: http://localhost:8001/accounts/testprovider/login/callback/
(Comme ci-dessus) http://127.0.0.1:8001/accounts/testprovider/login/callback/

Créer un utilisateur de test

Créez un utilisateur à utiliser lors de la connexion à OAuth. http://127.0.0.1:8000/admin/auth/user/

Création d'une application de test consommateur OAuth2

Créez une application qui demande l'authentification et l'autorisation de test_provider.

Création de projet

(pipenv)$ cd test-oauth

(pipenv)$ django-admin.py startproject test_consumer

(pipenv)$ cd test_consumer

Modifier test_consumer / settings.py

Ajouté à INSTALLED_APP

test_consumer/settings.py


INSTALLED_APPS = [
    #ajouter à
   'django.contrib.sites',
   'test_consumer',
   'allauth',
   'allauth.account',
   'testprovider',
]

Ajouter à la fin

test_consumer/settings.py


AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
)

SITE_ID = 1
SESSION_COOKIE_NAME = 'test-consumer-session-id'
#Rediriger vers la première page après la connexion
LOGIN_REDIRECT_URL = '/'

Spécifiez la destination de la transition après l'authentification avec ** LOGIN_REDIRECT_URL **.

Modification de test_consumer / urls.py

test_consumer/urls.py



from django.contrib import admin
from django.urls import path, include
from django.views.generic import TemplateView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', TemplateView.as_view(template_name='index.html')),
    path('accounts/', include('allauth.urls')),
]

Créer un modèle

(pipenv)$ mkdir test_consumer/templates

index.html


<!DOCTYPE html>
{% load socialaccount %}
{% load account %}

<html>
<head>
    <meta charset="utf-8">
    <title>testprovider</title>
</head>
<body>
{% if user.is_authenticated %}
Bienvenue{% user_display user %}M.<br />
  {% for sa in user.socialaccount_set.all %}
    {{ sa.extra_data }}<br />
  {% endfor %}
{% else %}
  <a href="{% provider_login_url "testprovider" %}">
Connectez-vous avec Test Provider
  </a>
{% endif %}
</body>
</html>

Pour vérifier l'opération, utilisez ** {% if user.is_authenticated%} ** pour afficher le lien de connexion à l'état déconnecté et les informations utilisateur à l'état connecté.

Création d'un adaptateur de fournisseur de test

Hériter de la classe Provider en se référant à Implémentation de django-allauth pour la connexion pour divers fournisseurs Implémentez l'adaptateur de fournisseur de test. [Une addition] Les fournisseurs qui ne sont pas dans les fournisseurs de django-allauth peuvent réécrire cette zone pour créer ** une fonction de connexion sociale oleore personnalisée. ** **

testprovider/provider.py


from allauth.socialaccount import providers
from allauth.socialaccount.providers.base import ProviderAccount
from allauth.socialaccount.providers.oauth2.provider import OAuth2Provider

class TestAccount(ProviderAccount):

    def to_str(self):
        dflt = super(TestAccount, self).to_str()
        return self.account.extra_data.get('name', dflt)

class TestProvider(OAuth2Provider):
    id = 'testprovider'
    name = 'Test Provider'
    account_class = TestAccount

    def get_default_scope(self):
        return ['read', 'write']

    def get_site(self):
        settings = self.get_settings()
        return settings.get('SITE', 'testprovider')

    def extract_uid(self, data):
        uid = str(data['user_id'])
        return uid

    def extract_common_fields(self, data):
        return dict(username=data.get('email', 'no name'))

providers.registry.register(TestProvider)

testprovider/urls.py


from allauth.socialaccount.providers.oauth2.urls import default_urlpatterns
from .provider import TestProvider

urlpatterns = default_urlpatterns(TestProvider)

testprovider/views.py



import requests

from allauth.socialaccount.providers.oauth2.views import (OAuth2Adapter,
                                                          OAuth2LoginView,
                                                          OAuth2CallbackView)
from allauth.socialaccount.providers import registry

from .provider import TestProvider

from django.conf import settings

server_url_prefix = getattr(
    settings, 'TEST_PROVIDER_URL_PREFIX',
    'http://127.0.0.1:8000')

class TestOAuth2Adapter(OAuth2Adapter):
    provider_id = TestProvider.id
    access_token_url = server_url_prefix + '/o/token/'
    authorize_url = server_url_prefix + '/o/authorize/'
    profile_url = server_url_prefix + '/api/profile/'

    def complete_login(self, request, app, token, **kwargs):
        provider = registry.by_id(app.provider)
        resp = requests.get(self.profile_url,
                            params={'access_token': token.token})

        extra_data = resp.json()
        return self.get_provider().sociallogin_from_response(
            request, extra_data)

oauth2_login = OAuth2LoginView.adapter_view(TestOAuth2Adapter)
oauth2_callback = OAuth2CallbackView.adapter_view(TestOAuth2Adapter)

Enregistrement initial des données sur le site d'administration

(pipenv)$ python manage.py migrate
(pipenv)$ python manage.py createsuperuser
(pipenv)$ python manage.py runserver 8001

http://127.0.0.1:8001/admin Cliquez sur + Ajouter dans [COMPTES SOCIAUX]> [Applications sociales] Définissez le "client ID" et le "client secret" de l'application enregistrée côté test_provider

Éléments de réglage Définir la valeur
Provider Test Provider
Name Test Provider
Client id ID client créé plus tôt
Secret key Clé secrète que j'ai créée plus tôt
Key Ciel
Sites example.Sélectionnez com

Contrôle de fonctionnement

http://127.0.0.1:8001 Connectez-vous en tant qu'utilisateur de test que vous avez créé précédemment avec un navigateur différent de celui que vous avez connecté avec test_provider.

[Connexion avec le fournisseur de test]> "Autoriser"

Si la liaison d'ID réussit, la destination sera la destination de la redirection http://127.0.0.1:8001 après une connexion réussie définie dans ** test_consumer / settings.py **, et les informations utilisateur qui n'étaient pas vues lors de la déconnexion seront affichées. Il est censé être affiché.

À la fin

Ensuite, je développerai ce contenu pour créer une fonction de connexion sociale pour les fournisseurs de services qui n'est pas fournie par ** django-allauth **.

Recommended Posts

[Note d'étude] Intégration OAuth2 entre les projets django
Mémo d'apprentissage Django
Note d'étude LPIC101
mémo du didacticiel django
mémo de déploiement heroku (Django)
Twitter OAuth avec Django
Django memo n ° 1 à partir de zéro
Planification des tâches @ mémo d'étude
Script Shell @ mémo d'étude
[Memo] Environnement de développement Django