On-behalf-of flow for resources in other tenant than user's

Erik Post 70 Reputation points
2023-10-12T14:06:20.7233333+00:00

Hi, I have the following scenario:

  • tenant A contains users
  • tenant B has Azure resources (e.g. blob storage)
  • users from tenant A are invited as guest users in tenant B
  • access to the resources in tenant B is setup via RBAC

Say I would like to create a Nextjs app that allows users to sign in and list the files in blob storage. All API calls to Azure APIs are handled server side from the Nextjs app (either via React Server Components or Route Handlers).

If I understand correctly this would need On-behalf-of flow. And I got this working partially.

What happens in the app (based on the info in this @azure/identity sample):

  • user signs in via authorization code flow (with PKCE). For this purpose an App Registration has been created in tenant A. This App Registration has the basic Microsoft Graph delegated permissions (email, openid, profile, User.Read). The same App Registration also exposes an API with App ID URI api://{clientId}. A single scope has been defined (access_obo_user) and the client has been configured to be an authorized client of itself. Finally, this scope has also been added as a delegated API permission. Also in the manifest the client id has been added as a knownClientApplication.
  • sign in (via NextAuth) works perfectly fine. The scope used is openid profile email api://{clientId}/.default. This results in a valid ID token and access token with the scope defined in the Expose an API blade (access_obo_user).
  • before calling the Azure Storage API (via azure javascript SDK) I exchange this access token for a new one using the OnBehalfOfCredential. For this I use the client ID and secret from tenant A (the same as for the initial user sign in).

But then I call the BlobServiceClient.listContainers() function for a storage account in tenant B with the OnBehalfOf credential using azure storage sdk for javascript. This however leads to an error:

invalid_grant: AADSTS65001: The user or administrator has not consented to use the application with ID '<clientId>' named '<App Registration Name>'. Send an interactive authorization request for this user and resource.

As an alternative approach I tried to retrieve the token explicitly (via OnBehalfOfCredential.getToken with the scope api://<clientId>/.default) and then pass this retrieved token to the BlobServiceClient using a TokenCredential implementation that simply returns the previously retrieved token.

This leads to a different error:

Server failed to authenticate the request. Please refer to the information in the www-authenticate header.

The www-authenticate response header contains the following:

Bearer authorization_uri=https://login.microsoftonline.com/<tenant B guid>/oauth2/authorize resource_id=https://storage.azure.com

I was under the impression that no consent would be needed when this has been set up as described above. What am I missing and what is needed to get this scenario working?

Microsoft Entra ID
Microsoft Entra ID
A Microsoft Entra identity service that provides identity management and access control capabilities. Replaces Azure Active Directory.
24,165 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Shweta Mathur 30,271 Reputation points Microsoft Employee
    2023-10-18T12:01:32.2033333+00:00

    Hi @Erik Post ,

    Thanks for reaching out.

    I understand that you want to authenticate your guest users in tenant B and access the resources of tenant B.

    I am not sure why you are using On- Behalf-Of-Here. What is the need for Graph API permissions in this scenario.

    Could you please brief the purpose of that.

    However, it is not possible to get access token for both Microsoft Graph and protected API in one request. The Microsoft identity platform does not allow you to get a token for several resources at once.

    In your scenario, you can invite Tenant A users as guest to Tenant B and to grant access to Azure resources for users external to an organization, you can use Azure role-based access control (Azure RBAC) and the capabilities in Azure Active Directory B2B collaboration.

    Once guest users have access to resources in your tenant , they call call the resources in Tenant B like other members of Tenant B.

    Reference sample to authenticate users and authorize them to call Storage resource.

    https://github.com/Azure-Samples/ms-identity-javascript-react-tutorial/tree/main/2-Authorization-I/2-call-arm

    Hope this will help.

    Thanks,

    Shweta


    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.