Increased Agent Refresh Token TTL from 30 to 90 days and made expiration renew every refresh.

This commit is contained in:
2025-11-23 03:51:01 -07:00
parent 584cc940e2
commit aa9bbe1d7e
3 changed files with 18 additions and 6 deletions

View File

@@ -77,14 +77,16 @@ def test_refresh_token_success(engine_harness: EngineTestHarness) -> None:
with sqlite3.connect(str(harness.db_path)) as conn:
cur = conn.cursor()
cur.execute(
"SELECT last_used_at, revoked_at FROM refresh_tokens WHERE guid = ?",
"SELECT last_used_at, revoked_at, expires_at FROM refresh_tokens WHERE guid = ?",
(guid,),
)
row = cur.fetchone()
assert row is not None
last_used_at, revoked_at = row
last_used_at, revoked_at, bumped_expires_at = row
assert last_used_at is not None
assert revoked_at is None
refreshed_expiry = datetime.fromisoformat(bumped_expires_at)
assert refreshed_expiry > now + timedelta(days=80)
def test_refresh_token_requires_payload(engine_harness: EngineTestHarness) -> None:

View File

@@ -312,9 +312,11 @@ def register(
return hashlib.sha256(token.encode("utf-8")).hexdigest()
def _issue_refresh_token(cur: sqlite3.Cursor, guid: str) -> Dict[str, Any]:
# Sliding window expiration; refreshed on each successful token refresh call.
REFRESH_TOKEN_TTL_DAYS = 90
token = secrets.token_urlsafe(48)
now = _now()
expires_at = now.replace(microsecond=0) + timedelta(days=30)
expires_at = now.replace(microsecond=0) + timedelta(days=REFRESH_TOKEN_TTL_DAYS)
cur.execute(
"""
INSERT INTO refresh_tokens (id, guid, token_hash, created_at, expires_at)

View File

@@ -12,7 +12,7 @@ from __future__ import annotations
import hashlib
import sqlite3
from datetime import datetime, timezone
from datetime import datetime, timezone, timedelta
from typing import Callable
from flask import Blueprint, current_app, jsonify, request
@@ -28,6 +28,7 @@ def register(
dpop_validator: DPoPValidator,
) -> None:
blueprint = Blueprint("tokens", __name__)
REFRESH_TOKEN_TTL_DAYS = 90
def _hash_token(token: str) -> str:
return hashlib.sha256(token.encode("utf-8")).hexdigest()
@@ -70,7 +71,8 @@ def register(
return jsonify({"error": "refresh_token_revoked"}), 401
if expires_at:
try:
if _parse_iso(expires_at) <= datetime.now(tz=timezone.utc):
parsed_expiry = _parse_iso(expires_at)
if parsed_expiry <= datetime.now(tz=timezone.utc):
return jsonify({"error": "refresh_token_expired"}), 401
except Exception:
pass
@@ -124,10 +126,16 @@ def register(
"""
UPDATE refresh_tokens
SET last_used_at = ?,
expires_at = ?,
dpop_jkt = COALESCE(NULLIF(?, ''), dpop_jkt)
WHERE id = ?
""",
(_iso_now(), jkt, record_id),
(
_iso_now(),
_iso(datetime.now(tz=timezone.utc) + timedelta(days=REFRESH_TOKEN_TTL_DAYS)),
jkt,
record_id,
),
)
conn.commit()
finally: