10.3. Authentifizierung, Autorisierung und APIs#

Neben der Session-basierten Authentifizierung, die ich im Abschnitt “Sessions und Cookies” erläutert habe, verwenden viele Webseiten auch andere Authentifizierungs- und Autorisierungsmethoden, um den Zugang zu Ressourcen zu kontrollieren, insbesondere, wenn die Ressourcen über eine API bereitgestellt werden, aber nicht allen zugänglich sein sollen. Authentifizierung beschreibt dabei das Verfahren, mit dem überprüft wird, ob ein Client wirklich der ist, der er vorgibt zu sein, und Autorisierung beschreibt die anschließende Erteilung von Zugangsrechten zu Ressourcen an den Client.

10.3.1. Session- vs. Token-basierte Authentifizierung#

Wir betrachten zunächst allgemein die sogenannte “Token-basierte Authentifizierung”. Damit sich ein Client gegenüber einem Server authentifizieren kann, muss er irgendwie eindeutig identifizierbar sein. Eine Möglichkeit, wie ein Server einen Client über mehrere Anfragen hinweg wiedererkennen kann, sind Sessions. Jedoch haben wir gesehen, dass die Session IDs aller Clients bei einem Session-basierten Authentifizierungsvorgang auf dem Server gespeichert werden müssen. Wenn verschiedene Clients unterschiedliche Zugriffsrechte haben, muss auch diese Information auf dem Server gespeichert sein. Dies hat den Nachteil, dass bei vielen Clients viel Speicherplatz notwendig wird. Eine in dieser Hinsicht effizientere Methode, Clients zu identifizieren und deren Zugriffsrechte zu verwalten, ist die Verwendung von Tokens. Tokens sind im Grunde Zeichenfolgen, welche die Identität oder Berechtigungen von Clients repräsentieren.

Die folgenden beiden Abbildungen illustrieren vereinfacht den Unterschied zwischen einer Session- und einer Token-basierten Authentifizierung:

Session-Based Authentication

Fig. 10.14 Schaubild Session-basierte Authentifizierung. Quelle: Natalia Moskaleva 2023.#

Token-Based Authentication

Fig. 10.15 Schaubild Token-basierte Authentifizierung. Quelle: Natalia Moskaleva 2023.#

Aus den beiden Schaubildern lässt sich der grundsätzliche Unterschied zwischen Session- und Token-basierten Authentifizierungsmethoden ablesen. Die Session-basiete Authentifizierung zielt darauf ab, das zustandslose HTTP-Protokoll (siehe dazu Kapitel 6.4) mithilfe einer Session um einen Zustand zu ergänzen während bei der Token-basierten Authentitfizierung die Kommunikation weiterhin zustandslos abläuft: Das Zugangstoken muss bei jeder Anfrage erneut angegeben werden.

In der Praxis ist der Zugriff auf Ressourcen mithilfe von Zugriffstokens jedoch etwas komplizierter und beinhaltet neben der eigentlichen Authentifizierung auch eine Autorisierung des Clients, der die Anfrage stellt, also eine Erteilung von Zugriffsrechten auf bestimmte Ressourcen. Wie genau die Verwaltung der Zugriffsrechte erfolgt, hängt von dem spezifischen Framework oder Standard ab, der zur Implementierung des Authentifizierungs- bzw. Autorisierungsworkflows verwendet wird. Innerhalb eines Standards gibt es zudem für verschiedene Zwecke verschiedene Workflows: zum Beispiel kann es einen Workflow geben, der für die Mensch-Maschine Kommunikation vorgesehen ist (ein:e User:in möchte sich mit den Zugangsdaten von sozialem Netzwerk X in einer anderen Anwendung Y anmelden), und einen anderen Workflow, der für eine Maschine-zu-Maschine Kommunikation entworfen wurde (das ist unser Fall: Python requests wird verwendet, um Ressourcen von einem Server anzufragen).

10.3.2. OAuth 2.0: Zugriff mit Access Tokens#

Ein zur Verwaltung von Zugriffsrechten auf APIs viel genutzter Standard ist OAuth 2.0. OAuth 2.0 steht für “Open Authorization” und ist, einfach formuliert, eine Sammlung von Regeln und Verfahren, die festlegen, wie ein Client gegenüber einem Server eine erfolgte Authentifizierung nachweisen kann, um über eine Schnittstelle Zugriff auf bestimmte Ressourcen zu erhalten (Autorisierung). Die unterschiedlichen Workflows, wie der Client für verschiedene Zwecke Zugriffsrechte erhalten kann, werden im Kontext von Oauth 2.0 “Grants” genannt. So gibt es beispielsweise einen “Authorization Code Grant”, der für die Mensch-Maschine-Kommunikation vorgesehen ist (z.B. beim Login eine:r User:in mit den Zugangsdaten eines sozialen Netzwerks X in einer anderen Anwendung Y), und es gibt den für uns wichtigen “Client Credentials Grant Type”, welcher für die nicht-interaktive Maschine-zu-Maschine-Kommunikation verwendet wird (mehr dazu könnt ihr hier nachlesen).

Bei einem Zugriffsvorgang mit OAuth 2.0 können unabhängig vom spezifischen Workflow (Grant) grundsätzlich vier Parteien beteiligt sein: Ein Resource Owner, ein Client, ein Authorization Server und ein Resource Server. Der Authorization Server hat zwei Endpunkte: Einen Autorisierungsendpunkt und einen Token-Endpunkt. Bei einem Authorization Code Workflow wäre der Resource Owner beispielsweise ein:e Nutzer:in des sozialen Netzwerks X. Der Client wäre die Anwendung Y, bei der sich die Nutzer:in mit dem Account aus dem sozialen Netzwerk X anmelden möchte. Damit die Anmeldung erfolgen kann, muss der Client (also die Anwendung Y) an den Autorisierungsendpunkt des Authorization Servers des sozialen Netzwerks eine Anfrage stellen, ob er auf Daten aus dem Account des Resource Owners zugreifen darf. Dies muss der Resource Owner interaktiv durch Eingabe der eigenen Zugangsdaten beim sozialen Netzwerk bestätigen, und erst dann erhält der Client vom Authorization Server des sozialen Netzwerks ein Access Token. Dieses Token kann der Client dann verwenden, um eine Anfrage an den Resource Server des sozialen Netzwerks zu stellen, auf dem die Daten des Resource Owners liegen. Da die Zugriffsrechte in dem Access Token klar definiert sind, erhält der Client vom Resource Server genau die Daten, für die der Resource Owner zuvor die Zugriffserlaubnis erteilt hat. Dieses Video erläutert leicht verständlich den Authorization Code Workflow.

Beispiel OAuth 2.0 Authorization Code Workflow

Fig. 10.16 OAuth 2.0 Authorization Code Workflow: Beispiel Login. Adaptiert von Okta, Inc 2024 .#

Bei einem Client Credentials Workflow wäre dagegen der Resource Owner sozusagen das soziale Netzwerk selbst, sodass die Erteilung der Zugriffsrechte keine interaktive Authentifizierung und Autorisierung durch eine:n Nutzer:in voraussetzt. Allerdings wird der Begriff “Resource Owner” im Kontext von einem Client Credentials Workflow nicht verwendet, und man kann sich den Workflow stattdessen als Kommunikation zwischen nur drei Parteien vorstellen: Der Client authentifiziert sich direkt beim Authorization Server, indem er eine Anfrage an den Token-Endpunkt des Authorization Servers des sozialen Netzwerks stellt. Dabei gibt der Client seine “Credentials” an, also Authentifizierungsdaten, die er zuvor von den Betreiber:innen des sozialen Netzwerks selbst erhalten hat. Ist die Authentifizierung erfolgreich, erhält der Client genau wie beim Authorization Code Workflow vom Autorisierungserver ein Access Token und kann damit anschließend auf die Ressourcen auf dem Resource Server zugreifen.

Für uns ist im Rahmen dieses Seminars vor allem der Client Credentials Grant Type relevant und wir schauen uns diesen Workflow im Folgenden am Beispiel der TikTok Research API etwas genauer an.

Die TikTok Research API kann laut Dokumentationsseiten von “independent and academic researchers who work for a non-profit institution” zur automatisierten Abfrage von Daten zu Videos, Kommentaren und Nutzer:innenprofilen genutzt werden (siehe TikTok 2024: About Research API). Die Nutzung der API setzt eine erfolgreiche Bewerbung voraus. Erfolgreiche Bewerber:innen erhalten anschließend einen Client Key und ein Client Secret (das sind einfach Zeichenfolgen), mit denen sie Zugang zu den Video-, User-, und Comments-Endpunkten der API erhalten können (TikTok 2024: Getting Started). Bevor eine Anfrage an diese Endpunkte gestellt werden kann, müssen jedoch zunächst Client Key und Client Secret gegen ein Access Token ausgetauscht werden. Dazu muss eine Anfrage an den Token-Endpunkt der API gestellt werden (TikTok 2024: Client Access Token Management). Dem Abschnitt “Endpoint” auf der Seite “Client Access Token Management” können wir entnehmen, dass dazu eine POST-Anfrage an den Token-Endpunkt des Autorisierungsservers gestellt werden muss, und die Abschnitte “Headers” und “Request Body Parameters” geben uns Auskunft darüber, welche Angaben wir beim Aufruf der requests post()-Funktion übergeben müssen. Der Abschnitt “Response struct” gibt an, welche Daten bei einer erfolgreichen Anfrage zurückgegeben werden: Die Antwort enthält demnach ein Access Token, das im Rahmen der TikTok API “Bearer Tokens” genannt wird. Ein “Bearer Token” ist einfach eine Art von Access Token.

Besonders interessant ist für uns die Information, dass bei der Anfrage als Grant Type “client_credentials” angegeben werden soll, denn das verrät uns, dass zur Autorisierung ein Client Credentials Workflow verwendet wird. Ich habe bereits erwähnt, dass anders als beim Authorization Code Workflow die Authentifizierung beim Client Credentials Workflow direkt auf dem Autorisierungsserver erfolgt. Ein Blick in die OAuth 2.0-Dokumentationsseiten verrät uns, dass bei der TikTok Research API dazu offenbar eine Authentifizierungsmethode angewandt wird, die sich Client Secret nennt (Okta, Inc 2024: Client Credentials Flow und Application Credentials).

Der gesamte Workflow für die Nutzung der TikTok Research API sieht dann ungefähr so aus:

TikTok OAuth 2.0 Client Credentials Workflow

Fig. 10.17 OAuth 2.0 Client Credentials Workflow: Beispiel TikTok Research API. Adaptiert von Okta, Inc 2024.#

Der folgende Code von Kursteilnehmerin Annabella Backes zeigt, wie dieser Workflow in Python reproduziert werden kann. Zunächst müssen die Client Credentials gegen ein Access Token getauscht werden, indem eine Anfrage an den Token-Endpunkt des Authorization Servers gestellt wird:

# import requests

# CLIENT_KEY = 'your_key'
# CLIENT_SECRET = 'your_secret'

# # Token endpoint
# token_endpoint = 'https://open.tiktokapis.com/v2/oauth/token/'

# # Parameters for the request
# data = {
#     'client_key': CLIENT_KEY,
#     'client_secret': CLIENT_SECRET,
#     'grant_type': 'client_credentials'
# }

# # Headers for the request
# headers = {
#     'Content-Type': 'application/x-www-form-urlencoded',
#     'Cache-Control': 'no-cache'
# }

# # Send a POST request for the token
# response = requests.post(token_endpoint, data=data, headers=headers)

# # Extract the token from the response
# bearer_token = response.json().get('access_token', '')

Anschließend kann eine Anfrage an die Endpunkte der Research API gestellt werden, um Daten vom Resource Server abzufragen. Eine Anfrage an den User-Endpunkt sähe dann beispielsweise so aus (Code wieder von Annabella Backes):

# user_query_endpoint = 'https://open.tiktokapis.com/v2/research/user/info/?fields=display_name,bio_description,avatar_url,is_verified,follower_count,following_count,likes_count,video_count'

# user_data = {
#     'username': 'some_username'
# }

# headers = {
#     'authorization': f'bearer {bearer_token}',
#     'Content-Type': 'application/json'
# }

# response_user = requests.post(user_query_endpoint, json=user_data, headers=headers)
# result_user = response_user.json()

Zuletzt noch ein Wort zum Begriff “Autorisierung”. Die Entwickler:innen des Standards betonen, dass OAuth 2.0 ein Autorisierungsprotokoll ist und explizit kein Authentifizierungsprotokoll. Das bedeutet, dass OAuth 2.0 hauptsächlich dazu entworfen wurde, Zugang zu Ressourcen zu gewähren, und nicht zur Überprüfung der Identität des Clients, der Zugang anfragt (Okta, Inc. 2024). Zwar ist die Authentifizierung ein wesentlicher Bestandteil des Autorisierungsvorgangs: Zuerst wird mithilfe eines Authentifizierungsvorgangs die Identität des anfragenden Clients bestätigt, und erst danach wird eine Autorisierung erteilt und der Zugriff auf die angefragte Ressource gewährt. OAuth 2.0 beschreibt dabei jedoch nur, wie Clients die erfolgte Authentifizierung gegenüber einem Autorisierungsserver nachweisen können, um daraufhin Zugriffsberechtigungen auf Ressourcen zu erhalten, und nicht, wie die Authentifizierung selbst erfolgen soll. Der Client Credentials Workflow stellt also in dieser Hinsicht einen Spezialfall dar, weil kein Resource Owner die Autorisierung erteilt und die Zugriffsrechte des Clients bereits in den Credentials, die ihm von den Betreiber:innen der API zugeteilt werden, geregelt sind. Wenn im Client Credentials Workflow die Credentials gegen ein Access Token ausgetauscht werden, erfolgt also eine einfache Authentifizierung des Clients und es muss keine manuelle Autorisierung durch den Resource Owner erfolgen wie bei dem Authorization Code Workflow.

10.3.3. Authentifizierung mit API-Schlüssel (Key)#

Neben APIs, die ein Token-System zur Authentifizierung verwenden, gibt es auch APIs, die den Zugang zu Ressourcen über einen einfachen Zugangsschlüssel (Key) kontrollieren. Ein Beispiel ist die API des Guardian. Um die Schnittstelle zu verwenden, muss erst über ein Online-Formular ein Schlüssel beantragt werden. Mit dem Schlüssel kann dann ganz einfach eine Anfrage gestellt werden. Der Schlüssel kann der requests get()-Funktion bei der Anfrage zusammen mit weiteren Parametern als Dictionary übergeben werden. Ein Beispiel von GitHub-User:in Dan Nguyen:

# import requests

# MY_API_KEY = open("creds_guardian.txt").read().strip()
# API_ENDPOINT = 'http://content.guardianapis.com/search'
# my_params = {
#     'from-date': "",
#     'to-date': "",
#     'order-by': "newest",
#     'show-fields': 'all',
#     'page-size': 200,
#     'api-key': MY_API_KEY
# }

# resp = requests.get(API_ENDPOINT, my_params)

Was passiert in diesem Code? Zunächst wird der API Key aus einer Plaintext-Datei eingelesen und es werden überschüssige Leerzeichen entfernt. Danach wird die URL des content-Endpunkts der API einer Variable zugewiesen. Die beiden Variablen MY_API_KEY und API_ENDPOINT sind in diesem Beispiel groß geschrieben, weil es sich dabei um Konstanten handelt (siehe dazu meine Anmerkung im Kapitel 8.3). Die zusätzlichen Parameter im Dictionary my_params sind der Dokumentationsseite zum contents-Endpunkt entnommen und können je nach Zielsetzung variieren.

10.3.4. Weitere Authentifizierungsmethoden#

Neben dem Token-basierten Zugriff mit OAuth 2.0 und API-Keys gibt es noch weitere Methoden, die für den Zugriff auf REST APIs verwendet wird. Eine davon ist die sogenante Basic Authentication. Die Authentifizierung nach dem Basic Authentication-Verfahren ist von allen hier vorgestellten Verfahren das wohl unkomplizierteste, denn für dieses Authentifizierungsverfahren kann einfach der Parameter auth der requests get()-Funktion verwendet werden:

# requests.get('https://example.com', auth=('user', 'password'))

Siehe dazu auch die requests-Dokumentationsseiten.

10.3.5. Quellen#

  1. Jiri Caga. Most Used Authentication Methods for API. 2023. URL: https://medium.com/@jiri.caga/most-used-authentication-methods-for-api-96ce8666a015.

  2. Graham Cox. API Authentication - Tokens vs Sessions. 2023. URL: https://www.baeldung.com/cs/tokens-vs-sessions.

  3. Miguel Grinberg. API Authentication with Tokens. 2021. URL: https://blog.miguelgrinberg.com/post/api-authentication-with-tokens.

  4. Dick Hardt. OAuth 2.0 Specification. RFC 6749, section 4.4: Client Credentials Flow. 2024. URL: https://datatracker.ietf.org/doc/html/rfc6749#section-4.4.

  5. Sherry Hsu. Session vs Token Based Authentication. 2018. URL: https://sherryhsu.medium.com/session-vs-token-based-authentication-11a6c5ac45e4.

  6. Brian Iyoha. What Really Is the Difference between Session and Token Based Authentication. 2019. URL: https://dev.to/thecodearcher/what-really-is-the-difference-between-session-and-token-based-authentication-2o39.

  7. Damien Martin. Getting Data with OAuth. 2018. URL: https://kiwidamien.github.io/getting-data-with-oauth.html.

  8. Natalia Moskaleva. User Authentication: Comparing Session-based and Token-based Implementations. 2023. URL: https://www.criipto.com/blog/session-token-based-authentication.

  9. Matt Mullen. Using the Python Requests Module to Work with REST APIs. 2021. URL: https://blog.networktocode.com/post/using-python-requests-with-rest-apis/.

  10. Saleha Muzammil. Session-based Authentication vs Token-based Authentication. 2024. URL: https://www.educative.io/answers/session-based-authentication-vs-token-based-authentication.

  11. Rishabh Poddar. OAuth 2.0 vs Session Management. 2020. URL: https://supertokens.com/blog/oauth-2-vs-session-management.

  12. Kenneth Reitz. Requests Documentation: Authentication. 2016. URL: https://requests.readthedocs.io/en/latest/user/authentication/.

  13. MDN Contributors. An Overview of HTTP: HTTP Is Stateless, but Not Sessionless. 2023. URL: https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview#http_is_stateless_but_not_sessionless.

  14. Okta, Inc. Access Tokens. 2024. URL: https://www.oauth.com/oauth2-servers/access-tokens/.

  15. Okta, Inc. Application Credentials: Application Authentication Methods. 2024. URL: https://auth0.com/docs/secure/application-credentials#application-authentication-methods.

  16. Okta, Inc. Authentication and Authorization Flows: Client Credentials Flow. 2024. URL: https://auth0.com/docs/get-started/authentication-and-authorization-flow/client-credentials-flow.

  17. Okta, Inc. Client Credentials. 2024. URL: https://www.oauth.com/oauth2-servers/access-tokens/client-credentials/.

  18. Okta, Inc. The Resource Server. 2024. URL: https://www.oauth.com/oauth2-servers/the-resource-server/.

  19. Okta, Inc. What is OAuth 2.0? 2024. URL: https://auth0.com/intro-to-iam/what-is-oauth-2.

  20. TikTok. API Reference: Query Videos. 2024. URL: https://developers.tiktok.com/doc/research-api-specs-query-videos/.

  21. TikTok. About Research API. 2024. URL: https://developers.tiktok.com/doc/about-research-api/.

  22. TikTok. Client Access Token Management. 2024. URL: https://developers.tiktok.com/doc/client-access-token-management/.