fix(auth): Sitzungen ueber die Benutzer-ID statt ueber den Namen aufloesen
Das Sitzungs-Token trug den Benutzernamen als Subjekt, und get_current_user suchte danach. Eine Umbenennung machte damit jedes Token auf jedem anderen Geraet stillschweigend ungueltig — der Nutzer flog ohne Hinweis raus. Tokens tragen jetzt zusaetzlich uid, die unveraenderliche Zeilen-ID, und die Aufloesung geht darueber. sub bleibt als Anzeigename erhalten. Tokens ohne uid werden weiter ueber den Namen aufgeloest, damit vor der Aenderung ausgestellte Sitzungen gueltig bleiben — mit "Angemeldet bleiben" laufen die 180 Tage. Fuer SSO war die Zuordnung schon vorher richtig: OIDCIdentity haengt an (provider_key, sub) des Providers, und bei bekanntem sub wird der lokale Benutzername nicht angefasst. Ein umbenannter Nutzer in Authentik landet also unveraendert auf demselben Konto. Vier Tests halten beide Richtungen fest: Umbenennung beim Provider, lokale Umbenennung mit weiterlaufender Sitzung, lokale Umbenennung mit erhaltener SSO-Verknuepfung, und die Kompatibilitaet alter Tokens. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
cc4daf4a84
commit
725b61c8cb
@@ -33,7 +33,7 @@ from sqlalchemy.orm import Session
|
||||
import models
|
||||
import oidc_client
|
||||
import oidc_config
|
||||
from auth import ALGORITHM, SECRET_KEY, create_access_token, get_current_user
|
||||
from auth import ALGORITHM, SECRET_KEY, create_user_token, get_current_user
|
||||
from database import get_db
|
||||
from dav_util import public_base
|
||||
from oidc_client import OIDCError
|
||||
@@ -275,7 +275,7 @@ def oidc_callback(provider_key: str, request: Request,
|
||||
return _fail(request, e.slug)
|
||||
|
||||
logger.info("OIDC login (%s) user id=%s via %s", action, user.id, provider.key)
|
||||
token = create_access_token({"sub": user.username})
|
||||
token = create_user_token(user)
|
||||
|
||||
resp = RedirectResponse(url="/?sso=1", status_code=302)
|
||||
resp.delete_cookie(FLOW_COOKIE, path="/api/auth/oidc")
|
||||
@@ -300,13 +300,13 @@ def oidc_complete(request: Request, response: Response, db: Session = Depends(ge
|
||||
|
||||
try:
|
||||
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
|
||||
username = payload.get("sub")
|
||||
uid = payload.get("uid")
|
||||
except JWTError:
|
||||
raise HTTPException(401, "SSO-Sitzung ungültig")
|
||||
if not username:
|
||||
if uid is None:
|
||||
raise HTTPException(401, "SSO-Sitzung ungültig")
|
||||
|
||||
user = db.query(models.User).filter(models.User.username == username).first()
|
||||
user = db.query(models.User).filter(models.User.id == uid).first()
|
||||
if not user:
|
||||
raise HTTPException(401, "SSO-Sitzung ungültig")
|
||||
|
||||
@@ -404,7 +404,7 @@ def oidc_exchange(req: ExchangeRequest, db: Session = Depends(get_db)):
|
||||
|
||||
logger.info("OIDC exchange (%s) user id=%s via %s", action, user.id, provider.key)
|
||||
return {
|
||||
"access_token": create_access_token({"sub": user.username}),
|
||||
"access_token": create_user_token(user),
|
||||
"token_type": "bearer",
|
||||
"user": _user_dict(user),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user