Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 3 additions & 12 deletions msal/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -588,18 +588,9 @@ def _decorate_scope(
raise ValueError(
"API does not accept {} value as user-provided scopes".format(
reserved_scope))
if self.client_id in scope_set:
if len(scope_set) > 1:
# We make developers pass their client id, so that they can express
# the intent that they want the token for themselves (their own
# app).
# If we do not restrict them to passing only client id then they
# could write code where they expect an id token but end up getting
# access_token.
raise ValueError("Client Id can only be provided as a single scope")
decorated = set(reserved_scope) # Make a writable copy
else:
decorated = scope_set | reserved_scope

# client_id can also be used as a scope in B2C
decorated = scope_set | reserved_scope
decorated -= self._exclude_scopes
return list(decorated)

Expand Down
15 changes: 15 additions & 0 deletions tests/test_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -625,3 +625,18 @@ def test_organizations_authority_should_emit_warnning(self):
self._test_certain_authority_should_emit_warnning(
authority="https://login.microsoftonline.com/organizations")


class TestScopeDecoration(unittest.TestCase):
def _test_client_id_should_be_a_valid_scope(self, client_id, other_scopes):
# B2C needs this https://learn.microsoft.com/en-us/azure/active-directory-b2c/access-tokens#openid-connect-scopes
reserved_scope = ['openid', 'profile', 'offline_access']
scopes_to_use = [client_id] + other_scopes
self.assertEqual(
set(ClientApplication(client_id)._decorate_scope(scopes_to_use)),
set(scopes_to_use + reserved_scope),
"Scope decoration should return input scopes plus reserved scopes")

def test_client_id_should_be_a_valid_scope(self):
self._test_client_id_should_be_a_valid_scope("client_id", [])
self._test_client_id_should_be_a_valid_scope("client_id", ["foo"])

12 changes: 12 additions & 0 deletions tests/test_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -884,6 +884,18 @@ def test_b2c_acquire_token_by_ropc(self):
scope=config["scopes"],
)

def test_b2c_allows_using_client_id_as_scope(self):
# See also https://learn.microsoft.com/en-us/azure/active-directory-b2c/access-tokens#openid-connect-scopes
config = self.get_lab_app_object(azureenvironment="azureb2ccloud")
config["scopes"] = [config["appId"]]
self._test_username_password(
authority=self._build_b2c_authority("B2C_1_ROPC_Auth"),
client_id=config["appId"],
username="[email protected]",
password=self.get_lab_user_secret("msidlabb2c"),
scope=config["scopes"],
)


class WorldWideRegionalEndpointTestCase(LabBasedTestCase):
region = "westus"
Expand Down