Skip to content

Commit 614acc3

Browse files
Reject FIC leg-2 apps on silent flows too
The _reject_if_mtls_binding_cert guard already covered the six non-client-credential acquisition flows, but not acquire_token_silent / acquire_token_silent_with_error. With a shared token cache holding user refresh tokens, a FIC leg-2 app (client_assertion + mtls_binding_certificate) could silently redeem one of those RTs, putting the cert-bound leg-1 assertion on a non-mTLS jwt-bearer request -- which ESTS rejects with a confusing invalid_client rather than a clear message. Add the guard to both public silent entry points. Both call the private _acquire_token_silent_with_error directly (not each other), and acquire_token_for_client also uses that private helper, so the guard lives on the two public wrappers -- never on the private method -- to keep the legitimate mTLS client-credential flow working. No-op for normal apps. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent 132fac8 commit 614acc3

2 files changed

Lines changed: 12 additions & 0 deletions

File tree

msal/application.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,6 +1796,7 @@ def acquire_token_silent(
17961796
if cache lookup succeeded.
17971797
- None when cache lookup does not yield a token.
17981798
"""
1799+
self._reject_if_mtls_binding_cert("acquire_token_silent")
17991800
if not account:
18001801
return None # A backward-compatible NO-OP to drop the account=None usage
18011802
result = _clean_up(self._acquire_token_silent_with_error(
@@ -1850,6 +1851,7 @@ def acquire_token_silent_with_error(
18501851
- None when there is simply no token in the cache.
18511852
- A dict containing an "error" key, when token refresh failed.
18521853
"""
1854+
self._reject_if_mtls_binding_cert("acquire_token_silent_with_error")
18531855
if not account:
18541856
return None # A backward-compatible NO-OP to drop the account=None usage
18551857
return _clean_up(self._acquire_token_silent_with_error(

tests/test_application.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1769,6 +1769,16 @@ def test_fic_leg2_app_rejects_non_client_credential_flows(self):
17691769
with self.assertRaises(ValueError):
17701770
app.acquire_token_by_user_federated_identity_credential(
17711771
["s1"], "assertion_token", username="user@contoso.com")
1772+
# Silent flows are also unsupported: a shared cache could hold user RTs
1773+
# whose redemption would put the cert-bound assertion on a non-mTLS
1774+
# jwt-bearer request. Guard both silent entry points (they call the
1775+
# private _acquire_token_silent_with_error directly, not each other).
1776+
account = {"home_account_id": "uid.utid",
1777+
"environment": "login.microsoftonline.com", "username": "u"}
1778+
with self.assertRaises(ValueError):
1779+
app.acquire_token_silent(["s1"], account)
1780+
with self.assertRaises(ValueError):
1781+
app.acquire_token_silent_with_error(["s1"], account)
17721782

17731783
def test_secret_credential_with_flag_raises(self):
17741784
app = ConfidentialClientApplication(

0 commit comments

Comments
 (0)