feat: add sliding session timeout with idle and absolute caps

This commit is contained in:
2026-04-26 18:12:37 +09:30
parent 60799bbc52
commit d48e6b2f97
14 changed files with 398 additions and 31 deletions
+27 -1
View File
@@ -116,7 +116,7 @@ def login():
remember_me = data.get("remember_me", False)
policy_result = MfaPolicyService.after_primary_auth_success(user, remember_me)
duration = 2592000 if remember_me else 86400
duration = current_app.config.get("SESSION_ABSOLUTE_TIMEOUT", 28800) if remember_me else None
is_compliance_only = policy_result.create_compliance_only_session
user_session = AuthService.create_session(user, duration_seconds=duration, is_compliance_only=is_compliance_only)
@@ -227,6 +227,32 @@ def revoke_session(session_id):
return api_response(message="Session revoked successfully")
@api_v1_bp.route("/auth/sessions/refresh", methods=["POST"])
@login_required
def refresh_session():
"""Extend the current session's idle window.
The server already refreshes the session on every authenticated
request, but this endpoint exists so the frontend can proactively
keep a session alive (e.g. a heartbeat while the user is reading
a long page with no API calls).
Returns the new ``expires_at`` so the frontend can display a
countdown or warning before the absolute cap.
"""
session = g.current_session
session.refresh()
return api_response(
data={
"expires_at": session.expires_at.isoformat() + "Z"
if session.expires_at.isoformat()[-1] != "Z"
else session.expires_at.isoformat(),
},
message="Session refreshed",
)
@api_v1_bp.route("/auth/token", methods=["GET"])
@login_required
def get_token():
+2 -2
View File
@@ -190,8 +190,8 @@ def select_organization():
if not member:
return api_response(success=False, message="You are not a member of this organization", status=403, error_type="FORBIDDEN")
from gatehouse_app.services.session_service import SessionService
session = SessionService.create_session(user=user, organization_id=organization_id)
from gatehouse_app.services.auth_service import AuthService
session = AuthService.create_session(user=user)
state_record.mark_used()
provider_type_val = state_record.provider_type.value if isinstance(state_record.provider_type, _AuthMethodType) else state_record.provider_type