0

I have two application registrations: one for the backend and one for the frontend.

On the backend App Reg, I have defined (exposed) a scope called User_impersonation like the following:

enter image description here

On the frontend App Reg, I have added the permissions (User_impersonation) like the following:

enter image description here

Also on the frontend side, I enabled user/group assignment and assigned a security group; so that only the members of that security group can access/query this frontend.

enter image description here

So far, when a user queries the frontend with an access token (requested from the frontend app reg); everything works fine: the frontend app reg requests an access token from the backend and forwards the request of the user.

However, when I try to enable the user/group assignment on the backend app reg (by adding the same security group); the frontend app can no longer query the backend (User_impersonation fails); like the query times out with no reply from the backend.

Can someone help me make the User_impersonation work when the group assignment is enabled on both app regs (not only the frontend). Thanks.

This is how the client/user requests access to the webapp/frontend:


from azure.identity import DefaultAzureCredential, ClientSecretCredential

authority="https://login.microsoftonline.com/{TENANT_ID}/v2.0"

credential = DefaultAzureCredential(authority=authority, exclude_shared_token_cache_credential=True)
scope = "api://{frontend_clientid}/.default"
minerva_webapp_access_token = credential.get_token(scope).token

and this is how the webapp/frontend requests access to the backend app reg:


credential = ClientSecretCredential(
    tenant_id=TENANT_ID,
    client_id=WEBAPP_CLIENT_ID,
    client_secret=webapp_client_secret)
scope = (                "api://{minerva_python39_backend_app_client_id}/.default".format(
                        minerva_python39_backend_app_client_id=MINERVA_PYTHON39_CLIENTID))

access_token = credential.get_token(scope).token

Aniss Chohra
  • 391
  • 4
  • 18
  • Could you include what authentication flow you are using to request access token like authorization code flow or implicit flow? – Sridevi Sep 01 '23 at 12:24
  • I am using Python Azure-Identity to request the access token; I included code sample in the question – Aniss Chohra Sep 01 '23 at 14:38

1 Answers1

1

Note that, client credentials flow works only with permissions of Application type. This flow won't work with User_impersonation as it is Delegated permission.

I registered 2 applications in my Azure AD tenant same as you: one for the backend and one for the frontend.

On the Backend application, I defined (exposed) User_impersonation scope like below:

enter image description here

On the Frontend application, I added User_impersonation API permission:

enter image description here

Now, I generated access token using client credentials with same code as you like below:

credential = ClientSecretCredential(
    tenant_id=TENANT_ID,
    client_id=WEBAPP_CLIENT_ID,
    client_secret=webapp_client_secret)
scope = (                "api://{minerva_python39_backend_app_client_id}/.default".format(
                        minerva_python39_backend_app_client_id=MINERVA_PYTHON39_CLIENTID))

access_token = credential.get_token(scope).token
print(access_token)

Response:

enter image description here

When I decode the token by pasting it in jwt.ms, it has right audience in aud but missing scp claim like below:

enter image description here

To make User_impersonation work when the group assignment is enabled on both app regs, your access token should have scp claim with that specific permission.

For that, you need to use Delegated flows like authorization code flow, interactive flow, username password flow etc... for generating tokens.

In my case, I used authorization code flow to generate access token for which code is needed. I ran below authorization request in browser and got code successfully in address bar:

https://login.microsoftonline.com/<tenantId>/oauth2/v2.0/authorize? 
client_id=<frontend_appId>
&redirect_uri=https://jwt.ms
&response_type=code  
&response_mode=query  
&scope= api://<backend_appID>/User_impersonation
&state=12345

Code:

enter image description here

I ran below python code and got access token using authorization code flow in response like this:

from azure.identity import AuthorizationCodeCredential

   credential = AuthorizationCodeCredential(
       tenant_id=TENANT_ID,
       client_id=WEBAPP_CLIENT_ID,
       authorization_code="<auth_code_from_above>",
       redirect_uri="https://jwt.ms",
   )

scope = ( "api://{minerva_python39_backend_app_client_id}/.default".format(
                        minerva_python39_backend_app_client_id=MINERVA_PYTHON39_CLIENTID))

access_token = credential.get_token(scope).token
print(access_token)

Response:

enter image description here

When I decode the token by pasting it in jwt.ms, it has right audience in aud and User_impersonation permission in scp claim like below:

enter image description here

In your case, decode whether the token has User_impersonation permission in scp claim and change to Delegated flows for generating token to access backend as I mentioned.

Sridevi
  • 10,599
  • 1
  • 4
  • 17