Skip to content

Commit 6c84adf

Browse files
committed
Adds dSTS authority (as if it were an oidc_authority)
1 parent 6508d99 commit 6c84adf

File tree

2 files changed

+45
-10
lines changed

2 files changed

+45
-10
lines changed

msal/application.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import warnings
77
from threading import Lock
88
from typing import Optional # Needed in Python 3.7 & 3.8
9+
from urllib.parse import urlparse
910
import os
1011

1112
from .oauth2cli import Client, JwtAssertionCreator
@@ -622,6 +623,9 @@ def __init__(
622623
# Here the self.authority will not be the same type as authority in input
623624
if oidc_authority and authority:
624625
raise ValueError("You can not provide both authority and oidc_authority")
626+
if isinstance(authority, str) and urlparse(authority).path.startswith(
627+
"/dstsv2"): # dSTS authority's path always starts with "/dstsv2"
628+
oidc_authority = authority # So we treat it as if an oidc_authority
625629
try:
626630
authority_to_use = authority or "https://{}/common/".format(WORLD_WIDE)
627631
self.authority = Authority(

tests/test_authority.py

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -104,32 +104,63 @@ def test_authority_with_path_should_be_used_as_is(self, oidc_discovery):
104104
"authorization_endpoint": "https://contoso.com/authorize",
105105
"token_endpoint": "https://contoso.com/token",
106106
})
107-
class TestOidcAuthority(unittest.TestCase):
107+
class OidcAuthorityTestCase(unittest.TestCase):
108+
authority = "https://contoso.com/tenant"
109+
110+
def setUp(self):
111+
# setUp() gives subclass a dynamic setup based on their authority
112+
self.oidc_discovery_endpoint = (
113+
# MSAL Python always does OIDC Discovery,
114+
# not to be confused with Instance Discovery
115+
# Here the test is to confirm the OIDC endpoint contains no "/v2.0"
116+
self.authority + "/.well-known/openid-configuration")
117+
108118
def test_authority_obj_should_do_oidc_discovery_and_skip_instance_discovery(
109119
self, oidc_discovery, instance_discovery):
110120
c = MinimalHttpClient()
111-
a = Authority(None, c, oidc_authority_url="https://contoso.com/tenant")
121+
a = Authority(None, c, oidc_authority_url=self.authority)
112122
instance_discovery.assert_not_called()
113-
oidc_discovery.assert_called_once_with(
114-
"https://contoso.com/tenant/.well-known/openid-configuration", c)
123+
oidc_discovery.assert_called_once_with(self.oidc_discovery_endpoint, c)
115124
self.assertEqual(a.authorization_endpoint, 'https://contoso.com/authorize')
116125
self.assertEqual(a.token_endpoint, 'https://contoso.com/token')
117126

118127
def test_application_obj_should_do_oidc_discovery_and_skip_instance_discovery(
119128
self, oidc_discovery, instance_discovery):
120129
app = msal.ClientApplication(
121-
"id",
122-
authority=None,
123-
oidc_authority="https://contoso.com/tenant",
124-
)
130+
"id", authority=None, oidc_authority=self.authority)
125131
instance_discovery.assert_not_called()
126132
oidc_discovery.assert_called_once_with(
127-
"https://contoso.com/tenant/.well-known/openid-configuration",
128-
app.http_client)
133+
self.oidc_discovery_endpoint, app.http_client)
129134
self.assertEqual(
130135
app.authority.authorization_endpoint, 'https://contoso.com/authorize')
131136
self.assertEqual(app.authority.token_endpoint, 'https://contoso.com/token')
132137

138+
139+
class DstsAuthorityTestCase(OidcAuthorityTestCase):
140+
# Inherits OidcAuthority's test cases and run them with a dSTS authority
141+
authority = ( # dSTS is single tenanted with a tenant placeholder
142+
'https://test-instance1-dsts.dsts.core.azure-test.net/dstsv2/common')
143+
authorization_endpoint = (
144+
"https://some.url.dsts.core.azure-test.net/dstsv2/common/oauth2/authorize")
145+
token_endpoint = (
146+
"https://some.url.dsts.core.azure-test.net/dstsv2/common/oauth2/token")
147+
148+
@patch("msal.authority._instance_discovery")
149+
@patch("msal.authority.tenant_discovery", return_value={
150+
"authorization_endpoint": authorization_endpoint,
151+
"token_endpoint": token_endpoint,
152+
}) # We need to create new patches (i.e. mocks) for non-inherited test cases
153+
def test_application_obj_should_accept_dsts_url_as_an_authority(
154+
self, oidc_discovery, instance_discovery):
155+
app = msal.ClientApplication("id", authority=self.authority)
156+
instance_discovery.assert_not_called()
157+
oidc_discovery.assert_called_once_with(
158+
self.oidc_discovery_endpoint, app.http_client)
159+
self.assertEqual(
160+
app.authority.authorization_endpoint, self.authorization_endpoint)
161+
self.assertEqual(app.authority.token_endpoint, self.token_endpoint)
162+
163+
133164
class TestAuthorityInternalHelperCanonicalize(unittest.TestCase):
134165

135166
def test_canonicalize_tenant_followed_by_extra_paths(self):

0 commit comments

Comments
 (0)