SSO- und OAuth-Authentifizierung
Anmeldung über Google, GitHub, HuggingFace und generisches OIDC in Potato konfigurieren. Zugriff nach E-Mail-Domain oder GitHub-Organisation beschränken und SSO neben der lokalen Passwortanmeldung betreiben.
Neu in v2.3.0
Standardmäßig verwendet Potato eine einfache Anmeldung per Benutzername, bei der Annotatoren einen beliebigen Benutzernamen eingeben. Das genügt für die lokale Entwicklung und kleine Projekte, aber Produktivumgebungen brauchen eine richtige Authentifizierung, um unbefugten Zugriff zu verhindern, die Identität der Annotatoren zu bestätigen und institutionelle Anforderungen zu erfüllen.
SSO wird an einer Stelle konfiguriert. Setzen Sie authentication.method auf oauth und listen Sie einen oder mehrere Anbieter unter authentication.providers auf. Jeder Anbieter erhält auf der Anmeldeseite eine eigene Schaltfläche.
Potato bringt eingebaute Endpunkt-Metadaten für drei Anbieter mit: google, github und huggingface. Jeder andere Anbietername wird als generisches OIDC behandelt und benötigt eine discovery_url.
Schnellstart
Eine minimale Google-Einrichtung:
authentication:
method: "oauth"
providers:
google:
client_id: ${GOOGLE_CLIENT_ID}
client_secret: ${GOOGLE_CLIENT_SECRET}
user_identity_field: "email"
secret_key: ${POTATO_SECRET_KEY}Legen Sie die Geheimnisse in der Umgebung ab statt in der Datei:
export GOOGLE_CLIENT_ID="your-client-id.apps.googleusercontent.com"
export GOOGLE_CLIENT_SECRET="your-client-secret"
export POTATO_SECRET_KEY="$(python3 -c 'import secrets; print(secrets.token_hex(32))')"secret_key ist ein Schlüssel der obersten Ebene und gehört nicht zum Block authentication. Setzen Sie ihn oder setzen Sie POTATO_SECRET_KEY. Fehlt beides, erzeugt Potato einen zufälligen Schlüssel, sodass jeder Neustart alle Sitzungen ungültig macht, und protokolliert eine Warnung, wenn OAuth ohne ihn konfiguriert ist.
Potato stellt zwei OAuth-Routen bereit. /auth/login/<provider> startet den Ablauf und /auth/callback/<provider> nimmt die Antwort entgegen. Der Callback ist die URL, die Sie beim Anbieter registrieren, für Google also https://your-domain.com/auth/callback/google. Einen Konfigurationsschlüssel redirect_uri gibt es nicht; die Route wird aus dem Anbieternamen abgeleitet.
Erstellen Sie in der Google Cloud Console OAuth-2.0-Anmeldedaten vom Typ "Web application" und fügen Sie https://your-domain.com/auth/callback/google als autorisierte Weiterleitungs-URI hinzu. Für die lokale Entwicklung wird http://localhost:8000/auth/callback/google akzeptiert.
authentication:
method: "oauth"
providers:
google:
client_id: ${GOOGLE_CLIENT_ID}
client_secret: ${GOOGLE_CLIENT_SECRET}
allowed_domain: "umich.edu"allowed_domain nimmt eine einzelne Domain als String. Nur Konten, deren E-Mail-Adresse zu dieser Domain gehört, können sich anmelden.
GitHub
Registrieren Sie eine OAuth-App unter GitHub Settings > Developer settings > OAuth Apps und setzen Sie die Callback-URL auf https://your-domain.com/auth/callback/github.
authentication:
method: "oauth"
providers:
github:
client_id: ${GITHUB_CLIENT_ID}
client_secret: ${GITHUB_CLIENT_SECRET}
allowed_org: "my-research-lab"allowed_org nimmt einen einzelnen Organisationsnamen. Ist er gesetzt, fordert Potato den Scope read:org automatisch an, sodass Sie die Scopes nicht selbst angeben müssen. Die Mitgliedschaft des Annotators in der Organisation muss öffentlich sein, damit die Prüfung sie sieht.
HuggingFace
Erstellen Sie eine OAuth-Anwendung unter huggingface.co/settings/applications.
authentication:
method: "oauth"
providers:
huggingface:
client_id: ${HF_CLIENT_ID}
client_secret: ${HF_CLIENT_SECRET}
user_identity_field: "username"Der HuggingFace-Anbieter verbindet sich mit dem OIDC-Discovery-Endpunkt von HuggingFace und fordert standardmäßig openid profile email an.
Generisches OIDC
Jeder Anbietername außer google, github und huggingface wird als generisches OIDC behandelt und erfordert discovery_url. Geben Sie ihm einen display_name, damit die Anmeldeschaltfläche lesbar ist.
authentication:
method: "oauth"
providers:
oidc:
display_name: "University SSO"
discovery_url: "https://sso.university.edu/.well-known/openid-configuration"
client_id: ${OIDC_CLIENT_ID}
client_secret: ${OIDC_CLIENT_SECRET}
scopes:
- "openid"
- "email"
- "profile"Die Callback-URL, die Sie beim Anbieter registrieren, folgt dem Anbieterschlüssel. Ein Block namens oidc verwendet also https://your-domain.com/auth/callback/oidc.
Discovery-URLs gängiger Anbieter:
| Anbieter | Discovery-URL |
|---|---|
| Okta | https://your-org.okta.com/.well-known/openid-configuration |
| Azure AD | https://login.microsoftonline.com/{tenant-id}/v2.0/.well-known/openid-configuration |
| Auth0 | https://your-domain.auth0.com/.well-known/openid-configuration |
| Keycloak | https://keycloak.example.com/realms/{realm}/.well-known/openid-configuration |
scopes ist standardmäßig ["openid", "email", "profile"].
Mehrere Anbieter
providers nimmt so viele Einträge auf wie nötig, und jeder erzeugt eine eigene Anmeldeschaltfläche.
authentication:
method: "oauth"
providers:
google:
client_id: ${GOOGLE_CLIENT_ID}
client_secret: ${GOOGLE_CLIENT_SECRET}
github:
client_id: ${GITHUB_CLIENT_ID}
client_secret: ${GITHUB_CLIENT_SECRET}
oidc:
display_name: "University SSO"
discovery_url: "https://sso.university.edu/.well-known/openid-configuration"
client_id: ${OIDC_CLIENT_ID}
client_secret: ${OIDC_CLIENT_SECRET}Mit user_identity_field: "email" ist jemand, der sich über Google und später mit derselben Adresse über den Anbieter der Universität anmeldet, derselbe Potato-Benutzer und landet wieder bei denselben Zuweisungen.
Identität und automatische Registrierung
user_identity_field legt fest, welcher Claim des Anbieters zum Potato-Benutzernamen wird. Erlaubt sind email, username, sub oder name, Standard ist email. Der Wert ist wichtig, weil die Ausgabeverzeichnisse der Annotatoren nach dem Benutzernamen benannt sind. Wer ihn mitten in einer Studie ändert, trennt einen Annotator von seiner früheren Arbeit.
auto_register steuert, ob eine erste erfolgreiche Anmeldung das Potato-Konto anlegt. Standard ist true.
authentication:
method: "oauth"
providers:
google:
client_id: ${GOOGLE_CLIENT_ID}
client_secret: ${GOOGLE_CLIENT_SECRET}
allowed_domain: "umich.edu"
user_identity_field: "email"
auto_register: trueDie Zugriffskontrolle läuft über den Anbieter und nicht über eine Adressliste in der Konfiguration. Um einzuschränken, wer sich anmelden kann, verwenden Sie allowed_domain für Google, allowed_org für GitHub oder die Gruppen- und App-Zuweisungsfunktionen Ihres OIDC-Anbieters.
Gemischter Modus
allow_local_login fügt unter den SSO-Schaltflächen das Formular für Benutzername und Passwort hinzu. Standard ist false, SSO ersetzt also die lokale Anmeldung, sofern Sie diese nicht einschalten.
require_password: true
user_config:
allow_all_users: true
authentication:
method: "oauth"
providers:
google:
client_id: ${GOOGLE_CLIENT_ID}
client_secret: ${GOOGLE_CLIENT_SECRET}
allow_local_login: trueBei einer Migration laufen beide eine Zeit lang parallel. Stellen Sie die Annotatoren um und entfernen Sie allow_local_login, sobald sich alle über den Anbieter angemeldet haben. Der gemischte Modus deckt auch Studien ab, die Annotatoren der eigenen Institution mit externen Annotatoren kombinieren, die dort kein Konto haben.
Lokale Konten im gemischten Modus verwenden dasselbe gesalzene PBKDF2-Hashing wie jedes andere Passwortkonto. Zu den Abläufen zum Zurücksetzen siehe Passwortverwaltung.
Sitzungen
Die Sitzungsdauer ist ein Schlüssel der obersten Ebene, in Tagen:
session_lifetime_days: 7Erst ein stabiler secret_key sorgt dafür, dass Sitzungen einen Neustart überstehen.
Admin-Zugriff
Admin-Endpunkte authentifizieren sich mit einem API-Schlüssel statt über den OAuth-Block:
admin_api_key: ${POTATO_ADMIN_API_KEY}Potato liest admin_api_key zuerst aus der Konfiguration, dann aus der Umgebungsvariablen POTATO_ADMIN_API_KEY. Ist keines von beiden gesetzt, erzeugt es einen Schlüssel und schreibt ihn in admin_api_key.txt im Aufgabenverzeichnis. Aufrufer übergeben ihn im Header X-API-Key.
HTTPS
OAuth-Anbieter verlangen in der Produktion HTTPS-Weiterleitungs-URIs. localhost ist davon ausgenommen, sodass die Entwicklung über HTTP ohne Zertifikat funktioniert.
Hinter einem Reverse Proxy müssen Sie das ursprüngliche Schema weiterreichen, sonst verwendet die von Potato erzeugte Callback-URL http und der Anbieter lehnt sie ab:
location / {
proxy_pass http://localhost:8000;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
}Konfigurationsreferenz
| Schlüssel | Typ | Standard | Beschreibung |
|---|---|---|---|
authentication.method | string | in_memory | in_memory, database, clerk oder oauth |
authentication.providers | dict | erforderlich für oauth | Ein Eintrag pro Anbieter, mit dem Anbieternamen als Schlüssel |
authentication.user_identity_field | string | email | email, username, sub oder name |
authentication.allow_local_login | bool | false | Zeigt das Passwortformular neben den SSO-Schaltflächen |
authentication.auto_register | bool | true | Legt das Potato-Konto bei der ersten Anmeldung an |
secret_key | string | zufällig | Oberste Ebene. Für dauerhafte Sitzungen ist ein stabiler Wert nötig |
session_lifetime_days | int | 7 | Sitzungsdauer, oberste Ebene |
admin_api_key | string | generiert | Schlüssel der obersten Ebene für Admin-Endpunkte |
Schlüssel pro Anbieter:
| Schlüssel | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
client_id | string | ja | Vom Anbieter |
client_secret | string | ja | Vom Anbieter |
discovery_url | string | für generisches OIDC | OIDC-Discovery-Endpunkt |
display_name | string | nein | Text der Anmeldeschaltfläche |
allowed_domain | string | nein | Beschränkt auf eine E-Mail-Domain |
allowed_org | string | nein | Beschränkt auf eine GitHub-Organisation |
scopes | list | nein | Standard ist ["openid", "email", "profile"] |
Vollständiges Beispiel
annotation_task_name: "Annotation Project"
task_dir: "."
authentication:
method: "oauth"
providers:
google:
client_id: ${GOOGLE_CLIENT_ID}
client_secret: ${GOOGLE_CLIENT_SECRET}
allowed_domain: "umich.edu"
user_identity_field: "email"
auto_register: true
secret_key: ${POTATO_SECRET_KEY}
session_lifetime_days: 7
admin_api_key: ${POTATO_ADMIN_API_KEY}
data_files:
- "data/instances.jsonl"
item_properties:
id_key: id
text_key: text
annotation_schemes:
- annotation_type: radio
name: sentiment
description: "What is the sentiment of this text?"
labels: [Positive, Neutral, Negative]
output_annotation_dir: "output/"
export_annotation_format: "jsonl"Fehlerbehebung
Der Anbieter lehnt die Weiterleitungs-URI ab. Die beim Anbieter registrierte URI muss exakt /auth/callback/<provider> entsprechen. Schema und ein etwaiger nachfolgender Pfad zählen zum Abgleich, daher erzeugt ein Proxy, der X-Forwarded-Proto nicht weiterreicht, einen http-Callback, den der Anbieter ablehnt.
Nach einem Neustart sind alle abgemeldet. secret_key ist nicht gesetzt, also hat Potato beim Start einen neuen erzeugt.
Eine GitHub-Organisationsbeschränkung weist ein Mitglied ab. Seine Mitgliedschaft in der Organisation ist privat. Entweder macht das Mitglied sie öffentlich, oder Sie entfernen allowed_org und steuern den Zugriff auf andere Weise.
Die Validierung schlägt mit "providers is required" fehl. method: "oauth" braucht mindestens einen Eintrag unter providers. Der Wert der Methode ist oauth, nicht der Name eines Anbieters.
Weiterführende Informationen
- Passwortverwaltung -- lokale Konten, Hashing und Abläufe zum Zurücksetzen
- Passwortlose Anmeldung -- Zugang nur mit Benutzernamen für offene Aufgaben
- Crowdsourcing-Integration -- Authentifizierung auf Crowdsourcing-Plattformen
- Admin-Dashboard -- Benutzer und Berechtigungen verwalten
Implementierungsdetails finden Sie in der Quelldokumentation.