Reputation: 195
I'm working on web application that contains client side (SPA, angular 9) and backend (WebAPI, ASP.NET Core 3.0). Decided to use Application Roles feature to authorize users in our application. And i have requirement to be able to manage Application role assignments for users from our application UI via MSFT Graph API.
Authentication works fine. Client side gets token and attaches it to http requests to backend. Authorization also works fine i can extract app roles from the token and validate them.
Problem with adding Application role assignments for users from other AzureAD tenant -- TenantB. Seems that problem in GraphServiceClient configuration due to GraphApiAuth registered in TenantA.
Question: is this possible to add application role assignment for user from TenantB using GraphServiceClient authorized by Client Credentials in TenantA? Right now when i do add role assignment i'm getting exception like resource with some Guid not found. This resource is a user (from TenantB). This is a piece of code that adds user app role assignment. I see possible problem in GetGraphServiceClient function. It uses as authority URL with TenantA Id.
public async Task<AppRoleAssignment> AssignAppRoleToUser(Guid userId, Guid appRoleId)
{
var graphClient = await this.graphClientProvider.GetGraphServiceClient();
return await graphClient.Users[userId.ToString()].AppRoleAssignments.Request().AddAsync(
new AppRoleAssignment()
{
PrincipalId = userId,
AppRoleId = appRoleId,
ResourceId = this.graphAppSettingsProvider.GetAppRoleResourceIdAsGuid()
});
}
df0b3e71-fd2d-41a4-bfa9-0310b31395ae is Id of user from tenantB.
UPDATE:After further investigation i was able to assign App role for user from TenantB. But i had to change settings in the code that returns GraphServiceClient and provide TenantB Id and Application Service Principal Id from TenantB (instead of values from TenantA). But that's a problem. We would like to be able to assign application roles for users from any tenant and it will be not doable if we will have to provide TenantId and Service Principal Id for each tenant separately. Is it possible to do this some how with some common settings? This is how i get GraphServiceClient:
public async Task<GraphServiceClient> GetGraphServiceClient()
{
var clientId = this.graphAppSettingsProvider.GetClientId();
var clientSecret = this.graphAppSettingsProvider.GetClientSecret();
var tenantId = this.graphAppSettingsProvider.GetTenant();
var app = ConfidentialClientApplicationBuilder.Create(clientId)
.WithClientSecret(clientSecret)
.WithTenantId(tenantId)
.Build();
string[] scopes = {"https://graph.microsoft.com/.default"};
return new GraphServiceClient(
"https://graph.microsoft.com/v1.0",
new DelegateAuthenticationProvider((requestMessage) =>
{
var ar = app.AcquireTokenForClient(scopes).ExecuteAsync();
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", ar.Result.AccessToken);
return Task.FromResult(0);
}));
}
UPDATE 2 Changed a little requirements and now we just need to manage App Roles list for users from current user tenant. So, we changed permissions type from Application to Delegated to be behalf of authenticated user. As i said earlier we have Angular app in pair with ASP.NET Core WebAPI backend. Angular app gets access token and sends it to backend in Authorizaiton header. When i attach with access token to GraphServiceClient request (header) i'm getting error "Access token validation failure. Invalid audience." Question: is this correct flow to use access token from client for Graph API requests or should i get new access token for Graph API at backend using access token from client?
Any help/ideas appreciated. Thanks in advance!
Upvotes: 0
Views: 1999
Reputation: 9549
First, you need to set up the MyAuthApp application as a multi-tenant application.
Next, run admin consent url in the browser, and then you need to log in with another tenant's administrator account and consent. The multi-tenant application will then be added to the target tenant as an enterprise application. https://login.microsoftonline.com/common/adminconsent?client_id={client-id}
.
At the same time, the app role you created in tenant A will also be synchronized to the target tenant (for example, tenant B). Next, you only need to grant the app role of MyAuthApp to the users of tenant B through the Azure portal of tenant B or use ms graph api.
Upvotes: 0