Fix a bug with validate returning 401 when a session was refreshed. Simplify & cleanup.

This commit is contained in:
2026-01-28 18:45:02 +00:00
parent ce300ebdaf
commit 2cfca81672
2 changed files with 27 additions and 51 deletions
-15
View File
@@ -39,21 +39,6 @@ def get_reset(token: str) -> "ResetToken":
raise ValueError("This authentication link is no longer valid.") raise ValueError("This authentication link is no longer valid.")
def refresh_session_token(token: str, *, ip: str, user_agent: str):
"""Refresh a session extending its expiry."""
session_record = db.data().sessions.get(token)
if not session_record:
raise ValueError("Session not found or expired")
updated = db.update_session(
token,
ip=ip,
user_agent=user_agent,
expiry=expires(),
)
if not updated:
raise ValueError("Session not found or expired")
def delete_credential(credential_uuid: UUID, auth: str, host: str | None = None): def delete_credential(credential_uuid: UUID, auth: str, host: str | None = None):
"""Delete a specific credential for the current user.""" """Delete a specific credential for the current user."""
ctx = db.data().session_ctx(auth, hostutil.normalize_host(host)) ctx = db.data().session_ctx(auth, hostutil.normalize_host(host))
+21 -30
View File
@@ -14,11 +14,7 @@ from fastapi.responses import JSONResponse
from fastapi.security import HTTPBearer from fastapi.security import HTTPBearer
from paskia import db from paskia import db
from paskia.authsession import ( from paskia.authsession import EXPIRES, expires, get_reset
EXPIRES,
get_reset,
refresh_session_token,
)
from paskia.fastapi import authz, session, user from paskia.fastapi import authz, session, user
from paskia.fastapi.response import MsgspecResponse from paskia.fastapi.response import MsgspecResponse
from paskia.fastapi.session import AUTH_COOKIE, AUTH_COOKIE_NAME from paskia.fastapi.session import AUTH_COOKIE, AUTH_COOKIE_NAME
@@ -93,19 +89,14 @@ async def validate_token(
if auth: if auth:
consumed = EXPIRES - (ctx.session.expiry - datetime.now(UTC)) consumed = EXPIRES - (ctx.session.expiry - datetime.now(UTC))
if not timedelta(0) < consumed < _REFRESH_INTERVAL: if not timedelta(0) < consumed < _REFRESH_INTERVAL:
try: db.update_session(
refresh_session_token(
auth, auth,
ip=request.client.host if request.client else "", ip=request.client.host if request.client else "",
user_agent=request.headers.get("user-agent") or "", user_agent=request.headers.get("user-agent") or "",
expiry=expires(),
) )
session.set_session_cookie(response, auth) session.set_session_cookie(response, auth)
renewed = True renewed = True
except ValueError:
# Session disappeared, e.g. due to concurrent logout; global handler will clear
raise authz.AuthException(
status_code=401, detail="Session expired", mode="login"
)
return MsgspecResponse( return MsgspecResponse(
{ {
"valid": True, "valid": True,
@@ -115,24 +106,6 @@ async def validate_token(
) )
@app.get("/token-info")
async def token_info(credentials=Depends(bearer_auth)):
"""Get reset/device-add token info. Pass token via Bearer header."""
token = credentials.credentials
if not passphrase.is_well_formed(token):
raise HTTPException(400, "Invalid token format")
try:
reset_token = get_reset(token)
except ValueError as e:
raise HTTPException(401, str(e))
u = reset_token.user
return {
"token_type": reset_token.token_type,
"display_name": u.display_name,
}
@app.get("/forward") @app.get("/forward")
async def forward_authentication( async def forward_authentication(
request: Request, request: Request,
@@ -248,6 +221,24 @@ async def api_user_info(
) )
@app.get("/token-info")
async def token_info(credentials=Depends(bearer_auth)):
"""Get reset/device-add token info. Pass token via Bearer header."""
token = credentials.credentials
if not passphrase.is_well_formed(token):
raise HTTPException(400, "Invalid token format")
try:
reset_token = get_reset(token)
except ValueError as e:
raise HTTPException(401, str(e))
u = reset_token.user
return {
"token_type": reset_token.token_type,
"display_name": u.display_name,
}
@app.post("/logout") @app.post("/logout")
async def api_logout(request: Request, response: Response, auth=AUTH_COOKIE): async def api_logout(request: Request, response: Response, auth=AUTH_COOKIE):
if not auth: if not auth: