paint-brush
Über die Anmeldung hinaus: Implementieren Sie eine differenzierte Autorisierung mit ZITADELvon@zitadel
2,434 Lesungen
2,434 Lesungen

Über die Anmeldung hinaus: Implementieren Sie eine differenzierte Autorisierung mit ZITADEL

von ZITADEL20m2023/11/10
Read on Terminal Reader

Zu lang; Lesen

Dieser Artikel befasst sich mit dem Übergang von der traditionellen rollenbasierten Zugriffskontrolle zu einer differenzierten Sicherheit. ZITADEL erweitert die Autorisierung um dynamische Funktionen und unterstützt die externe Integration für maßgeschneiderte Anforderungen. Ein praktisches Beispiel veranschaulicht diese Prinzipien in der Praxis. Für praxisorientierte Entwickler behandelt der Artikel eine vollständige Code-Implementierung in Python.
featured image - Über die Anmeldung hinaus: Implementieren Sie eine differenzierte Autorisierung mit ZITADEL
ZITADEL HackerNoon profile picture
0-item
1-item


Einführung

Während wir uns einer Zero-Trust-Denkweise zuwenden, werden die Grenzen grobkörniger Sicherheitsmaßnahmen wie des traditionellen RBAC-Systems deutlich. Ein wesentlicher Teil des Übergangs zu Zero Trust, der oft nicht diskutiert wird, ist der Übergang von grobkörniger zu feinkörniger Sicherheit.


Eine differenzierte Autorisierung behebt dieses Problem, indem sie den Zugriff auf Attributen wie Benutzerrollen, Aktionen und sogar Kontext wie Zeit oder Ort basiert. Eine solch detaillierte Zugriffskontrolle ist für moderne Anwendungen von entscheidender Bedeutung. In diesem Artikel wird erläutert, wie ZITADEL berücksichtigt die Notwendigkeit einer derart differenzierten Autorisierung.


Mit den Funktionen von ZITADEL wie Rollen, Metadaten und Aktionen können Benutzer eine äußerst detaillierte Zugriffskontrolle erhalten, die für eine Zero-Trust-Umgebung geeignet ist. Darüber hinaus kann ZITADEL mit externen Autorisierungsdiensten zusammenarbeiten.

Von ZITADEL angebotene Autorisierungsmechanismen

ZITADEL ist ein Open Source , cloudnative Identitäts- und Zugriffsverwaltungslösung (IAM), geschrieben in Go. ZITADEL ist als SaaS-Lösung verfügbar und auch Open Source für diejenigen, die Selbsthosting-Optionen suchen, was Flexibilität gewährleistet. Es deckt sowohl B2C- als auch B2B-Anwendungsfälle ab.


Zu seinen Hauptzielen gehört die Bereitstellung schlüsselfertiger Funktionen für Authentifizierung, Autorisierung, Anmeldung und Single Sign-On (SSO) und ermöglicht gleichzeitig die Anpassung über Benutzeroberflächen.


Es verfügt über einen umfangreichen Audit-Trail zur Verfolgung aller Änderungen, ermöglicht Entwicklern die Erweiterung von Funktionalitäten mit benutzerdefiniertem Code (Aktionen), unterstützt weithin anerkannte Standards wie OIDC, OAuth, SAML und LDAP, legt Wert auf einfache Bedienung und Skalierbarkeit und bietet umfassende APIs für vielseitige Integration.

Rollenbasierte Zugriffskontrolle (RBAC) und delegierter Zugriff

ZITADEL verwendet RBAC zur Verwaltung von Benutzerberechtigungen, wobei Berechtigungen an Rollen gebunden sind und den Benutzern diese Rollen zugewiesen werden. Dies vereinfacht die Benutzerzugriffsverwaltung basierend auf ihren Organisationsrollen. Eine zusätzliche Funktion ermöglicht die Delegierung von Rollen an andere Organisationen und erleichtert so die gemeinsame Nutzung von Berechtigungen mit externen Einheiten.


Dies ist besonders wertvoll für vernetzte oder hierarchische Organisationen.


Obwohl diese Funktionen eine robuste Zugriffskontrolle bieten, reichen sie möglicherweise nicht für komplexe Autorisierungsanforderungen aus. Daher ist es wichtig, die detaillierte Autorisierung in ZITADEL zu untersuchen.

Die Aktionsfunktion, benutzerdefinierte Metadaten und Ansprüche für die attributbasierte Zugriffskontrolle (ABAC)

ZITADEL erweitert das traditionelle RBAC durch die Einführung seiner Dynamik Aktionen Funktion für attributbasierte Zugriffskontrolle (ABAC). Im Gegensatz zu RBAC, das den Zugriff auf der Grundlage von Benutzerrollen gewährt, ist ABAC vielseitiger und bewertet bei Zugriffsanfragen Attribute, die mit dem Benutzer, der Aktion und der Ressource verknüpft sind.


Mit den Aktionen von ZITADEL können Post-Authentifizierungsskripte erstellt werden, um bestimmte Benutzerattribute zu analysieren und den Zugriff bei Bedarf zu blockieren.


Aktionen können auch benutzerdefinierte Ansprüche festlegen, um das ABAC-System zu stärken und erweiterte Autorisierungsmodelle zu ermöglichen, die den Zugriff basierend auf Attributen wie Ort, Zeit oder jedem definierbaren Faktor einschränken.


Mit ZITADEL können Administratoren oder berechtigte Entwickler benutzerdefinierte Metadaten zu Benutzern und Organisationen hinzufügen und so die Möglichkeiten der fein abgestuften Zugriffskontrolle erweitern.


Es unterstützt aggregierte Ansprüche durch die Erfassung zusätzlicher Daten aus externen Systemen wie CRM- oder HR-Tools. ZITADEL kann auch einzigartige Ressourcen wie Versandaufträge oder IoT-Geräte verwalten und den Zugriff anhand von Attributen wie Benutzer-Sub, Rollen, Ansprüchen, IP und mehr bestimmen.

Erweiterung der bestehenden Fähigkeiten von ZITADEL für eine differenzierte Zugangskontrolle

Trotz der umfassenden Funktionen von ZITADEL kann es Fälle geben, in denen ein individuellerer oder detaillierterer Ansatz erforderlich ist.


Derzeit besteht der effektivste Weg zur Implementierung einer feinkörnigen Autorisierung in ZITADEL darin, benutzerdefinierte Anwendungslogik für kleinere Projekte zu verwenden oder für größere Projekte ein verfügbares Drittanbieter-Tool wie warrant.dev , cerbos.dev usw. zu nutzen.


Diese Tools können in ZITADEL integriert werden, wodurch Ihre Fähigkeit zur differenzierten, feinkörnigen Autorisierung weiter verbessert wird.

Ein praktisches Beispiel

Nehmen wir an, es gibt eine hypothetische Newsroom-Anwendung in einem Medienunternehmen, die mit einer Back-End-API kommuniziert. Journalisten nutzen es zum Schreiben, während Redakteure diese Artikel bearbeiten und veröffentlichen. Diese API, in diesem Beispiel in Python Flask geschrieben, verfügt über bestimmte Endpunkte und der Zugriff auf diese Endpunkte hängt von der Rolle des Benutzers und seiner Erfahrung ab. Die Endpunkte:


  • write_article : Nur für Journalisten zum Schreiben.


  • edit_article : Nur für Redakteure zum Bearbeiten von Artikeln.


  • review_articles : Für erfahrene Journalisten sowie mittlere und erfahrene Redakteure zur Rezension von Artikeln.


  • publish_article : Für mittlere und erfahrene Journalisten und leitende Redakteure zum Veröffentlichen. Intern verwendet die API ein von ZITADEL ausgegebenes JWT, um zu überprüfen, wer Anfragen stellt. Benutzer müssen im Header ihrer Anfrage ein gültiges JWT senden. Dieses JWT wurde abgerufen, als sich der Benutzer anmeldete.


    Das JWT enthält Informationen über den Benutzer, wie seine Rolle und Erfahrung. Diese in benutzerdefinierten Ansprüchen enthaltenen Informationen sind für diesen Anwendungsfall von entscheidender Bedeutung. Das Backend entscheidet anhand dieser Informationen, ob der Benutzer auf die angeforderte Ressource zugreifen kann.

Die Anwendungslogik

Diagramm 1: Die Interaktionen einer feingranularen Autorisierung über die Anmeldung hinaus



  • Benutzer-Onboarding : Während des Benutzer-Onboarding-Prozesses erhält jeder Benutzer eine Rolle, z. B. journalist oder editor . Dies ist von entscheidender Bedeutung, da dadurch festgelegt wird, wer in unserem Setup welchen Zugriff erhält. Verwalten von Erfahrung/Dienstalter: Neben Rollen wird auch die Erfahrung eines Benutzers (in unserem Beispiel junior , intermediate und senior ) verfolgt. Wenn sich die Erfahrung eines Benutzers ändert, aktualisiert ZITADEL diese als Metadaten. Wenn beim Onboarding von ZITADEL kein Erfahrungslevel angegeben ist, geht das System einfach davon aus, dass es sich um „Junior“ handelt.


  • Benutzeranmeldung : Ein Benutzer muss sich zuerst anmelden, um auf die API zuzugreifen. Nach erfolgreicher Anmeldung sendet ZITADEL einen Token mit den Benutzerinformationen zurück.


  • Token-Validierung: Wenn eine Anfrage eines Benutzers die API erreicht, validiert die API das Token, indem sie den Token-Introspection-Endpunkt von ZITADEL aufruft. Obwohl JWTs lokal mithilfe von JWKS validiert werden können, haben wir uns für die Methode von ZITADEL zur Überprüfung von Token entschieden, um eine bessere Sicherheit und sofortige Token-Überprüfungen zu gewährleisten. Auf diese Weise können wir Token sofort widerrufen, sie von einem Ort aus verwalten und haben weniger Sicherheitsprobleme. Dadurch bleiben die Anmelde- und Zugriffskontrollen unserer API stark und auf dem neuesten Stand des Servers.


  • Fein abgestufte Zugriffskontrolle: Die Anwendung ist für die Autorisierung des Zugriffs auf Ressourcen basierend auf der Rolle und dem Erfahrungsniveau eines Benutzers verantwortlich. Es verwendet eine vordefinierte Zugriffskontrollliste, die jeden Ressourcenendpunkt den Benutzerrollen und Erfahrungsstufen zuordnet, die für den Zugriff darauf berechtigt sind. Diese Liste dient als Regelwerk für die Gewährung oder Verweigerung des Zugriffs auf Ressourcen.


  • Trennung von Belangen : Bei der Gestaltung dieser API wurde besonderes Augenmerk darauf gelegt, sicherzustellen, dass Geschäftslogik und Zugriffskontrollregeln sauber getrennt sind. Dies ist entscheidend für die Wartbarkeit und Skalierbarkeit der Anwendung. Durch die Trennung von Geschäftslogik und Zugriffsregeln erhalten wir ein übersichtlicheres, modulares Design.


    Dadurch können wir Geschäftsaktionen und Zugriffsregeln aktualisieren, ohne sich gegenseitig zu beeinflussen. Dies erhöht die Wartbarkeit des Codes und erleichtert die Verwaltung bei der Skalierung der Anwendung.


    Darüber hinaus macht dieses Design das System sicherer, da Zugriffsregeln von der Hauptgeschäftslogik abstrahiert werden, wodurch das Risiko verringert wird, dass beim Ändern der Geschäftslogik versehentlich Sicherheitslücken entstehen.

ZITADEL einrichten

1. Erstellen Sie eine Media House-Organisation, ein Newsroom-Projekt und eine Artikel-API

  1. Erstellen Sie die Organisation „Media House“, gehen Sie zu „Projekte“ und erstellen Sie ein neues Projekt mit dem Namen „Newsroom“.



  2. Klicken Sie im Newsroom-Projekt auf die Schaltfläche „Neu“ , um eine neue Anwendung zu erstellen.



  1. Fügen Sie einen Namen hinzu und wählen Sie den Typ API aus.



  1. Wählen Sie „Basic“ als Authentifizierungsmethode aus und klicken Sie auf „Fortfahren“ .



  1. Überprüfen Sie nun Ihre Konfiguration und klicken Sie auf Erstellen .



  1. Sie sehen nun die Client-ID und das Client-Geheimnis der API. Kopieren Sie sie und speichern Sie sie. Klicken Sie auf Schließen .



  1. Wenn Sie links auf „URLs“ klicken, werden die relevanten OIDC-URLs angezeigt. Notieren Sie sich die Aussteller -URL, token_endpoint und introspection_endpoint .



2. Erstellen Sie Rollen im Newsroom-Projekt

  1. Notieren Sie sich außerdem die Ressourcen-ID Ihres Projekts (gehen Sie zum Projekt und kopieren Sie die Ressourcen-ID).



  1. Aktivieren Sie im Projekt-Dashboard das Kontrollkästchen „Rollen bei der Authentifizierung beanspruchen“ und klicken Sie auf „Speichern“ .



  1. Gehen Sie zu Rollen (im linken Menü) und klicken Sie auf Neu , um neue Rollen hinzuzufügen.



  1. Geben Sie die Rollen „Redakteur “ und „Journalist“ wie unten gezeigt ein und klicken Sie auf „Speichern“ .



  1. Sie sehen nun die erstellten Rollen.



3. Erstellen Sie Benutzer im Newsroom-Projekt

  1. Gehen Sie wie unten gezeigt zur Registerkarte „Benutzer“ in Ihrer Organisation und dann zur Registerkarte „Dienstbenutzer“ . In dieser Demo werden wir Dienstbenutzer erstellen. Um einen Dienstbenutzer hinzuzufügen, klicken Sie auf die Schaltfläche „Neu“ .


    Dienstbenutzer erstellen


  2. Fügen Sie als Nächstes die Details des Dienstbenutzers hinzu, wählen Sie JWT als Zugriffstokentyp aus und klicken Sie auf Erstellen .


    Dienstbenutzer erstellen


  3. Klicken Sie oben rechts auf die Schaltfläche „Aktionen“ . Wählen Sie im Dropdown-Menü die Option „Client-Geheimnis generieren“ aus.




  4. Kopieren Sie Ihre Kunden-ID und Ihr Kundengeheimnis. Klicken Sie auf Schließen .



  5. Jetzt haben Sie einen Dienstbenutzer mit seinen Client-Anmeldeinformationen.

4. Fügen Sie Berechtigungen für die Benutzer hinzu

  1. Gehen Sie zu Berechtigungen . Klicken Sie auf Neu .


  2. Wählen Sie den Benutzer und das Projekt aus, für den die Berechtigung erstellt werden soll. Klicken Sie auf Weiter .



  3. Hier können Sie eine Rolle auswählen. Wählen Sie die Rolle „Journalist“ für den aktuellen Benutzer aus. Klicken Sie auf Speichern .


    Autorisierung hinzufügen


  4. Sie können sehen, dass die Dienstbenutzerin Lois Lane jetzt die Rolle der Journalistin im Newsroom- Projekt übernimmt.



5. Fügen Sie den Benutzern Metadaten hinzu

Fügen wir nun dem Benutzerprofil Metadaten hinzu, um dessen Dienstalter anzugeben. Verwenden Sie „experience_level“ als Schlüssel und wählen Sie als Wert „Junior“, „Intermediate“ oder „Senior“.


Obwohl wir normalerweise davon ausgehen können, dass diese Metadaten durch einen API-Aufruf der HR-Anwendung festgelegt werden, werden wir der Einfachheit und dem besseren Verständnis halber die Metadaten direkt in der Konsole festlegen.


  1. Gehen Sie zu Metadaten . Klicken Sie auf Bearbeiten .



  2. Geben Sie experience_level als Schlüssel und senior als Wert an. Klicken Sie auf das Speichern-Symbol und dann auf die Schaltfläche „Schließen“ .



  3. Der Benutzer verfügt nun über die erforderlichen Metadaten, die seinem Konto zugeordnet sind.



  4. Sie können auch einige weitere Dienstbenutzer mit unterschiedlichen Rollen und Erfahrungsstufen (unter Verwendung von Metadaten) hinzufügen, um die Demo mithilfe der vorherigen Schritte zu testen.


6. Erstellen Sie eine Aktion zum Erfassen von Rollen und Metadaten im benutzerdefinierten Anspruch

1. Klicken Sie auf Aktionen . Klicken Sie auf Neu , um eine neue Aktion zu erstellen.



2. Geben Sie im Abschnitt „Aktion erstellen“ der Aktion denselben Namen wie dem Funktionsnamen, z. B. „assignRoleAndExperienceClaims“. Kopieren/fügen Sie im Skriptfeld den folgenden Code ein und klicken Sie dann auf Hinzufügen .



 function assignRoleAndExperienceClaims(ctx, api) { // Check if grants and metadata exist if (!ctx.v1.user.grants || !ctx.v1.claims['urn:zitadel:iam:user:metadata']) { return; } // Decode experience level from Base64 - metadata is Base64 encoded let experience_encoded = ctx.v1.claims['urn:zitadel:iam:user:metadata'].experience_level; let experience = ''; try { experience = decodeURIComponent(escape(String.fromCharCode.apply(null, experience_encoded.split('').map(function(c) { return '0x' + ('0' + c.charCodeAt(0).toString(16)).slice(-2); })))); } catch (e) { return; // If decoding fails, stop executing the function } // Check if the experience level exists if (!experience) { return; } // Iterate through the user's grants ctx.v1.user.grants.grants.forEach(grant => { // Iterate through the roles of each grant grant.roles.forEach(role => { // Check if the user is a journalist if (role === 'journalist') { // Set custom claims with the user's role and experience level api.v1.claims.setClaim('journalist:experience_level', experience); } // Check if the user is an editor else if (role === 'editor') { // Set custom claims with the user's role and experience level api.v1.claims.setClaim('editor:experience_level', experience); } }); }); }


  1. Die „assignRoleAndExperienceClaims“ werden nun als Aktion aufgeführt.



  1. Als nächstes müssen wir einen Flusstyp auswählen. Gehen Sie zum Abschnitt „Flows“ unten. Wählen Sie im Dropdown-Menü Komplement-Token aus.



  1. Jetzt müssen Sie einen Auslöser auswählen. Klicken Sie auf Trigger hinzufügen . Wählen Sie als Auslösertyp die Erstellung von Vorzugriffstokens und als zugehörige Aktion „assignRoleAndExperienceClaims“ aus.



  1. Und jetzt wird der Auslöser aufgelistet.



Wenn nun ein Benutzer ein Zugriffstoken anfordert, wird die Aktion ausgeführt, wobei die Benutzerrollen und Metadaten in das erforderliche Format umgewandelt und als benutzerdefinierter Anspruch zum Token hinzugefügt werden. Dieser benutzerdefinierte Anspruch kann dann von Drittanbieteranwendungen verwendet werden, um den differenzierten Benutzerzugriff zu verwalten.

Richten Sie das API-Projekt ein

Klonen Sie das Projekt von GitHub:

Führen Sie den folgenden Befehl aus, um das Projekt aus diesem GitHub-Repository zu klonen:

  • git clone https://github.com/zitadel/example-fine-grained-authorization.git


Navigieren Sie zum Projektverzeichnis:

Navigieren Sie nach dem Klonen mit zum Projektverzeichnis

  • cd example-fine-grained-authorization .


Richten Sie eine Python-Umgebung ein:

Stellen Sie sicher, dass Python 3 und pip installiert sind. Sie können dies überprüfen, indem Sie ausführen

  • python3 --version und
  • pip3 --version

in Ihrem Terminal. Wenn Sie Python oder Pip nicht installiert haben, müssen Sie diese installieren.


Erstellen Sie als Nächstes eine neue virtuelle Umgebung für dieses Projekt, indem Sie es ausführen

  • python3 -m venv env .


Aktivieren Sie die Umgebung, indem Sie Folgendes ausführen:

  • Unter Windows: .\env\Scripts\activate
  • Unter Unix oder MacOS: source env/bin/activate


Nachdem Sie diesen Befehl ausgeführt haben, sollte Ihr Terminal anzeigen, dass Sie jetzt in der virtuellen Umgebung von env arbeiten.


Abhängigkeiten installieren:

Führen Sie den Befehl aus, während sich das Terminal im Projektverzeichnis befindet (dasjenige, das „requirements.txt“ enthält).

  • pip3 install -r requirements.txt

um die notwendigen Abhängigkeiten zu installieren.


Umgebungsvariablen konfigurieren:

Das Projekt erfordert bestimmte Umgebungsvariablen. Füllen Sie die .env Datei mit den Werten aus, die wir von ZITADEL abgerufen haben.

 PROJECT_ID="<YOUR PROJECT ID>" ZITADEL_DOMAIN="<YOUR INSTANCE DOMAIN eg https://instance-as23uy.zitadel.cloud>" ZITADEL_TOKEN_URL="<YOUR TOKEN URL eg https://instance-as23uy.zitadel.cloud/oauth/v2/token" CLIENT_ID="<YOUR SERVICE USER'S CLIENT ID FROM THE GENERATED CLIENT CREDENTIALS eg sj_Alice>" CLIENT_SECRET="<YOUR SERVICE USER'S SECRET FROM THE GENERATED CLIENT CREDENTIALS"> ZITADEL_INTROSPECTION_URL="<YOUR INTROSPECTION URL eg https://instance-as23uy.zitadel.cloud/oauth/v2/introspect>" API_CLIENT_ID="<THE CLIENT ID OF YOUR API APPLICATION FOR BASIC AUTH eg 324545668690006737@api>" API_CLIENT_SECRET="<THE CLIENT SECRET OF YOUR API APPLICATION FOR BASIC AUTH>"


Führen Sie die Anwendung aus:

Die Flask-API (in app.py ) verwendet JWT-Token und benutzerdefinierte Ansprüche für eine differenzierte Zugriffskontrolle. Bei jeder Anfrage wird der benutzerdefinierte Anspruch „experience_level“ für die Rollen „ journalist “ und editor “ überprüft und anhand dieser Informationen entschieden, ob der authentifizierte Benutzer auf den angeforderten Endpunkt zugreifen kann.


app.py

 from flask import Flask, jsonify from auth import token_required from access_control import authorize_access app = Flask(__name__) # Define the /write_article route. @app.route('/write_article', methods=['POST']) @token_required def write_article(): authorization = authorize_access('write_article') if authorization is not True: return authorization # Resource-specific code goes here... return jsonify({"message": "Article written successfully!"}), 200 # Define the /edit_article route. @app.route('/edit_article', methods=['PUT']) @token_required def edit_article(): authorization = authorize_access('edit_article') if authorization is not True: return authorization # Resource-specific code goes here... return jsonify({"message": "Article edited successfully!"}), 200 # Define the /review_article route. @app.route('/review_articles', methods=['GET']) @token_required def review_article(): authorization = authorize_access('review_article') if authorization is not True: return authorization # Resource-specific code goes here... return jsonify({"message": "Article review accessed successfully!"}), 200 # Define the /publish_article route. @app.route('/publish_article', methods=['POST']) @token_required def publish_article(): authorization = authorize_access('publish_article') if authorization is not True: return authorization # Resource-specific code goes here... return jsonify({"message": "Article published successfully!"}), 200 # Add more endpoints as needed... if __name__ == '__main__': app.run(debug=True)


auth.py

 import os import jwt import requests from functools import wraps from flask import request, jsonify, g ZITADEL_INTROSPECTION_URL = os.getenv('ZITADEL_INTROSPECTION_URL') API_CLIENT_ID = os.getenv('API_CLIENT_ID') API_CLIENT_SECRET = os.getenv('API_CLIENT_SECRET') # This function checks the token introspection and populates the flask.g variable with the user's token def token_required(f): @wraps(f) def decorated(*args, **kwargs): token = request.headers.get('Authorization') if not token: abort(401) # Return status code 401 for Unauthorized if there's no token else: token = token.split(' ')[1] # The token is in the format "Bearer <token>", we want to extract the actual token # Call the introspection endpoint introspection_response = requests.post( ZITADEL_INTROSPECTION_URL, auth=(API_CLIENT_ID, API_CLIENT_SECRET), data={'token': token} ) if not introspection_response.json().get('active', False): return jsonify({"message": "Invalid token"}), 403 # Decode the token and print it for inspection decoded_token = jwt.decode(token, options={"verify_signature": False}) print(f"\n\n***** Decoded Token: {decoded_token} \n\n******") # Add the decoded token to Flask's global context g.token = decoded_token return f(*args, **kwargs) return decorated


access_control.py (Beispielcode zur Simulation einer Regel-Engine)

 import base64 import jwt from flask import g, jsonify # The access_requirements dictionary represents your access control rules. access_requirements = { 'write_article': [{'role': 'journalist', 'experience_level': 'junior'}, {'role': 'journalist', 'experience_level': 'intermediate'}, {'role': 'journalist', 'experience_level': 'senior'}], 'edit_article': [{'role': 'editor', 'experience_level': 'junior'}, {'role': 'editor', 'experience_level': 'intermediate'}, {'role': 'editor', 'experience_level': 'senior'}], 'review_articles': [{'role': 'journalist', 'experience_level': 'senior'}, {'role': 'editor', 'experience_level': 'intermediate'}, {'role': 'editor', 'experience_level': 'senior'}], 'publish_article': [{'role': 'journalist', 'experience_level': 'intermediate'}, {'role': 'journalist', 'experience_level': 'senior'}, {'role': 'editor', 'experience_level': 'senior'}] # Add more endpoints as needed... } # This function checks if the user is authorized to access the given endpoint. def authorize_access(endpoint): # We assume that the token has already been decoded in auth.py decoded_token = g.token # Initialize role and experience_level variables role = None experience_level = None for claim, value in decoded_token.items(): if ':experience_level' in claim: role, _ = claim.split(':') experience_level = base64.b64decode(value).decode('utf-8') break # If there's no role in the token, return an error if not role: return jsonify({"message": "Missing role"}), 403 # If there's a role in the token but no experience level, default the experience level to 'junior' if role and not experience_level: experience_level = 'junior' # If there's no role or experience level in the token, return an error if not role or not experience_level: return jsonify({"message": "Missing role or experience level"}), 403 # Get the requirements for the requested endpoint endpoint_requirements = access_requirements.get(endpoint) # If the endpoint is not in the access control list, return an error if not endpoint_requirements: return jsonify({"message": "Endpoint not found in access control list"}), 403 # Check if the user's role and experience level meet the requirements for the requested endpoint for requirement in endpoint_requirements: required_role = requirement['role'] required_experience_level = requirement['experience_level'] # Experience level hierarchy experience_levels = ['junior', 'intermediate', 'senior'] if role == required_role and experience_levels.index(experience_level) >= experience_levels.index(required_experience_level): return True #return jsonify({"message": "Access denied"}), 403 return jsonify({"message": f"Access denied! You are a {experience_level} {role} and therefore cannot access {endpoint}"}), 403


Führen Sie die Flask-Anwendung aus, indem Sie Folgendes ausführen:

python3 app.py


Wenn alles richtig eingerichtet ist, sollte Ihre Flask-Anwendung jetzt ausgeführt werden.


Dieses Projekt wurde mit Python 3 entwickelt und getestet. Stellen Sie daher sicher, dass Sie einen Python 3-Interpreter verwenden.

Führen Sie die API aus und testen Sie sie

Führen Sie die API aus

  1. Stellen Sie sicher, dass Sie das Repository geklont und die erforderlichen Abhängigkeiten wie zuvor beschrieben installiert haben.


  2. Führen Sie das Skript client_credentials_token_generator.py aus, um ein Zugriffstoken zu generieren.


    client_credentials_token_generator.py

     import os import requests import base64 from dotenv import load_dotenv load_dotenv() ZITADEL_DOMAIN = os.getenv("ZITADEL_DOMAIN") CLIENT_ID = os.getenv("CLIENT_ID") CLIENT_SECRET = os.getenv("CLIENT_SECRET") ZITADEL_TOKEN_URL = os.getenv("ZITADEL_TOKEN_URL") PROJECT_ID = os.getenv("PROJECT_ID") # Encode the client ID and client secret in Base64 client_credentials = f"{CLIENT_ID}:{CLIENT_SECRET}".encode("utf-8") base64_client_credentials = base64.b64encode(client_credentials).decode("utf-8") # Request an OAuth token from ZITADEL headers = { "Content-Type": "application/x-www-form-urlencoded", "Authorization": f"Basic {base64_client_credentials}" } data = { "grant_type": "client_credentials", "scope": f"openid profile email urn:zitadel:iam:org:project:id:{PROJECT_ID}:aud urn:zitadel:iam:org:projects:roles urn:zitadel:iam:user:metadata" } response = requests.post(ZITADEL_TOKEN_URL, headers=headers, data=data) if response.status_code == 200: access_token = response.json()["access_token"] print(f"Response: {response.json()}") print(f"Access token: {access_token}") else: print(f"Error: {response.status_code} - {response.text}")


    Öffnen Sie Ihr Terminal, navigieren Sie zum Projektverzeichnis und führen Sie dann das Skript mit Python3 aus:

    python3 client_credentials_token_generator.py


  3. Bei Erfolg wird ein Zugriffstoken auf Ihr Terminal gedruckt. Dies ist das Token, mit dem Sie Ihre Anfragen an die API authentifizieren.


  4. Wenn Sie die Flask-API nicht zuvor gestartet haben, führen Sie die API aus, indem Sie ein anderes Terminal im Projektverzeichnis öffnen und Folgendes ausführen:

    python3 app.py


  5. Der API-Server sollte jetzt laufen und bereit sein, Anfragen anzunehmen.


Jetzt können Sie cURL oder einen anderen HTTP-Client (wie Postman) verwenden, um Anfragen an die API zu stellen. Denken Sie daran, your_access_token in den Curl-Befehlen durch das Zugriffstoken zu ersetzen, das Sie in Schritt 2 erhalten haben.

Testen Sie die API

Szenario 1: Junior-Redakteur versucht, einen Artikel zu bearbeiten (Erfolg)


Benutzer mit editor Rolle und junior Erfahrungsstufe versuchen, den Endpunkt edit_article aufzurufen.

  • curl -H "Authorization: Bearer <your_access_token>" -X POST http://localhost:5000/edit_article


  • Erwartete Ausgabe: {"message": "Article edited successfully"}


Szenario 2: Junior-Redakteur versucht, einen Artikel zu veröffentlichen (Misserfolg)

Benutzer mit editor Rolle und junior Erfahrungsstufe versuchen, den Endpunkt publish_article aufzurufen.

  • curl -H "Authorization: Bearer <your_access_token>" -X POST http://localhost:5000/publish_article


  • Erwartete Ausgabe: {"message": "Access denied! You are a junior editor and therefore cannot access publish_article"}


Szenario 3: Leitender Journalist versucht, einen Artikel zu schreiben (Erfolg)

Ein Benutzer mit der Rolle journalist und der Stufe senior experience_level“ versucht, den Endpunkt write_article aufzurufen.

  • curl -H "Authorization: Bearer <your_access_token>" -X POST http://localhost:5000/write_article

  • Erwartete Ausgabe: {"message": "Article written successfully"}


Szenario 4: Nachwuchsjournalist versucht, Artikel zu rezensieren (Misserfolg)

Benutzer mit der Rolle journalist und der Erfahrungsebene „Junior“ versuchen, den Endpunkt review_articles aufzurufen.

  • curl -H "Authorization: Bearer <your_access_token>" -X POST http://localhost:5000/review_articles


  • Erwartete Ausgabe: {"message": "Access denied! You are a junior journalist and therefore cannot access review_articles"}


Szenario 5: Leitender Redakteur versucht, Artikel zu überprüfen (Erfolg)

Benutzer mit editor Rolle und senior Erfahrungsstufe versuchen, auf den Endpunkt review_articles zuzugreifen.

  • curl -H "Authorization: Bearer <your_access_token>" -X POST http://localhost:5000/review_articles


  • Erwartete Ausgabe: {"message": "Article reviewed successfully"}


Szenario 6: Fortgeschrittener Journalist versucht, einen Artikel zu veröffentlichen (Erfolg)

Benutzer mit journalist und intermediate experience_level versuchen, auf den publish_article -Endpunkt zuzugreifen.

  • curl -H "Authorization: Bearer <your_access_token>" -X POST http://localhost:5000/publish_article


  • Erwartete Ausgabe: {"message": "Article published successfully"}

Abschluss

In diesem Artikel haben wir untersucht, wie wichtig es ist, vom traditionellen RBAC zu einem detaillierteren, feinkörnigeren Autorisierungsansatz mit ZITADEL überzugehen.


Wir haben uns mit seinen Funktionen wie dynamischen Aktionen für ABAC und der Möglichkeit zur Integration mit Tools von Drittanbietern befasst und gesehen, wie diese Funktionen in einem realen Szenario praktisch angewendet werden können.


Da die Anforderungen an die Cybersicherheit wachsen, bieten Plattformen wie ZITADEL die notwendigen Lösungen für komplexe Autorisierungsherausforderungen.