Skip to content

Commit 3d6e831

Browse files
committed
Expose and document AutoRefresher, deprecate client_assertion as a string
This addresses 705 and 746
1 parent 331c16f commit 3d6e831

File tree

3 files changed

+41
-10
lines changed

3 files changed

+41
-10
lines changed

msal/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,5 @@
4545
# 1. officially part of the MSAL public API, and
4646
# 2. can still be caught by the user code even if we change the module structure.
4747
from .oauth2cli.oauth2 import BrowserInteractionTimeoutError
48+
from .oauth2cli.assertion import AutoRefresher
4849

msal/application.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,30 @@ def __init__(
304304
305305
.. admonition:: Supporting raw assertion obtained from elsewhere
306306
307+
*Added in version 1.32.0*:
308+
309+
MSAL Python accepts a callback which shall obtain an assertion::
310+
311+
import msal
312+
313+
def assertion_callback():
314+
return '''A fresh JWT with claims:
315+
aud, exp, iss, jti, nbf, and sub'''
316+
317+
smart_callback = msal.AutoRefresher(
318+
assertion_callback,
319+
expires_in=3600, # Whatever value that you see fit
320+
) # This ensures the original callback will be cached
321+
322+
app = msal.ConfidentialClientApplication(
323+
...,
324+
client_credential={"client_assertion": smart_callback},
325+
)
326+
307327
*Added in version 1.13.0*:
328+
329+
Deprecated.
330+
308331
It can also be a completely pre-signed assertion that you've assembled yourself.
309332
Simply pass a container containing only the key "client_assertion", like this::
310333
@@ -757,6 +780,11 @@ def _build_client(self, client_credential, authority, skip_regional_client=False
757780
# Use client_credential.get("...") rather than "..." in client_credential
758781
# so that we can ignore an empty string came from an empty ENV VAR.
759782
if client_credential.get("client_assertion"):
783+
if isinstance(client_credential["client_assertion"], str):
784+
warnings.warn(
785+
"Please use a callback instead of a string. See also "
786+
"https://msal-python.readthedocs.io/en/latest/#msal.ClientApplication.params.client_credential",
787+
DeprecationWarning)
760788
client_assertion = client_credential['client_assertion']
761789
else:
762790
headers = {}

tests/test_e2e.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -692,14 +692,16 @@ def _test_acquire_token_obo(self, config_pca, config_cca,
692692
result = cca.acquire_token_silent(config_cca["scope"], account)
693693
self.assertEqual(cca_result["access_token"], result["access_token"])
694694

695-
def _test_acquire_token_by_client_secret(
696-
self, client_id=None, client_secret=None, authority=None, scope=None,
695+
def _test_acquire_token_for_client(
696+
self, client_id=None, client_credential=None, authority=None, scope=None,
697697
oidc_authority=None,
698698
**ignored):
699-
assert client_id and client_secret and scope and (
699+
assert client_id and client_credential and scope and (
700700
authority or oidc_authority)
701701
self.app = msal.ConfidentialClientApplication(
702-
client_id, client_credential=client_secret, authority=authority,
702+
client_id,
703+
client_credential=client_credential,
704+
authority=authority,
703705
oidc_authority=oidc_authority,
704706
http_client=MinimalHttpClient())
705707
result = self.app.acquire_token_for_client(scope)
@@ -936,9 +938,9 @@ def test_acquire_token_by_client_secret(self):
936938
# Vastly different than ArlingtonCloudTestCase.test_acquire_token_by_client_secret()
937939
_app = self.get_lab_app_object(
938940
publicClient="no", signinAudience="AzureAdMyOrg")
939-
self._test_acquire_token_by_client_secret(
941+
self._test_acquire_token_for_client(
940942
client_id=_app["appId"],
941-
client_secret=self.get_lab_user_secret(
943+
client_credential=self.get_lab_user_secret(
942944
_app["clientSecret"].split("/")[-1]),
943945
authority="{}{}.onmicrosoft.com".format(
944946
_app["authority"], _app["labName"].lower().rstrip(".com")),
@@ -1047,9 +1049,9 @@ def test_ciam_acquire_token_for_client(self):
10471049
else: # Ciam6 era has a URL path that ends with the secret name
10481050
secret_name = secret_url.path.split("/")[-1]
10491051
logger.info('Detected secret name "%s" from "%s"', secret_name, raw_url)
1050-
self._test_acquire_token_by_client_secret(
1052+
self._test_acquire_token_for_client(
10511053
client_id=self.app_config["appId"],
1052-
client_secret=self.get_lab_user_secret(secret_name),
1054+
client_credential=self.get_lab_user_secret(secret_name),
10531055
authority=self.app_config.get("authority"),
10541056
oidc_authority=self.app_config.get("oidc_authority"),
10551057
scope=self.app_config["scopes"], # It shall ends with "/.default"
@@ -1212,8 +1214,8 @@ def test_acquire_token_by_ropc(self):
12121214

12131215
def test_acquire_token_by_client_secret(self):
12141216
config = self.get_lab_user(usertype="cloud", azureenvironment=self.environment, publicClient="no")
1215-
config["client_secret"] = self.get_lab_user_secret("ARLMSIDLAB1-IDLASBS-App-CC-Secret")
1216-
self._test_acquire_token_by_client_secret(**config)
1217+
config["client_credential"] = self.get_lab_user_secret("ARLMSIDLAB1-IDLASBS-App-CC-Secret")
1218+
self._test_acquire_token_for_client(**config)
12171219

12181220
def test_acquire_token_obo(self):
12191221
config_cca = self.get_lab_user(

0 commit comments

Comments
 (0)