mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2025-12-16 02:05:48 -07:00
Increased Agent Refresh Token TTL from 30 to 90 days and made expiration renew every refresh.
This commit is contained in:
@@ -77,14 +77,16 @@ def test_refresh_token_success(engine_harness: EngineTestHarness) -> None:
|
|||||||
with sqlite3.connect(str(harness.db_path)) as conn:
|
with sqlite3.connect(str(harness.db_path)) as conn:
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute(
|
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,),
|
(guid,),
|
||||||
)
|
)
|
||||||
row = cur.fetchone()
|
row = cur.fetchone()
|
||||||
assert row is not None
|
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 last_used_at is not None
|
||||||
assert revoked_at is 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:
|
def test_refresh_token_requires_payload(engine_harness: EngineTestHarness) -> None:
|
||||||
|
|||||||
@@ -312,9 +312,11 @@ def register(
|
|||||||
return hashlib.sha256(token.encode("utf-8")).hexdigest()
|
return hashlib.sha256(token.encode("utf-8")).hexdigest()
|
||||||
|
|
||||||
def _issue_refresh_token(cur: sqlite3.Cursor, guid: str) -> Dict[str, Any]:
|
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)
|
token = secrets.token_urlsafe(48)
|
||||||
now = _now()
|
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(
|
cur.execute(
|
||||||
"""
|
"""
|
||||||
INSERT INTO refresh_tokens (id, guid, token_hash, created_at, expires_at)
|
INSERT INTO refresh_tokens (id, guid, token_hash, created_at, expires_at)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import sqlite3
|
import sqlite3
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone, timedelta
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
|
||||||
from flask import Blueprint, current_app, jsonify, request
|
from flask import Blueprint, current_app, jsonify, request
|
||||||
@@ -28,6 +28,7 @@ def register(
|
|||||||
dpop_validator: DPoPValidator,
|
dpop_validator: DPoPValidator,
|
||||||
) -> None:
|
) -> None:
|
||||||
blueprint = Blueprint("tokens", __name__)
|
blueprint = Blueprint("tokens", __name__)
|
||||||
|
REFRESH_TOKEN_TTL_DAYS = 90
|
||||||
|
|
||||||
def _hash_token(token: str) -> str:
|
def _hash_token(token: str) -> str:
|
||||||
return hashlib.sha256(token.encode("utf-8")).hexdigest()
|
return hashlib.sha256(token.encode("utf-8")).hexdigest()
|
||||||
@@ -70,7 +71,8 @@ def register(
|
|||||||
return jsonify({"error": "refresh_token_revoked"}), 401
|
return jsonify({"error": "refresh_token_revoked"}), 401
|
||||||
if expires_at:
|
if expires_at:
|
||||||
try:
|
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
|
return jsonify({"error": "refresh_token_expired"}), 401
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
@@ -124,10 +126,16 @@ def register(
|
|||||||
"""
|
"""
|
||||||
UPDATE refresh_tokens
|
UPDATE refresh_tokens
|
||||||
SET last_used_at = ?,
|
SET last_used_at = ?,
|
||||||
|
expires_at = ?,
|
||||||
dpop_jkt = COALESCE(NULLIF(?, ''), dpop_jkt)
|
dpop_jkt = COALESCE(NULLIF(?, ''), dpop_jkt)
|
||||||
WHERE id = ?
|
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()
|
conn.commit()
|
||||||
finally:
|
finally:
|
||||||
|
|||||||
Reference in New Issue
Block a user