From 5eb525d107855789cd1ac9e93933bc3b7971930f Mon Sep 17 00:00:00 2001 From: gilesb Date: Thu, 8 Jan 2026 17:10:33 +0000 Subject: [PATCH] Add l2_server claim to JWT tokens for L1 verification L1 needs to know which L2 server issued the token so it can verify the token with the correct server. Now tokens include: - l2_server: The L2 server URL (e.g., https://artdag.rose-ash.com) - username: Also include username for compatibility (in addition to sub) Co-Authored-By: Claude Opus 4.5 --- auth.py | 15 +++++++++++++-- server.py | 8 ++++---- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/auth.py b/auth.py index 112fd9c..a3ff749 100644 --- a/auth.py +++ b/auth.py @@ -135,16 +135,27 @@ async def authenticate_user(data_dir: Path, username: str, password: str) -> Opt ) -def create_access_token(username: str) -> Token: - """Create a JWT access token.""" +def create_access_token(username: str, l2_server: str = None) -> Token: + """Create a JWT access token. + + Args: + username: The username + l2_server: The L2 server URL (e.g., https://artdag.rose-ash.com) + Required for L1 to verify tokens with the correct L2. + """ expires = datetime.now(timezone.utc) + timedelta(days=ACCESS_TOKEN_EXPIRE_DAYS) payload = { "sub": username, + "username": username, # Also include as username for compatibility "exp": expires, "iat": datetime.now(timezone.utc) } + # Include l2_server so L1 knows which L2 to verify with + if l2_server: + payload["l2_server"] = l2_server + token = jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM) return Token( diff --git a/server.py b/server.py index 9c016e5..5ba9bf1 100644 --- a/server.py +++ b/server.py @@ -329,7 +329,7 @@ async def ui_login_submit(request: Request): if not user: return HTMLResponse('
Invalid username or password
') - token = create_access_token(user.username) + token = create_access_token(user.username, l2_server=f"https://{DOMAIN}") response = HTMLResponse(f'''
Login successful! Redirecting...
@@ -413,7 +413,7 @@ async def ui_register_submit(request: Request): except ValueError as e: return HTMLResponse(f'
{str(e)}
') - token = create_access_token(user.username) + token = create_access_token(user.username, l2_server=f"https://{DOMAIN}") response = HTMLResponse(f'''
Registration successful! Redirecting...
@@ -1129,7 +1129,7 @@ async def register(req: UserCreate): except ValueError as e: raise HTTPException(400, str(e)) - return create_access_token(user.username) + return create_access_token(user.username, l2_server=f"https://{DOMAIN}") @app.post("/auth/login", response_model=Token) @@ -1139,7 +1139,7 @@ async def login(req: UserLogin): if not user: raise HTTPException(401, "Invalid username or password") - return create_access_token(user.username) + return create_access_token(user.username, l2_server=f"https://{DOMAIN}") @app.get("/auth/me")