Skip to content

chore: move resources and auth classes into dedicated files - #94

Open
itsoyou wants to merge 4 commits into
mainfrom
syk/remove-some-bits-from-the-config-and-utils-junk-drawer
Open

chore: move resources and auth classes into dedicated files#94
itsoyou wants to merge 4 commits into
mainfrom
syk/remove-some-bits-from-the-config-and-utils-junk-drawer

Conversation

@itsoyou

@itsoyou itsoyou commented Aug 12, 2026

Copy link
Copy Markdown
Member

@itsoyou
itsoyou requested a review from a team as a code owner August 12, 2026 14:35
@cursor

cursor Bot commented Aug 12, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes how outbound auth headers are built and how invalid auth config is rejected; valid basic/bearer configs should behave the same, but stricter parsing could break misconfigured deployments.

Overview
Http auth is moved out of config.py into http_auth.py, with NoAuth, BasicAuth, and BearerAuth modeled as frozen Pydantic models (strict, no extra fields) and parsed via coerce_http_auth for dict/list config shapes. OAuth introspection and notify-on-registration configs still coerce auth in dataclass __post_init__ because Pydantic validators do not run there.

Twisted web resources (LoginMetadataResource, MetadataResource, PublicKeysResource) are extracted from token_authenticator.py and utils.py into synapse_token_authenticator/resources/. TokenAuthenticator registers the same endpoints but uses the new modules and builds OIDC introspection headers with BasicAuth(...).header_map() instead of basic_auth helpers.

Adds tests/test_http_auth.py for parsing, coercion, and config integration. Test helper FakeResponse.json return type is updated to Self.

Reviewed by Cursor Bugbot for commit dc7562a. Bugbot is set up for automated code reviews on this repo. Configure here.

@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.00000% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.38%. Comparing base (749505a) to head (dc7562a).

Files with missing lines Patch % Lines
synapse_token_authenticator/resources/metadata.py 55.55% 4 Missing ⚠️
...se_token_authenticator/resources/login_metadata.py 78.57% 3 Missing ⚠️
...ynapse_token_authenticator/resources/public_key.py 66.66% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #94      +/-   ##
==========================================
+ Coverage   72.05%   76.38%   +4.33%     
==========================================
  Files           5        9       +4     
  Lines         773      792      +19     
  Branches      144      146       +2     
==========================================
+ Hits          557      605      +48     
+ Misses        157      131      -26     
+ Partials       59       56       -3     
Files with missing lines Coverage Δ
synapse_token_authenticator/config.py 73.88% <100.00%> (+8.91%) ⬆️
synapse_token_authenticator/http_auth.py 100.00% <100.00%> (ø)
synapse_token_authenticator/token_authenticator.py 71.84% <100.00%> (+0.31%) ⬆️
synapse_token_authenticator/utils.py 100.00% <ø> (+8.92%) ⬆️
...se_token_authenticator/resources/login_metadata.py 78.57% <78.57%> (ø)
...ynapse_token_authenticator/resources/public_key.py 66.66% <66.66%> (ø)
synapse_token_authenticator/resources/metadata.py 55.55% <55.55%> (ø)

Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 749505a...dc7562a. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread synapse_token_authenticator/token_authenticator.py Outdated
Comment on lines +59 to +68
if auth_type == "basic":
username, password, *rest = args
if rest:
raise ValueError("BasicAuth expects username and password")
return BasicAuth(username=username, password=password)
if auth_type == "bearer":
token, *rest = args
if rest:
raise ValueError("BearerAuth expects a single token")
return BearerAuth(token=token)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a curiosity, what if the config_model had the extra='forbid' and strict=True? Then wouldn't need to test for additional args, right? Can we put the nice error messages onto the base models, or does that need to stay here?

@jason-famedly jason-famedly left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think just those couple of things, a question and a change request and this should be good to go. I wasn't expecting the Pydantic, but what an unexpected delight!

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Auth config no longer coerced
    • Restored _coerce_http_auth in IntrospectionValidationConfig and NotifyOnRegistration post_init so YAML/dict auth is converted to HttpAuth before header_map() is called.

Create PR

Or push these changes by commenting:

@cursor push a65e10029d
Preview (a65e10029d)
diff --git a/synapse_token_authenticator/config.py b/synapse_token_authenticator/config.py
--- a/synapse_token_authenticator/config.py
+++ b/synapse_token_authenticator/config.py
@@ -12,6 +12,7 @@
 from synapse_token_authenticator.http_auth import (
     HttpAuth,
     NoAuth,
+    _coerce_http_auth,
 )
 
 
@@ -107,6 +108,7 @@
                 def __post_init__(self):
                     if not isinstance(self.validator, Exist):
                         self.validator = parse_validator(self.validator)
+                    self.auth = _coerce_http_auth(self.auth)
 
             @dataclass
             class NotifyOnRegistration:
@@ -114,6 +116,9 @@
                 auth: HttpAuth = field(default_factory=NoAuth)
                 interrupt_on_error: bool = True
 
+                def __post_init__(self):
+                    self.auth = _coerce_http_auth(self.auth)
+
             @dataclass
             class OAuthConfig:
                 jwt_validation: JwtValidationConfig | None = None

You can send follow-ups to the cloud agent here.

Comment thread synapse_token_authenticator/config.py
@itsoyou
itsoyou requested a review from jason-famedly August 13, 2026 13:09

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Dict auth ignores extra keys
    • parse_dict_auth now constructs BasicAuth/BearerAuth with **value after popping type so extra=forbid rejects unknown dict keys, matching the previous behavior and list-form validation.

Create PR

Or push these changes by commenting:

@cursor push 140bdee6bd
Preview (140bdee6bd)
diff --git a/synapse_token_authenticator/http_auth.py b/synapse_token_authenticator/http_auth.py
--- a/synapse_token_authenticator/http_auth.py
+++ b/synapse_token_authenticator/http_auth.py
@@ -47,9 +47,9 @@
     if auth_type is None:
         return NoAuth()
     if auth_type == "basic":
-        return BasicAuth(username=value["username"], password=value["password"])
+        return BasicAuth(**value)
     if auth_type == "bearer":
-        return BearerAuth(token=value["token"])
+        return BearerAuth(**value)
     raise AuthValidationError(f"Unknown HttpAuth type {auth_type}")
 
 

diff --git a/tests/test_http_auth.py b/tests/test_http_auth.py
--- a/tests/test_http_auth.py
+++ b/tests/test_http_auth.py
@@ -44,9 +44,24 @@
         assert e.value.args[0] == "HttpAuth missing type"
 
     def test_parse_dict_auth_basic_missing_username(self):
-        with pytest.raises(KeyError):
+        with pytest.raises(ValueError):
             parse_dict_auth({"type": "basic", "password": "pass"})
 
+    def test_parse_dict_auth_basic_extra_fields(self):
+        with pytest.raises(ValueError):
+            parse_dict_auth(
+                {
+                    "type": "basic",
+                    "username": "user",
+                    "password": "pass",
+                    "extra": "field",
+                }
+            )
+
+    def test_parse_dict_auth_bearer_extra_fields(self):
+        with pytest.raises(ValueError):
+            parse_dict_auth({"type": "bearer", "token": "token", "extra": "field"})
+
     def test_parse_dict_auth_unknown_http_auth_type(self):
         with pytest.raises(ValueError) as e:
             parse_dict_auth({"type": "unknown", "token": "token"})

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 1e33a76. Configure here.

Comment thread synapse_token_authenticator/http_auth.py Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants