diff --git a/.gitignore b/.gitignore index 36b43713..eedae684 100644 --- a/.gitignore +++ b/.gitignore @@ -49,6 +49,7 @@ src/build docs/_build/ # Visual Studio Files /.vs/* +.vscode/* /tests/.vs/* # vim files diff --git a/msal/application.py b/msal/application.py index 75c36d59..8f06c275 100644 --- a/msal/application.py +++ b/msal/application.py @@ -1542,20 +1542,35 @@ def _acquire_token_silent_from_cache_and_possibly_refresh_it( None, # Unknown data from older MSAL. Broker might still work. ): from .broker import _acquire_token_silently + _authority = "https://{}/{}".format( + self.authority.instance, self.authority.tenant) + claims = _merge_claims_challenge_and_capabilities( + self._client_capabilities, claims_challenge) response = _acquire_token_silently( - "https://{}/{}".format(self.authority.instance, self.authority.tenant), + _authority, self.client_id, account["local_account_id"], scopes, - claims=_merge_claims_challenge_and_capabilities( - self._client_capabilities, claims_challenge), + claims=claims, correlation_id=correlation_id, auth_scheme=auth_scheme, **data) + if force_refresh and response.get("access_token"): + response = _acquire_token_silently( + _authority, + self.client_id, + account["local_account_id"], + scopes, + claims=claims, + correlation_id=correlation_id, + auth_scheme=auth_scheme, + at_to_renew=response.get("access_token"), + **data) if response: # Broker provides a decisive outcome account_was_established_by_broker = account.get( "account_source") == _GRANT_TYPE_BROKER broker_attempt_succeeded_just_now = "error" not in response + if account_was_established_by_broker or broker_attempt_succeeded_just_now: return self._process_broker_response(response, scopes, data) diff --git a/msal/broker.py b/msal/broker.py index e16e6102..02a316f1 100644 --- a/msal/broker.py +++ b/msal/broker.py @@ -215,6 +215,7 @@ def _signin_interactively( def _acquire_token_silently( authority, client_id, account_id, scopes, claims=None, correlation_id=None, auth_scheme=None, + at_to_renew=None, **kwargs): # For MSA PT scenario where you use the /organizations, yes, # acquireTokenSilently is expected to fail. - Sam Wilson @@ -224,6 +225,8 @@ def _acquire_token_silently( return params = pymsalruntime.MSALRuntimeAuthParameters(client_id, authority) params.set_requested_scopes(scopes) + if at_to_renew: + params.set_access_token_to_renew(at_to_renew) if claims: params.set_decoded_claims(claims) if auth_scheme: diff --git a/tests/test_account_source.py b/tests/test_account_source.py index 662f0419..c9a2430d 100644 --- a/tests/test_account_source.py +++ b/tests/test_account_source.py @@ -73,6 +73,6 @@ def test_interactive_flow_and_its_silent_call_should_invoke_broker(self, _, mock result = app.acquire_token_silent_with_error( [SCOPE], account, force_refresh=True, post=_mock_post) - mocked_broker_ats.assert_called_once() + mocked_broker_ats.assert_called() self.assertEqual(result["token_source"], "broker") diff --git a/tests/test_force_refresh.py b/tests/test_force_refresh.py new file mode 100644 index 00000000..93ca89d6 --- /dev/null +++ b/tests/test_force_refresh.py @@ -0,0 +1,43 @@ +from tests import unittest +import msal +import sys + + +if sys.platform not in ("win32", "darwin"): + raise unittest.SkipTest(f"Our broker does not support {sys.platform}") + +SCOPES = ["https://management.azure.com/.default"] +_AZURE_CLI = "04b07795-8ddb-461a-bbee-02f9e1bf7b46" +pca = msal.PublicClientApplication( + _AZURE_CLI, + authority="https://login.microsoftonline.com/organizations", + enable_broker_on_mac=True, + enable_broker_on_windows=True, + ) + + +class ForceRefreshTestCase(unittest.TestCase): + def test_silent_with_force_refresh_should_return_a_new_token(self): + result = pca.acquire_token_interactive( + scopes=SCOPES, + prompt="select_account", + parent_window_handle=pca.CONSOLE_WINDOW_HANDLE, + enable_msa_passthrough=True, + ) + accounts = pca.get_accounts() + self.assertNotEqual( + [], accounts, + "Interactive flow should have established a logged-in account") + account = accounts[0] + old_token = result.get("access_token") + + result = pca.acquire_token_silent(SCOPES, account) + assertion = "This token should have been received from cache" + self.assertEqual(result.get("access_token"), old_token, assertion) + self.assertEqual(result.get("token_source"), "cache", assertion) + + result = pca.acquire_token_silent(SCOPES, account, force_refresh=True) + assertion = "A new token should have been received from broker" + self.assertNotEqual(result.get("access_token"), old_token, assertion) + self.assertEqual(result.get("token_source"), "broker", assertion) +