From 9d9f8a8bae467839fbaed9b1e9221872dea3ee41 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Sun, 3 Aug 2025 08:50:57 -0400 Subject: [PATCH] Hash JWT token in API --- src/seedpass/api.py | 8 ++++++-- src/tests/test_api.py | 7 +++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/seedpass/api.py b/src/seedpass/api.py index e7cd0c0..8e85955 100644 --- a/src/seedpass/api.py +++ b/src/seedpass/api.py @@ -16,6 +16,7 @@ from fastapi import FastAPI, Header, HTTPException, Request, Response import asyncio import sys from fastapi.middleware.cors import CORSMiddleware +import hashlib from slowapi import Limiter, _rate_limit_exceeded_handler from slowapi.errors import RateLimitExceeded @@ -49,6 +50,8 @@ def _check_token(auth: str | None) -> None: raise HTTPException(status_code=401, detail="Token expired") except jwt.InvalidTokenError: raise HTTPException(status_code=401, detail="Unauthorized") + if hashlib.sha256(token.encode()).hexdigest() != _token: + raise HTTPException(status_code=401, detail="Unauthorized") def _reload_relays(relays: list[str]) -> None: @@ -80,7 +83,8 @@ def start_server(fingerprint: str | None = None) -> str: _pm = PasswordManager(fingerprint=fingerprint) _jwt_secret = secrets.token_urlsafe(32) payload = {"exp": datetime.now(timezone.utc) + timedelta(minutes=5)} - _token = jwt.encode(payload, _jwt_secret, algorithm="HS256") + raw_token = jwt.encode(payload, _jwt_secret, algorithm="HS256") + _token = hashlib.sha256(raw_token.encode()).hexdigest() if not getattr(app.state, "limiter", None): app.state.limiter = limiter app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler) @@ -97,7 +101,7 @@ def start_server(fingerprint: str | None = None) -> str: allow_methods=["*"], allow_headers=["*"], ) - return _token + return raw_token def _require_password(password: str | None) -> None: diff --git a/src/tests/test_api.py b/src/tests/test_api.py index 118e3a0..a44064c 100644 --- a/src/tests/test_api.py +++ b/src/tests/test_api.py @@ -4,6 +4,7 @@ import sys import pytest from fastapi.testclient import TestClient +import hashlib sys.path.append(str(Path(__file__).resolve().parents[1])) @@ -48,6 +49,12 @@ def client(monkeypatch): return client, token +def test_token_hashed(client): + _, token = client + assert api._token != token + assert api._token == hashlib.sha256(token.encode()).hexdigest() + + def test_cors_and_auth(client): cl, token = client headers = {"Authorization": f"Bearer {token}", "Origin": "http://example.com"}