Add OIDC issuer validation #840
Build #20251218.4 had test failures
Details
- Failed: 120 (7.19%)
- Passed: 1,272 (76.26%)
- Other: 276 (16.55%)
- Total: 1,668
Annotations
Check failure on line 85 in Build log
azure-pipelines / AzureAD.microsoft-authentication-library-for-python (2708)
Build log #L85
20 test(s) failed, 278 test(s) collected.
Check failure on line 1797 in Build log
azure-pipelines / AzureAD.microsoft-authentication-library-for-python (2708)
Build log #L1797
Bash exited with code '1'.
Check failure on line 85 in Build log
azure-pipelines / AzureAD.microsoft-authentication-library-for-python (2708)
Build log #L85
20 test(s) failed, 278 test(s) collected.
Check failure on line 1797 in Build log
azure-pipelines / AzureAD.microsoft-authentication-library-for-python (2708)
Build log #L1797
Bash exited with code '1'.
azure-pipelines / AzureAD.microsoft-authentication-library-for-python (2708)
tests/test_authority.py::TestAuthorityIssuerValidation::test_ciam_authority_with_host_tenant
self = <tests.test_authority.TestAuthorityIssuerValidation testMethod=test_ciam_authority_with_host_tenant>
tenant_discovery_mock = <MagicMock name='tenant_discovery' id='140210544550160'>
@patch("msal.authority.tenant_discovery")
def test_ciam_authority_with_host_tenant(self, tenant_discovery_mock):
"""Test CIAM authority with tenant in hostname"""
tenant_name = "tenant_name"
authority_url = f"https://{tenant_name}{_CIAM_DOMAIN_SUFFIX}/custom/path"
issuer = f"https://{tenant_name}{_CIAM_DOMAIN_SUFFIX}"
> authority = self._create_authority_with_issuer(authority_url, issuer, tenant_discovery_mock)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_authority.py:386:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/test_authority.py:336: in _create_authority_with_issuer
authority = Authority(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <msal.authority.Authority object at 0x7f854fb38710>, authority_url = None
http_client = <tests.http_client.MinimalHttpClient object at 0x7f854fb38d90>
validate_authority = True, instance_discovery = None
oidc_authority_url = 'https://tenant_name.ciamlogin.com/custom/path'
def __init__(
self, authority_url, http_client,
validate_authority=True,
instance_discovery=None,
oidc_authority_url=None,
):
"""Creates an authority instance, and also validates it.
:param validate_authority:
The Authority validation process actually checks two parts:
instance (a.k.a. host) and tenant. We always do a tenant discovery.
This parameter only controls whether an instance discovery will be
performed.
"""
self._http_client = http_client
self._oidc_authority_url = oidc_authority_url
if oidc_authority_url:
logger.debug("Initializing with OIDC authority: %s", oidc_authority_url)
tenant_discovery_endpoint = self._initialize_oidc_authority(
oidc_authority_url)
else:
logger.debug("Initializing with Entra authority: %s", authority_url)
tenant_discovery_endpoint = self._initialize_entra_authority(
authority_url, validate_authority, instance_discovery)
try:
openid_config = tenant_discovery(
tenant_discovery_endpoint,
self._http_client)
except ValueError:
error_message = (
"Unable to get OIDC authority configuration for {url} "
"because its OIDC Discovery endpoint is unavailable at "
"{url}/.well-known/openid-configuration ".format(url=oidc_authority_url)
if oidc_authority_url else
"Unable to get authority configuration for {}. "
"Authority would typically be in a format of "
"https://login.microsoftonline.com/your_tenant "
"or https://tenant_name.ciamlogin.com "
"or https://tenant_name.b2clogin.com/tenant.onmicrosoft.com/policy. "
.format(authority_url)
) + " Also please double check your tenant name or GUID is correct."
raise ValueError(error_message)
openid_config.pop("issuer", None) # Not used in MSAL.py, so remove it therefore no need to validate it
logger.debug(
'openid_config("%s") = %s', tenant_discovery_endpoint, openid_config)
self._issuer = openid_config.get('issuer')
self.authorization_endpoint = openid_config['authorization_endpoint']
self.token_endpoint = openid_config['token_endpoint']
self.device_authorization_endpoint = openid_config.get('device_authorization_endpoint')
_, _, self.tenant = canonicalize(self.token_endpoint
Raw output
/home/vsts/work/1/s/msal/authority.py:128: ValueError: The issuer 'None' does not match the authority 'https://tenant_name.ciamlogin.com/custom/path' or a known pattern. When using the 'oidc_authority' parameter in ClientApplication, the authority will be validated against the issuer from https://tenant_name.ciamlogin.com/custom/path/.well-known/openid-configuration .If using a known Entra authority (e.g. login.microsoftonline.com) the 'authority' parameter should be used instead of 'oidc_authority'.
azure-pipelines / AzureAD.microsoft-authentication-library-for-python (2708)
tests/test_authority.py::TestAuthorityIssuerValidation::test_ciam_authority_with_matching_tenant
self = <tests.test_authority.TestAuthorityIssuerValidation testMethod=test_ciam_authority_with_matching_tenant>
tenant_discovery_mock = <MagicMock name='tenant_discovery' id='140210576540304'>
@patch("msal.authority.tenant_discovery")
def test_ciam_authority_with_matching_tenant(self, tenant_discovery_mock):
"""Test CIAM authority with matching tenant in path"""
authority_url = "https://custom-domain.com/tenant_name"
issuer = f"https://tenant_name{_CIAM_DOMAIN_SUFFIX}"
> authority = self._create_authority_with_issuer(authority_url, issuer, tenant_discovery_mock)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_authority.py:377:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/test_authority.py:336: in _create_authority_with_issuer
authority = Authority(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <msal.authority.Authority object at 0x7f85519be810>, authority_url = None
http_client = <tests.http_client.MinimalHttpClient object at 0x7f85519bdad0>
validate_authority = True, instance_discovery = None
oidc_authority_url = 'https://custom-domain.com/tenant_name'
def __init__(
self, authority_url, http_client,
validate_authority=True,
instance_discovery=None,
oidc_authority_url=None,
):
"""Creates an authority instance, and also validates it.
:param validate_authority:
The Authority validation process actually checks two parts:
instance (a.k.a. host) and tenant. We always do a tenant discovery.
This parameter only controls whether an instance discovery will be
performed.
"""
self._http_client = http_client
self._oidc_authority_url = oidc_authority_url
if oidc_authority_url:
logger.debug("Initializing with OIDC authority: %s", oidc_authority_url)
tenant_discovery_endpoint = self._initialize_oidc_authority(
oidc_authority_url)
else:
logger.debug("Initializing with Entra authority: %s", authority_url)
tenant_discovery_endpoint = self._initialize_entra_authority(
authority_url, validate_authority, instance_discovery)
try:
openid_config = tenant_discovery(
tenant_discovery_endpoint,
self._http_client)
except ValueError:
error_message = (
"Unable to get OIDC authority configuration for {url} "
"because its OIDC Discovery endpoint is unavailable at "
"{url}/.well-known/openid-configuration ".format(url=oidc_authority_url)
if oidc_authority_url else
"Unable to get authority configuration for {}. "
"Authority would typically be in a format of "
"https://login.microsoftonline.com/your_tenant "
"or https://tenant_name.ciamlogin.com "
"or https://tenant_name.b2clogin.com/tenant.onmicrosoft.com/policy. "
.format(authority_url)
) + " Also please double check your tenant name or GUID is correct."
raise ValueError(error_message)
openid_config.pop("issuer", None) # Not used in MSAL.py, so remove it therefore no need to validate it
logger.debug(
'openid_config("%s") = %s', tenant_discovery_endpoint, openid_config)
self._issuer = openid_config.get('issuer')
self.authorization_endpoint = openid_config['authorization_endpoint']
self.token_endpoint = openid_config['token_endpoint']
self.device_authorization_endpoint = openid_config.get('device_authorization_endpoint')
_, _, self.tenant = canonicalize(self.token_endpoint) # Usually a GUID
# Validate the iss
Raw output
/home/vsts/work/1/s/msal/authority.py:128: ValueError: The issuer 'None' does not match the authority 'https://custom-domain.com/tenant_name' or a known pattern. When using the 'oidc_authority' parameter in ClientApplication, the authority will be validated against the issuer from https://custom-domain.com/tenant_name/.well-known/openid-configuration .If using a known Entra authority (e.g. login.microsoftonline.com) the 'authority' parameter should be used instead of 'oidc_authority'.
azure-pipelines / AzureAD.microsoft-authentication-library-for-python (2708)
tests/test_authority.py::TestAuthorityIssuerValidation::test_exact_match_issuer
self = <tests.test_authority.TestAuthorityIssuerValidation testMethod=test_exact_match_issuer>
tenant_discovery_mock = <MagicMock name='tenant_discovery' id='140210576282896'>
@patch("msal.authority.tenant_discovery")
def test_exact_match_issuer(self, tenant_discovery_mock):
"""Test when issuer exactly matches the OIDC authority URL"""
authority_url = "https://example.com/tenant"
> authority = self._create_authority_with_issuer(authority_url, authority_url, tenant_discovery_mock)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_authority.py:347:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/test_authority.py:336: in _create_authority_with_issuer
authority = Authority(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <msal.authority.Authority object at 0x7f855197d090>, authority_url = None
http_client = <tests.http_client.MinimalHttpClient object at 0x7f855197c550>
validate_authority = True, instance_discovery = None
oidc_authority_url = 'https://example.com/tenant'
def __init__(
self, authority_url, http_client,
validate_authority=True,
instance_discovery=None,
oidc_authority_url=None,
):
"""Creates an authority instance, and also validates it.
:param validate_authority:
The Authority validation process actually checks two parts:
instance (a.k.a. host) and tenant. We always do a tenant discovery.
This parameter only controls whether an instance discovery will be
performed.
"""
self._http_client = http_client
self._oidc_authority_url = oidc_authority_url
if oidc_authority_url:
logger.debug("Initializing with OIDC authority: %s", oidc_authority_url)
tenant_discovery_endpoint = self._initialize_oidc_authority(
oidc_authority_url)
else:
logger.debug("Initializing with Entra authority: %s", authority_url)
tenant_discovery_endpoint = self._initialize_entra_authority(
authority_url, validate_authority, instance_discovery)
try:
openid_config = tenant_discovery(
tenant_discovery_endpoint,
self._http_client)
except ValueError:
error_message = (
"Unable to get OIDC authority configuration for {url} "
"because its OIDC Discovery endpoint is unavailable at "
"{url}/.well-known/openid-configuration ".format(url=oidc_authority_url)
if oidc_authority_url else
"Unable to get authority configuration for {}. "
"Authority would typically be in a format of "
"https://login.microsoftonline.com/your_tenant "
"or https://tenant_name.ciamlogin.com "
"or https://tenant_name.b2clogin.com/tenant.onmicrosoft.com/policy. "
.format(authority_url)
) + " Also please double check your tenant name or GUID is correct."
raise ValueError(error_message)
openid_config.pop("issuer", None) # Not used in MSAL.py, so remove it therefore no need to validate it
logger.debug(
'openid_config("%s") = %s', tenant_discovery_endpoint, openid_config)
self._issuer = openid_config.get('issuer')
self.authorization_endpoint = openid_config['authorization_endpoint']
self.token_endpoint = openid_config['token_endpoint']
self.device_authorization_endpoint = openid_config.get('device_authorization_endpoint')
_, _, self.tenant = canonicalize(self.token_endpoint) # Usually a GUID
# Validate the issuer if using OIDC authority
if self._oidc_authority_url and not self.has_valid_issuer():
Raw output
/home/vsts/work/1/s/msal/authority.py:128: ValueError: The issuer 'None' does not match the authority 'https://example.com/tenant' or a known pattern. When using the 'oidc_authority' parameter in ClientApplication, the authority will be validated against the issuer from https://example.com/tenant/.well-known/openid-configuration .If using a known Entra authority (e.g. login.microsoftonline.com) the 'authority' parameter should be used instead of 'oidc_authority'.
azure-pipelines / AzureAD.microsoft-authentication-library-for-python (2708)
tests/test_authority.py::TestAuthorityIssuerValidation::test_custom_authority_with_microsoft_issuer
self = <tests.test_authority.TestAuthorityIssuerValidation testMethod=test_custom_authority_with_microsoft_issuer>
tenant_discovery_mock = <MagicMock name='tenant_discovery' id='140210575795600'>
@patch("msal.authority.tenant_discovery")
def test_custom_authority_with_microsoft_issuer(self, tenant_discovery_mock):
"""Test when custom authority is used with a known Microsoft issuer (should succeed)"""
authority_url = "https://custom-domain.com/tenant"
issuer = f"https://{WORLD_WIDE}/tenant"
> authority = self._create_authority_with_issuer(authority_url, issuer, tenant_discovery_mock)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_authority.py:411:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/test_authority.py:336: in _create_authority_with_issuer
authority = Authority(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <msal.authority.Authority object at 0x7f8551907b90>, authority_url = None
http_client = <tests.http_client.MinimalHttpClient object at 0x7f85519064d0>
validate_authority = True, instance_discovery = None
oidc_authority_url = 'https://custom-domain.com/tenant'
def __init__(
self, authority_url, http_client,
validate_authority=True,
instance_discovery=None,
oidc_authority_url=None,
):
"""Creates an authority instance, and also validates it.
:param validate_authority:
The Authority validation process actually checks two parts:
instance (a.k.a. host) and tenant. We always do a tenant discovery.
This parameter only controls whether an instance discovery will be
performed.
"""
self._http_client = http_client
self._oidc_authority_url = oidc_authority_url
if oidc_authority_url:
logger.debug("Initializing with OIDC authority: %s", oidc_authority_url)
tenant_discovery_endpoint = self._initialize_oidc_authority(
oidc_authority_url)
else:
logger.debug("Initializing with Entra authority: %s", authority_url)
tenant_discovery_endpoint = self._initialize_entra_authority(
authority_url, validate_authority, instance_discovery)
try:
openid_config = tenant_discovery(
tenant_discovery_endpoint,
self._http_client)
except ValueError:
error_message = (
"Unable to get OIDC authority configuration for {url} "
"because its OIDC Discovery endpoint is unavailable at "
"{url}/.well-known/openid-configuration ".format(url=oidc_authority_url)
if oidc_authority_url else
"Unable to get authority configuration for {}. "
"Authority would typically be in a format of "
"https://login.microsoftonline.com/your_tenant "
"or https://tenant_name.ciamlogin.com "
"or https://tenant_name.b2clogin.com/tenant.onmicrosoft.com/policy. "
.format(authority_url)
) + " Also please double check your tenant name or GUID is correct."
raise ValueError(error_message)
openid_config.pop("issuer", None) # Not used in MSAL.py, so remove it therefore no need to validate it
logger.debug(
'openid_config("%s") = %s', tenant_discovery_endpoint, openid_config)
self._issuer = openid_config.get('issuer')
self.authorization_endpoint = openid_config['authorization_endpoint']
self.token_endpoint = openid_config['token_endpoint']
self.device_authorization_endpoint = openid_config.get('device_authorization_endpoint')
_, _, self.tenant = canonicalize(self.token_endpoint) # Usually a GUID
#
Raw output
/home/vsts/work/1/s/msal/authority.py:128: ValueError: The issuer 'None' does not match the authority 'https://custom-domain.com/tenant' or a known pattern. When using the 'oidc_authority' parameter in ClientApplication, the authority will be validated against the issuer from https://custom-domain.com/tenant/.well-known/openid-configuration .If using a known Entra authority (e.g. login.microsoftonline.com) the 'authority' parameter should be used instead of 'oidc_authority'.