certauth/tests/test_auth.py
Jarian Cottingham df82068aeb fix: CSRF protection, cookie security flags, rate limiting, XSS (#23,#24,#25,#28,#33)
Add CSRF tokens to all cookie-based POST endpoints.
Set Secure and SameSite=Strict on auth cookie.
Rate limit login to 5 attempts per 15min per IP.
Escape HTML in signing error messages (XSS fix).
Remove duplicate get_user_from_cookie definition.
2026-07-04 04:51:56 +00:00

60 lines
2.0 KiB
Python

import os
import sys
import unittest
from unittest import mock
from httpx import AsyncClient, ASGITransport
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "api"))
class TestAuthSecurity(unittest.TestCase):
def test_rate_limiting_exists(self):
import main
self.assertTrue(hasattr(main, '_check_rate_limit'))
self.assertEqual(main._LOGIN_MAX_ATTEMPTS, 5)
self.assertEqual(main._LOGIN_WINDOW_SECONDS, 900)
def test_csrf_token_generation(self):
import main
t1 = main._generate_csrf_token()
t2 = main._generate_csrf_token()
self.assertNotEqual(t1, t2)
self.assertEqual(len(t1), 64)
def test_csrf_verify_rejects_empty(self):
import main
req = mock.MagicMock()
req.cookies.get.return_value = None
self.assertFalse(main._verify_csrf_token(req, "any-token"))
def test_csrf_verify_rejects_mismatch(self):
import main
req = mock.MagicMock()
req.cookies.get.return_value = "stored-token"
self.assertFalse(main._verify_csrf_token(req, "different-token"))
def test_csrf_verify_accepts_match(self):
import main
req = mock.MagicMock()
req.cookies.get.return_value = "matching-token"
self.assertTrue(main._verify_csrf_token(req, "matching-token"))
def test_no_duplicate_get_user_from_cookie(self):
import main, inspect
sources = inspect.getsourcelines(main)[0]
count = sum(1 for line in sources if 'def get_user_from_cookie' in line)
self.assertEqual(count, 1, "get_user_from_cookie must be defined exactly once")
def test_xss_escaped_in_sign_error(self):
"""Check that HTML in error messages gets escaped."""
import html as h
err = '<script>alert("xss")</script>'
escaped = h.escape(err)
self.assertNotIn("<script>", escaped)
self.assertIn("&lt;script&gt;", escaped)
if __name__ == "__main__":
unittest.main()