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

This commit is contained in:
Leo Vasanko
2026-01-28 18:45:02 +00:00
parent 7614d0e8d9
commit 21f3a713f6
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.")
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):
"""Delete a specific credential for the current user."""
ctx = db.data().session_ctx(auth, hostutil.normalize_host(host))
+27 -36
View File
@@ -14,11 +14,7 @@ from fastapi.responses import JSONResponse
from fastapi.security import HTTPBearer
from paskia import db
from paskia.authsession import (
EXPIRES,
get_reset,
refresh_session_token,
)
from paskia.authsession import EXPIRES, expires, get_reset
from paskia.fastapi import authz, session, user
from paskia.fastapi.response import MsgspecResponse
from paskia.fastapi.session import AUTH_COOKIE, AUTH_COOKIE_NAME
@@ -93,19 +89,14 @@ async def validate_token(
if auth:
consumed = EXPIRES - (ctx.session.expiry - datetime.now(UTC))
if not timedelta(0) < consumed < _REFRESH_INTERVAL:
try:
refresh_session_token(
auth,
ip=request.client.host if request.client else "",
user_agent=request.headers.get("user-agent") or "",
)
session.set_session_cookie(response, auth)
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"
)
db.update_session(
auth,
ip=request.client.host if request.client else "",
user_agent=request.headers.get("user-agent") or "",
expiry=expires(),
)
session.set_session_cookie(response, auth)
renewed = True
return MsgspecResponse(
{
"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")
async def forward_authentication(
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")
async def api_logout(request: Request, response: Response, auth=AUTH_COOKIE):
if not auth: