[PYTHON] Erstellen wir eine App, die OIDC mit Azure AD authentifiziert

Einführung

Wenn Sie überlegen, wie Azure AD mit Ihrer App funktioniert, können Sie Folgendes tun:

Die Informationen zu OpenID Connnect (OIDC) sind ziemlich umfangreich, aber ich hatte das Gefühl, dass die Informationen zu SCIM klein waren. Deshalb begann ich, einen Artikel zu schreiben, in der Hoffnung, dass es Einstellungen in Azure AD geben würde, und ein Beispiel für die Implementierung einer App. Dieses Mal werden wir uns jedoch mit dem Punkt befassen, an dem SSO mit dem ersten OIDC durchgeführt werden kann. Die App ist in Django implementiert und der Authentifizierungsfluss verwendet den Authentifizierungscodefluss. Vorerst werde ich es mit Blick auf die automatische Bereitstellung einstellen.

Machen wir das! (Der Quellcode für diese Zeit befindet sich auf github.)

1. Über Django

Django ist ein Python-Webanwendungsframework. Ich benutze es, weil es vorerst einfach ist, es zu bewegen. Wir hoffen, dass die folgenden Erklärungen Ihnen ein Gefühl dafür vermitteln, auch wenn Sie keine Erfahrung mit Django haben. Wenn Sie jedoch Erfahrung mit anderen MVC-Frameworks haben, können Sie durch die in diesem Artikel verwendete Django-Terminologie verwirrt sein. Seien Sie also bitte vorsichtig mit den folgenden Punkten.

Django verwendet das MVC-Muster, genau wie die meisten Webframeworks. Referenz: Informationen zum MVC-Modell Jedes Element heißt jedoch anders und heißt MTV (Model, View, Template). Es ist verwirrend, aber beachten Sie, dass ** Djangos Ansicht ein allgemeiner MVC-Controller ist **.

Quelle: [[Python] Django-Lernprogramm - Schnellste Erstellung einer allgemeinen Geschäftswebanwendung](https://qiita.com/okoppe8/items/54eb105c9c94c0960f14#djnago-%E3%81%AE-mvc%E3%83%91 % E3% 82% BF% E3% 83% BC% E3% 83% B3)

2. Informationen zum Auroraization Code Flow

Dies ist eine der gängigen Methoden zur Authentifizierung und Autorisierung von Webanwendungen. Details sind in den folgenden öffentlichen Informationen zusammengefasst. Befolgen Sie erneut den folgenden Artikel, um ein Token mithilfe der Microsoft Authentication Library (MSAL) zu erhalten.

Referenz: Fluss der Microsoft ID-Plattform und des OAuth 2.0-Authentifizierungscodes

3. Registrieren Sie die App bei Azure AD

Es gibt zwei Bildschirme zum Registrieren einer App in Azure AD: "App registrieren" und "Unternehmensanwendung". Sie müssen sich jedoch für die automatische Bereitstellung über "Unternehmensanwendung" registrieren. Sie benötigen eine Lizenz für Azure AD Premium P1 oder höher. Wenn Sie keine haben, verwenden Sie die kostenlose Testversion.

3.1 Registrieren Sie Ihre App unter ** Azure Portal> Azure Active Directory> Unternehmensanwendungen> Neue Anwendungen> Nicht-Galerie-Anwendungen **.

3.2 Suchen und öffnen Sie unter ** Azure Portal> Azure Active Directory> App registrieren> Alle Anwendungen ** die oben erstellte App.

3.3 Notieren Sie sich die "Anwendungs-ID" und "Verzeichnis-ID" auf der Seite ** Übersicht **.

3.4. ** Authentifizierung ** Fügen Sie den Umleitungs-URI von der Seite hinzu.

"Konten" ist der Name der App, die wir dieses Mal erstellen.

3.5. ** Zertifikate und Geheimnisse> Erstellen Sie ein Client-Geheimnis mit dem neuen Client-Geheimnis ** und notieren Sie es.

Dieses Mal verwende ich der Einfachheit halber das Client-Geheimnis. Zertifikate können auch als sicherere Methode verwendet werden.

4. Erstellen Sie ein Django-Projekt

Erstellen Sie ein "mysite" -Projekt mit dem folgenden Befehl:

django-admin startproject mysite

Fügen Sie einen Ordner hinzu, um die Vorlage zu platzieren.

mysite/settings.py


TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],  #hinzufügen
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

5. Erstellen Sie die Anwendung "Konten"

Erstellen Sie mit dem folgenden Befehl eine App namens "accounts" im Projekt "mysite":

python manage.py startapp accounts

Erstellen Sie "urls.py"

accounts/urls.py


from django.urls import include, path

from . import views

urlpatterns = [
    path('', views.index),
    path('login/', views.login_view, name='login'),
    path('logout/', views.logout_view, name='logout'),
    path('oidc/callback/', views.callback_view) 
]

/ accounts / oidc / callback ist der in Schritt 3.4 festgelegte Umleitungs-URI. Nach der Authentifizierung bei Azure AD wird der Benutzer zu diesem URI umgeleitet. Der zu diesem Zeitpunkt übergebene Autorisierungscode muss implementiert werden, damit er von views.callback_view verarbeitet werden kann.

Erstellen Sie ein benutzerdefiniertes Benutzermodell

Ermöglicht Benutzern, die mit Azure AD authentifiziert sind, die Anmeldung bei dieser App. Dazu müssen Sie Azure AD-Benutzer App-Benutzern zuordnen. Dieses Mal ordnen wir einen Benutzer zu, dessen ObjectId auf der Azure AD-Seite und die external_id der App identisch sind.

Erstellen Sie ein benutzerdefiniertes Benutzermodell und fügen Sie das Attribut external_id hinzu.

accounts/models.py


from django.db import models
from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    external_id = models.CharField(max_length=50, blank=True)

Ändern Sie den Administratorbildschirm, um die externe ID des Benutzers anzuzeigen.

accounts/admin.py


from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin

from .models import User


class UserAdmin(BaseUserAdmin):
    list_display = ['username', 'is_staff', 'is_active', 'external_id']


admin.site.register(User, UserAdmin)

Das benutzerdefinierte Benutzermodell sei das Authentifizierungsbenutzermodell.

mysite/settings.py


AUTH_USER_MODEL = 'accounts.User'  #hinzufügen

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'accounts.apps.AccountsConfig',  #hinzufügen
]

Fügen Sie der Projekt-URL "Konten" hinzu.

mysite/urls.py


from django.contrib import admin
from django.shortcuts import redirect  #hinzufügen
from django.urls import include, path  #include hinzugefügt

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', lambda req: redirect('accounts/', permanent=False)),  #hinzufügen
    path('accounts/', include('accounts.urls')),  #hinzufügen
]

6. Implementieren Sie den Authentifizierungscode-Fluss

Grundsätzlich können Sie die Authentifizierung mit Azure AD erreichen, indem Sie eine URL zum Azure AD-Authentifizierungsendpunkt erstellen und den Benutzer dorthin umleiten. Häufig verwendete Funktionen sind auch in der Bibliothek [MSAL] verfügbar (https://github.com/AzureAD/microsoft-authentication-library-for-python). Der folgende Code basiert auf Flask + MSAL Sample.

6.1. Fügen Sie einen Bildschirm hinzu.

6.2. Einstellungen für Authentifizierung und Autorisierung hinzufügen.

mysite/settings.py


# Azure AD

SCOPES = ['User.Read']
TENANT_ID = '{3.3.Verzeichnis-ID}'
AUTHORITY = f'https://login.microsoftonline.com/{TENANT_ID}/'
CLIENT_ID = '{3.3.Anwendungs-ID}'
REDIRECT_PATH = '{3.4.URI umleiten}'
CLIENT_SECRET = '{3.5.Kundengeheimnis}'
ENDPOINT = 'https://graph.microsoft.com/beta/me'

ENDPOINT ist eine API, auf die durch die Berechtigungen des angemeldeten Benutzers verwiesen wird. Dieses Mal wird API zur Erfassung von Benutzerinformationen ausgeführt, also "GELTUNGSBEREICHE" Ich füge User.Read hinzu.

6.3. Implementieren der Ansicht.

accounts/views.py


import uuid
import msal
from django.shortcuts import redirect
from django.contrib.auth import login, logout
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from django.contrib.auth import get_user_model

from mysite2 import settings

User = get_user_model()


@login_required
def index(request):
    context = {'user': request.user}
    return render(request, 'accounts/index.html', context)


def logout_view(request):
    logout(request)
    return redirect('/')


def login_view(request):
    request.session['state'] = str(uuid.uuid4())
    auth_url = _build_auth_url(
        scopes=settings.SCOPES, state=request.session['state'])
    context = {'auth_url': auth_url}
    return render(request, 'accounts/login.html', context)


def callback_view(request):
    if request.GET.get('state') != request.session.get('state'):
        # 'state'Stimmt nicht mit der Anfrage überein
        return redirect('/')
    if 'error' in request.GET:
        #Azure AD authentifiziert sich/Es wurde ein Autorisierungsfehler zurückgegeben
        return render(request, 'accounts/auth_error.html', request.GET)
    if 'code' in request.GET:
        cache = _load_cache(request)
        result = _build_msal_app(cache=cache).acquire_token_by_authorization_code(
            request.GET['code'],
            scopes=settings.SCOPES,  # Misspelled scope would cause an HTTP 400 error here
            redirect_uri=settings.REDIRECT_PATH)
        if 'error' in result:
            return render(request, 'accounts/auth_error.html', result)
        request.session['user'] = result.get('id_token_claims')

    try:
        #Oid auf der Azure AD-Seite und extern auf der App-Seite_Überprüfen Sie, ob der Benutzer dieselbe ID hat
        oid = request.session['user']['oid']
        user = User.objects.get(external_id=oid)
        login(request, user)
    except User.DoesNotExist as e:
        context = {'error': 'User.DoesNotExist', 'error_description': str(e)}
        return render(request, 'accounts/auth_error.html', context)

    return redirect('/')


def _build_auth_url(authority=None, scopes=None, state=None):
    return _build_msal_app(authority=authority).get_authorization_request_url(
        scopes or [],
        state=state or str(uuid.uuid4()),
        redirect_uri=settings.REDIRECT_PATH)


def _build_msal_app(cache=None, authority=None):
    return msal.ConfidentialClientApplication(
        settings.CLIENT_ID, authority=settings.AUTHORITY,
        client_credential=settings.CLIENT_SECRET, token_cache=cache)


def _load_cache(request):
    cache = msal.SerializableTokenCache()
    if request.session.get('token_cache'):
        cache.deserialize(request.session['token_cache'])
    return cache


def _save_cache(request, cache):
    if cache.has_state_changed:
        request.session['token_cache'] = cache.serialize()

Das Folgende sind die Punkte.

7. Führen Sie die App aus

#Erstellen Sie eine Datenbank
python manage.py makemigrations
python manage.py migrate

#Erstellen Sie einen Administrator
python manage.py createsuperuser

#Starten Sie den Server
python manage.py runserver

Sie können auf die App zugreifen, indem Sie in Ihrem Browser "http: // localhost: 8000 /" öffnen. / admin ist die Admin-Konsole.

8. Authentifizieren Sie sich bei Azure AD und melden Sie sich bei der App an

Melden Sie sich jetzt als Azure AD-Benutzer bei der App an.

Weisen Sie zunächst Benutzer zu, die sich auf der Seite ** Azure Portal> Azure Active Directory> Unternehmensanwendungen> Anwendungen> Benutzer und Gruppen ** anmelden möchten.

Da wir diesmal die automatische Bereitstellung nicht konfiguriert haben, starten Sie die Admin-Shell mit "python manage.py shell" und erstellen Sie manuell einen Benutzer auf der App-Seite, wie unten gezeigt.

from django.contrib.auth import get_user_model
User = get_user_model()
user = User.objects.create(username='{Benutzername des Azure AD-Benutzers}', external_id='{Azure AD-Benutzer ObjectId}') 
user.save()

Wenn der oben genannte Benutzer auf die App zugreift und die Anmeldeschaltfläche drückt, ist der Azure AD-Authentifizierungsbildschirm erforderlich. Wenn Sie dort Ihre Anmeldeinformationen eingeben, werden Sie aufgefordert, den unten gezeigten App-Berechtigungen zuzustimmen. Dieser Zustimmungsbildschirm erfordert nur einen erstmaligen Zugriff. Darüber hinaus kann der Administrator die Einwilligung von Mandant zu Mandant erteilen. In diesem Fall wird der Einwilligungsbildschirm den allgemeinen Benutzern nicht angezeigt.

2019-12-24_07h04_10.png

Wenn Sie hier akzeptieren, haben Sie sich erfolgreich angemeldet!

2019-12-24_07h21_12.png

Die App kann auch auf APIs zugreifen, die durch die Berechtigungen des angemeldeten Benutzers geschützt sind.

2019-12-24_07h21_58.png

abschließend

Ich konnte mich als Azure AD-Benutzer bei der App anmelden.

Der Grund für die Erstellung der externalId des benutzerdefinierten Benutzers dieses Mal ist die Authentifizierung und die Implementierung der [SCIM-API](Benutzerbereitstellung von SCIM in Azure Active Directory (Azure AD)). Es ist jedoch ziemlich schwierig, eine nach der anderen zu implementieren. Wenn Sie also eine Bibliothek für die SCIM-API haben, sollten Sie diese verwenden. Diesmal scheint Django eine Bibliothek namens django-scim2 zu haben, aber es scheint, dass das benutzerdefinierte Benutzermodell auch für die Bibliothek neu erstellt werden muss. Wenn Sie die SCIM-API verwenden, müssen Sie möglicherweise bereits in der Entwurfsphase nachdenken. Ich werde versuchen, beim nächsten Mal eine App zu erstellen, die die automatische Bereitstellung unterstützt!

Recommended Posts

Erstellen wir eine App, die OIDC mit Azure AD authentifiziert
Erstellen Sie eine App, die Schüler mit Python errät
Erstellen Sie eine englische Wort-App mit Python
Erstellen Sie eine Bildkompositions-App mit Flask + Pillow
[kotlin] Erstellen Sie eine App, die Fotos erkennt, die mit einer Kamera auf Android aufgenommen wurden
Erstellen Sie mithilfe der COTOHA-API eine App, die gut mit Berichten von Personen funktioniert
Lassen Sie uns eine App erstellen, die ähnliche Bilder mit Python und Flask Part1 durchsuchen kann
Lassen Sie uns eine App erstellen, die ähnliche Bilder mit Python und Flask Part2 durchsuchen kann
Erstellen Sie eine Umgebung mit virtualenv
Erstellen Sie eine API mit Django
Erstellen wir ein Skript, das sich bei Ideone.com in Python registriert.
Lassen Sie uns eine externe Spezifikation erstellen, die einfach zu handhaben ist
Erstellen einer Todo-App mit Django ① Erstellen Sie eine Umgebung mit Docker
Erstellen Sie eine App, die LINE jeden Morgen über das Wetter informiert
Erstellen Sie eine Altersgruppe mit Pandas
Lassen Sie uns mit Azure Face Emotionen erkennen
Erstellen Sie eine Web-App, die mit Plotly Dash einfach visualisiert werden kann
Erstellen Sie eine Anwendung, indem Sie mit Pygame klassifizieren
Erstellen einer Bildaufteilungs-App mit Tkinter
Erstellen Sie mit PySimpleGUI einen Bildverarbeitungs-Viewer
Erstellen wir mit Python eine kostenlose Gruppe
Erstellen Sie schnell eine Excel-Datei mit Python #python
Erstellen Sie eine GUI-App mit Tkinter of Python
Erstellen Sie mit Django Updateview einen Update-Bildschirm
Erstellen Sie eine einfache Web-App mit Flasche
Erstellen der ersten App mit Django Startprojekt
[Python] Erstellen Sie schnell eine API mit Flask
Generieren Sie eine add-in-fähige Excel-Instanz mit xlwings
Lassen Sie uns mit Python 1 einen Investitionsalgorithmus entwickeln
Erstellen Sie mit cx_Freeze eine aktualisierbare MSI-Datei
Mit LINEBot habe ich eine Anwendung erstellt, die mich über die "Buszeit" informiert.