feat(pat): authenticate personal access tokens

handle_auth resolves a dgpt_pat_ bearer against the database instead of
decoding it as a JWT, for both the Flask and the ASGI routes. Scopes and the
resource filter always come from the token row, and the claims that mark a
PAT are stripped from decoded JWTs so a session token cannot pose as one.
ASGI routes reject tokens unless they name the scope that admits them, and
/api/user/me reports what the calling token may do.
This commit is contained in:
arc53-machine committed 2026-09-19 23:39:58 +01:00
1 parent 22ecc0aee3
commit 174130607a
8 files changed
+604 -3

No files matched your search

+1 -1
View File
@@ -94,7 +94,7 @@ async def stream_message_events(request: Request) -> Response:
"""
# Same JWT decoder and OIDC revocation check as the Flask routes. With
# AUTH_TYPE unset the caller resolves to ``{"sub": "local"}``.
decoded, error = await authenticate(request)
decoded, error = await authenticate(request, pat_scope="chat:run")
if error is not None:
return error
user_id = decoded.get("sub") if isinstance(decoded, dict) else None