diff --git a/msal/application.py b/msal/application.py index 7e3ec16e..62ba4b5c 100644 --- a/msal/application.py +++ b/msal/application.py @@ -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) diff --git a/tests/test_application.py b/tests/test_application.py index 804ccb82..b62f41d5 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -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"]) + diff --git a/tests/test_e2e.py b/tests/test_e2e.py index 5c43f4f0..48ffe47a 100644 --- a/tests/test_e2e.py +++ b/tests/test_e2e.py @@ -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="b2clocal@msidlabb2c.onmicrosoft.com", + password=self.get_lab_user_secret("msidlabb2c"), + scope=config["scopes"], + ) + class WorldWideRegionalEndpointTestCase(LabBasedTestCase): region = "westus"