Skip to content

Commit 0e9e495

Browse files
committed
Implement issuer validation on CCA's aquire_token_for_client()
1 parent 8f63843 commit 0e9e495

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

msal/application.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2409,6 +2409,14 @@ def acquire_token_for_client(self, scopes, claims_challenge=None, **kwargs):
24092409
- A successful response would contain "access_token" key,
24102410
- an error response would contain "error" and usually "error_description".
24112411
"""
2412+
if not self.authority.is_valid_issuer():
2413+
return {
2414+
"error": "invalid_issuer",
2415+
"error_description": (
2416+
"The issuer '{}' does not match this authority. "
2417+
"No token request will be sent."
2418+
).format(self.authority._issuer),
2419+
}
24122420
if kwargs.get("force_refresh"):
24132421
raise ValueError( # We choose to disallow force_refresh
24142422
"Historically, this method does not support force_refresh behavior. "

msal/authority.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ def __init__(
6767
performed.
6868
"""
6969
self._http_client = http_client
70+
self._oidc_authority_url = oidc_authority_url
7071
if oidc_authority_url:
7172
logger.debug("Initializing with OIDC authority: %s", oidc_authority_url)
7273
tenant_discovery_endpoint = self._initialize_oidc_authority(
@@ -95,6 +96,7 @@ def __init__(
9596
raise ValueError(error_message)
9697
logger.debug(
9798
'openid_config("%s") = %s', tenant_discovery_endpoint, openid_config)
99+
self._issuer = openid_config.get('issuer')
98100
self.authorization_endpoint = openid_config['authorization_endpoint']
99101
self.token_endpoint = openid_config['token_endpoint']
100102
self.device_authorization_endpoint = openid_config.get('device_authorization_endpoint')
@@ -174,11 +176,24 @@ def user_realm_discovery(self, username, correlation_id=None, response=None):
174176
self.__class__._domains_without_user_realm_discovery.add(self.instance)
175177
return {} # This can guide the caller to fall back normal ROPC flow
176178

179+
def is_valid_issuer(self) -> bool:
180+
if self._oidc_authority_url:
181+
return self._oidc_authority_url == self._issuer
182+
else:
183+
# The non-OIDC cases include:
184+
# those known-to-Microsoft, those known-to-developer,
185+
# those already passed authority validation, or those opted out of authority validation.
186+
# TODO: We plan to remove the OIDC discovery behavior in the near future.
187+
# Then we can simply return True here.
188+
return True
189+
177190

178191
def canonicalize(authority_or_auth_endpoint):
179192
# Returns (url_parsed_result, hostname_in_lowercase, tenant)
180193
authority = urlparse(authority_or_auth_endpoint)
181-
if authority.scheme == "https":
194+
if (
195+
authority.scheme == "http" and authority.hostname in ("localhost", "127.0.0.1")
196+
) or authority.scheme == "https":
182197
parts = authority.path.split("/")
183198
first_part = parts[1] if len(parts) >= 2 and parts[1] else None
184199
if authority.hostname.endswith(_CIAM_DOMAIN_SUFFIX): # CIAM

0 commit comments

Comments
 (0)