Skip to content

Commit d164ace

Browse files
style: ruff autofix (auto)
1 parent 5ccb5ec commit d164ace

7 files changed

Lines changed: 53 additions & 30 deletions

File tree

src/connectors/google_drive/oauth.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def _verify_id_token(id_token: str | None) -> dict | None:
3838
logger.debug("Google ID token verified, email=%s", claims.get("email"))
3939
return claims
4040

41+
4142
_REFRESH_TIMEOUT_SECONDS = 30
4243

4344

src/connectors/onedrive/oauth.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@
88
logger = logging.getLogger(__name__)
99

1010

11-
def _verify_access_token(
12-
access_token: str | None, tenant_id: str | None = None
13-
) -> dict | None:
11+
def _verify_access_token(access_token: str | None, tenant_id: str | None = None) -> dict | None:
1412
"""
1513
Verify Microsoft access token signature, expiry, audience, and issuer domain.
1614

src/connectors/sharepoint/oauth.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@
88
logger = logging.getLogger(__name__)
99

1010

11-
def _verify_access_token(
12-
access_token: str | None, tenant_id: str | None = None
13-
) -> dict | None:
11+
def _verify_access_token(access_token: str | None, tenant_id: str | None = None) -> dict | None:
1412
"""
1513
Verify Microsoft access token signature, expiry, audience, and issuer domain.
1614
@@ -154,7 +152,11 @@ async def load_credentials(self) -> bool:
154152
logger.debug(f"Found {len(accounts)} accounts in MSAL cache")
155153
if accounts:
156154
self._current_account = accounts[0]
157-
username = self._current_account.get('username', 'no username') if self._current_account else 'no username'
155+
username = (
156+
self._current_account.get("username", "no username")
157+
if self._current_account
158+
else "no username"
159+
)
158160
logger.debug(f"Set current account: {username}")
159161

160162
if needs_upgrade:
@@ -216,7 +218,11 @@ async def _refresh_from_json_token(self, token_data: dict) -> bool:
216218
logger.debug(f"After refresh, found {len(accounts)} accounts")
217219
if accounts:
218220
self._current_account = accounts[0]
219-
username = self._current_account.get('username', 'no username') if self._current_account else 'no username'
221+
username = (
222+
self._current_account.get("username", "no username")
223+
if self._current_account
224+
else "no username"
225+
)
220226
logger.debug(f"Set current account after refresh: {username}")
221227
return True
222228

src/services/auth_service.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ async def handle_oauth_callback(
287287
# Raises JWTVerificationError on any validation failure — connection is rejected.
288288
if connector_type == "google_drive":
289289
from connectors.google_drive.oauth import _verify_id_token
290+
290291
_verify_id_token(token_data.get("id_token"))
291292
logger.debug("[AUTH] Google ID token verification completed for OAuth callback")
292293

src/utils/env_utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ def get_env_float(key: str, default: float | None = None) -> float | None:
3535
"""Get an environment variable as a float."""
3636
return safe_float(os.getenv(key), default)
3737

38+
3839
def get_env_set(key: str) -> set[str] | None:
3940
"""Return a set of non-empty strings from a comma-separated env var.
4041

src/utils/jwt_verification.py

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,7 @@ def verify_google_id_token(token: str, client_id: str) -> dict[str, Any]:
151151
JWTVerificationError: For other verification failures
152152
"""
153153
if not client_id:
154-
raise JWTVerificationError(
155-
"client_id is required for Google ID token verification"
156-
)
154+
raise JWTVerificationError("client_id is required for Google ID token verification")
157155

158156
try:
159157
# Fetch JWKS
@@ -243,8 +241,7 @@ def _validate_ms_issuer(issuer: str, token_tid: str, signing_key_issuer: str) ->
243241
)
244242
if tid_in_iss and tid_in_iss != token_tid:
245243
raise InvalidIssuerError(
246-
f"Tenant ID in issuer URL {tid_in_iss!r} does not match "
247-
f"tid claim {token_tid!r}"
244+
f"Tenant ID in issuer URL {tid_in_iss!r} does not match tid claim {token_tid!r}"
248245
)
249246

250247

@@ -300,9 +297,7 @@ def verify_microsoft_access_token(
300297
JWTVerificationError: Any other verification failure.
301298
"""
302299
if not client_id:
303-
raise JWTVerificationError(
304-
"client_id is required for Microsoft access token verification"
305-
)
300+
raise JWTVerificationError("client_id is required for Microsoft access token verification")
306301

307302
try:
308303
# Decode without verification to inspect claims and pick the JWKS endpoint.
@@ -356,9 +351,7 @@ def verify_microsoft_access_token(
356351
if not kid:
357352
raise JWTVerificationError("Token header missing 'kid' field")
358353

359-
signing_key_entry = next(
360-
(k for k in jwks.get("keys", []) if k.get("kid") == kid), None
361-
)
354+
signing_key_entry = next((k for k in jwks.get("keys", []) if k.get("kid") == kid), None)
362355
if signing_key_entry is None:
363356
raise JWTVerificationError(f"Signing key with kid '{kid}' not found in JWKS")
364357

@@ -429,4 +422,5 @@ def clear_jwks_cache():
429422
_jwks_cache.clear()
430423
logger.debug("JWKS cache cleared")
431424

425+
432426
# Made with Bob

tests/unit/utils/test_jwt_verification.py

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
verify_microsoft_access_token,
4646
)
4747

48-
4948
# ─────────────────────────────────────────────────────────────────────────────
5049
# Shared helpers
5150
# ─────────────────────────────────────────────────────────────────────────────
@@ -64,8 +63,10 @@ def _generate_rsa_key_pair():
6463
public_key = private_key.public_key()
6564

6665
# Build a minimal JWK for the public key (PyJWT RSAAlgorithm.from_jwk accepts this).
67-
from jwt.algorithms import RSAAlgorithm
6866
import json
67+
68+
from jwt.algorithms import RSAAlgorithm
69+
6970
jwk_str = RSAAlgorithm.to_jwk(public_key)
7071
jwk_dict = json.loads(jwk_str)
7172
jwk_dict["kid"] = KID
@@ -136,10 +137,11 @@ def _clear_cache():
136137
# _resolve_ms_jwks_url
137138
# ─────────────────────────────────────────────────────────────────────────────
138139

140+
139141
class TestResolveMsJwksUrl:
140142
def test_v2_token_uses_v2_endpoint(self):
141143
url = _resolve_ms_jwks_url(TENANT_ID, "2.0")
142-
assert f"/discovery/v2.0/keys" in url
144+
assert "/discovery/v2.0/keys" in url
143145
assert TENANT_ID in url
144146

145147
def test_v1_token_uses_v1_endpoint(self):
@@ -157,6 +159,7 @@ def test_unknown_version_defaults_to_v2(self):
157159
# _validate_ms_issuer
158160
# ─────────────────────────────────────────────────────────────────────────────
159161

162+
160163
class TestValidateMsIssuer:
161164
def test_v2_exact_match_passes(self):
162165
"""Signing key issuer exactly matches token iss — should pass."""
@@ -194,6 +197,7 @@ def test_issuer_without_guid_segment_skips_tid_url_check(self):
194197
# verify_microsoft_access_token
195198
# ─────────────────────────────────────────────────────────────────────────────
196199

200+
197201
class TestVerifyMsAccessToken:
198202
"""Tests for verify_microsoft_access_token()."""
199203

@@ -222,9 +226,12 @@ def test_graph_token_tenant_allow_list_enforced(self):
222226
token = _make_ms_token(self.private_key, aud=MS_GRAPH_AUD)
223227

224228
with patch("utils.jwt_verification._fetch_jwks"):
225-
with pytest.raises(InvalidIssuerError, match="not in the configured allowed tenant list"):
229+
with pytest.raises(
230+
InvalidIssuerError, match="not in the configured allowed tenant list"
231+
):
226232
verify_microsoft_access_token(
227-
token, CLIENT_ID,
233+
token,
234+
CLIENT_ID,
228235
allowed_tenant_ids={"ffffffff-ffff-ffff-ffff-ffffffffffff"},
229236
)
230237

@@ -235,7 +242,8 @@ def test_graph_token_allowed_tenant_passes(self):
235242

236243
with patch("utils.jwt_verification._fetch_jwks"):
237244
claims = verify_microsoft_access_token(
238-
token, CLIENT_ID,
245+
token,
246+
CLIENT_ID,
239247
allowed_tenant_ids={TENANT_ID},
240248
)
241249
assert claims["tid"] == TENANT_ID
@@ -331,9 +339,12 @@ def test_tenant_allow_list_rejects_unlisted_tenant(self):
331339
token = _make_ms_token(self.private_key)
332340

333341
with patch("utils.jwt_verification._fetch_jwks", return_value=self.jwks):
334-
with pytest.raises(InvalidIssuerError, match="not in the configured allowed tenant list"):
342+
with pytest.raises(
343+
InvalidIssuerError, match="not in the configured allowed tenant list"
344+
):
335345
verify_microsoft_access_token(
336-
token, CLIENT_ID,
346+
token,
347+
CLIENT_ID,
337348
allowed_tenant_ids={"ffffffff-ffff-ffff-ffff-ffffffffffff"},
338349
)
339350

@@ -343,7 +354,8 @@ def test_tenant_allow_list_accepts_listed_tenant(self):
343354

344355
with patch("utils.jwt_verification._fetch_jwks", return_value=self.jwks):
345356
claims = verify_microsoft_access_token(
346-
token, CLIENT_ID,
357+
token,
358+
CLIENT_ID,
347359
allowed_tenant_ids={TENANT_ID},
348360
)
349361
assert claims["tid"] == TENANT_ID
@@ -392,8 +404,9 @@ def test_jwks_fetch_failure_raises(self):
392404
"""Network failure during JWKS fetch propagates as JWTVerificationError."""
393405
token = _make_ms_token(self.private_key)
394406

395-
with patch("utils.jwt_verification._fetch_jwks",
396-
side_effect=JWTVerificationError("network error")):
407+
with patch(
408+
"utils.jwt_verification._fetch_jwks", side_effect=JWTVerificationError("network error")
409+
):
397410
with pytest.raises(JWTVerificationError):
398411
verify_microsoft_access_token(token, CLIENT_ID)
399412

@@ -430,6 +443,7 @@ def test_templated_jwks_key_issuer_accepted(self):
430443
# verify_google_id_token
431444
# ─────────────────────────────────────────────────────────────────────────────
432445

446+
433447
class TestVerifyGoogleIdToken:
434448
"""Tests for verify_google_id_token()."""
435449

@@ -523,44 +537,52 @@ def test_jwks_cached_between_calls(self):
523537
# get_env_set (env_utils helper)
524538
# ─────────────────────────────────────────────────────────────────────────────
525539

540+
526541
class TestGetEnvSet:
527542
"""Tests for the get_env_set() helper used for MICROSOFT_ALLOWED_TENANT_IDS."""
528543

529544
def test_unset_returns_none(self, monkeypatch):
530545
monkeypatch.delenv("MICROSOFT_ALLOWED_TENANT_IDS", raising=False)
531546
from utils.env_utils import get_env_set
547+
532548
assert get_env_set("MICROSOFT_ALLOWED_TENANT_IDS") is None
533549

534550
def test_empty_string_returns_none(self, monkeypatch):
535551
monkeypatch.setenv("MICROSOFT_ALLOWED_TENANT_IDS", "")
536552
from utils.env_utils import get_env_set
553+
537554
assert get_env_set("MICROSOFT_ALLOWED_TENANT_IDS") is None
538555

539556
def test_whitespace_only_returns_none(self, monkeypatch):
540557
monkeypatch.setenv("MICROSOFT_ALLOWED_TENANT_IDS", " ")
541558
from utils.env_utils import get_env_set
559+
542560
assert get_env_set("MICROSOFT_ALLOWED_TENANT_IDS") is None
543561

544562
def test_single_value_returns_set(self, monkeypatch):
545563
monkeypatch.setenv("MICROSOFT_ALLOWED_TENANT_IDS", "aaaa-1111")
546564
from utils.env_utils import get_env_set
565+
547566
result = get_env_set("MICROSOFT_ALLOWED_TENANT_IDS")
548567
assert result == {"aaaa-1111"}
549568

550569
def test_multiple_values_returns_set(self, monkeypatch):
551570
monkeypatch.setenv("MICROSOFT_ALLOWED_TENANT_IDS", "aaaa-1111,bbbb-2222,cccc-3333")
552571
from utils.env_utils import get_env_set
572+
553573
result = get_env_set("MICROSOFT_ALLOWED_TENANT_IDS")
554574
assert result == {"aaaa-1111", "bbbb-2222", "cccc-3333"}
555575

556576
def test_values_are_stripped(self, monkeypatch):
557577
monkeypatch.setenv("MICROSOFT_ALLOWED_TENANT_IDS", " aaaa-1111 , bbbb-2222 ")
558578
from utils.env_utils import get_env_set
579+
559580
result = get_env_set("MICROSOFT_ALLOWED_TENANT_IDS")
560581
assert result == {"aaaa-1111", "bbbb-2222"}
561582

562583
def test_empty_segments_ignored(self, monkeypatch):
563584
monkeypatch.setenv("MICROSOFT_ALLOWED_TENANT_IDS", "aaaa-1111,,bbbb-2222,")
564585
from utils.env_utils import get_env_set
586+
565587
result = get_env_set("MICROSOFT_ALLOWED_TENANT_IDS")
566588
assert result == {"aaaa-1111", "bbbb-2222"}

0 commit comments

Comments
 (0)