6.3 KiB
name, description
| name | description |
|---|---|
| onyva-login | Integriert den zentralen Onyva Dev Login (OIDC/SSO) in ein bestehendes Projekt. Nutze diesen Skill wenn jemand "onyva login integrieren", "auth integrieren" oder "/onyva-login" schreibt. |
Deine Aufgabe ist es, den zentralen Onyva Dev Login (OIDC/SSO-Server unter https://login.onyva.dev) in das aktuelle Projekt zu integrieren.
Vorgehen
-
Analysiere das Projekt zuerst — Lies relevante Dateien (Framework, Routing, vorhandene Auth-Logik, Env-Konfiguration), bevor du Code schreibst.
-
Frage nach fehlenden Infos — Du brauchst:
OIDC_CLIENT_IDundOIDC_CLIENT_SECRET(aus dem Admin-Panel von login.onyva.dev)OIDC_REDIRECT_URI(wohin der Auth-Server nach dem Login zurückleitet — muss im Admin-Panel eingetragen sein)OIDC_LOGOUT_REDIRECT_URI(wohin nach dem zentralen Logout weitergeleitet wird)- Falls noch nicht bekannt: welche Routen geschützt sein sollen und welche öffentlich bleiben
-
Implementiere die Integration nach den technischen Vorgaben unten.
-
Passe
.env.example(oder äquivalente Konfiguration) mit allen nötigen Variablen an.
Technische Vorgaben
Auth-Server
- Issuer / Basis-URL:
https://login.onyva.dev - Discovery:
https://login.onyva.dev/.well-known/openid-configuration
| Endpunkt | Methode | Zweck |
|---|---|---|
/oauth/authorize |
GET | Login starten |
/oauth/token |
POST | Code gegen Tokens tauschen |
/oauth/userinfo |
GET | Nutzerinfos per Bearer Token |
/oauth/jwks.json |
GET | Public Keys (RS256) |
/logout |
GET | Zentrales Logout |
Login starten
Generiere state (≥16 Zeichen, zufällig) und code_verifier (PKCE), speichere beide serverseitig in der Session. Dann Weiterleitung zu:
GET https://login.onyva.dev/oauth/authorize
?response_type=code
&client_id={OIDC_CLIENT_ID}
&redirect_uri={OIDC_REDIRECT_URI}
&scope=openid profile email
&state={state}
&code_challenge={BASE64URL(SHA256(code_verifier))}
&code_challenge_method=S256
Wichtig: state muss nachweislich in der URL stehen — ohne state kein state im Callback.
Callback verarbeiten
# Pseudocode — an das Framework anpassen
def callback(request):
# 1. State validieren
if request.params.get("state") != session.pop("oauth_state", None):
return error("State mismatch")
# 2. Sonderfall: Auth deaktiviert
if "auth_disabled" in request.params:
session["user"] = {"auth_disabled": True}
return redirect("/")
# 3. Token-Tausch (application/x-www-form-urlencoded, kein JSON)
resp = http_post("https://login.onyva.dev/oauth/token", data={
"grant_type": "authorization_code",
"code": request.params["code"],
"redirect_uri": OIDC_REDIRECT_URI,
"client_id": OIDC_CLIENT_ID,
"client_secret": OIDC_CLIENT_SECRET,
"code_verifier": session.pop("pkce_verifier"),
})
tokens = resp.json()
# 4. Claims aus id_token lesen
claims = decode_jwt(tokens["id_token"]) # Verifikation optional für interne Nutzung
session["user"] = {
"sub": claims["sub"], # "user:42"
"email": claims["email"],
"name": claims["name"],
"user_type": claims["user_type"], # "employee" | "customer"
"app_roles": claims["app_roles"], # ["admin"] | ["editor"] | ["viewer"] | []
}
return redirect("/")
Nach erfolgreichem Callback niemals auf /auth/* zurückleiten — return_to immer auf / oder eine echte App-Seite normalisieren.
JWT Claims
{
"sub": "user:42",
"email": "nutzer@onyva.de",
"name": "Max Mustermann",
"user_type": "employee",
"app_roles": ["admin"],
"iss": "https://login.onyva.dev",
"aud": "mein-client-id",
"exp": 1700000000
}
Logout
def logout(request):
session.clear()
return redirect(
f"https://login.onyva.dev/logout"
f"?post_logout_redirect_uri={urllib.parse.quote(OIDC_LOGOUT_REDIRECT_URI)}"
)
post_logout_redirect_uri muss absolut sein (https://...). Der Auth-Server löscht die zentrale Session — der Nutzer ist danach auf allen Onyva-Apps ausgeloggt.
Auth-Mode-Verhalten
| auth_mode | Auth-Server-Verhalten | Client-Verhalten |
|---|---|---|
required |
403 wenn keine Mitgliedschaft | Fehlermeldung anzeigen |
optional |
Code für jeden angemeldeten Nutzer; app_roles ggf. leer |
App entscheidet selbst |
disabled |
Sofort zurück mit ?auth_disabled=1 |
Kein Login-Dialog, alle Funktionen offen |
AUTH_ENABLED=false (Entwicklungsmodus)
def require_auth(request):
if not AUTH_ENABLED:
return {"sub": "user:0", "email": "dev@local", "name": "Dev", "user_type": "employee", "app_roles": ["admin"]}
# ... normaler Flow
Env-Variablen
OIDC_ISSUER=https://login.onyva.dev
OIDC_CLIENT_ID= # aus Admin-Panel
OIDC_CLIENT_SECRET= # aus Admin-Panel
OIDC_REDIRECT_URI= # muss exakt im Admin-Panel stehen; bei /api-Prefix: https://app.example.com/api/auth/callback
OIDC_LOGOUT_REDIRECT_URI= # z.B. https://app.example.com/
AUTH_ENABLED=true
Wichtige Fallstricke
- State ist Pflicht — wird er nicht mitgeschickt, kommt er nicht zurück und der Callback schlägt fehl
- Redirect URI exakt —
/api/auth/callback≠/auth/callback; im Admin-Panel muss genau dieselbe URL stehen - Token-Endpunkt: Form, kein JSON —
Content-Type: application/x-www-form-urlencoded - Session-Middleware — bei Starlette/FastAPI:
itsdangerousals Dependency erforderlich - Öffentliche Routen ausdrücklich ausnehmen — Upload-Links, Webhooks, Health-Checks müssen vom Auth Guard ausgeschlossen bleiben
- Kein Redirect auf Auth-Routen —
return_toniemals auf/auth/*setzen
Schnellcheckliste
- Env-Variablen konfiguriert und
.env.exampleaktualisiert - Redirect URI im Admin-Panel von login.onyva.dev eingetragen
- Login-Route:
state+ PKCE generiert, in Session gespeichert, in Authorize-URL enthalten - Callback-Route:
statevalidiert, Token-Tausch, Claims in Session - Logout-Route: lokale Session gelöscht, Weiterleitung zu zentralem Logout
- Auth Guard für geschützte Routen
- Öffentliche Routen explizit ausgenommen
AUTH_ENABLED=falseBypass für Entwicklungauth_disabled=1Callback-Fall abgedeckt