Search code examples
c#authenticationazure-active-directoryazure-managed-identityazure-appservice

Allow App Service to be called by just a test user and another App Service using a system assigned managed identity


I have an app service, let's call it Shiny API. It exposes functionality to my clients. Users authenticate using oAuth through a third party identity provider.

One of the data sources for this app service is in another app service within the same Azure tenant. Let's call it Legacy

I've decided to expose some of the functionality of Legacy which I'm exposing through an API I've added for this purpose: Legacy API.

So Legacy API may only be called by our development team (for testing and trouble shooting purposes) and by Shiny API. Its callers are "trusted".

In the old world, I would have configured IIS to use Windows Authentication, using a group managed account. The Azure equivalent is a System Assigned Managed Identity.

I think the client code in Shiny API needs to be a bit like this, but I cannot seem to find the correct way to configure Legacy API

// In Shiny API. 
// Used to authenticate to Legacy API
private async Task Authenticate(HttpClient httpClient)
{
    var NcoLegacyApiApplicationId = "<The Legacy API Client ID Guid>";
    var creds = new DefaultAzureCredential();
    var token = await creds.GetTokenAsync(new TokenRequestContext(new[] { NcoLegacyApiApplicationId }));
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.Token);
}

What do I have to do to allow only certain active directory users and Shiny API to access Legacy API?

I've tried a few things, but they led nowhere:

  • Do I need to do something in the Legacy API code, or can I do this with configuration only?
  • I configured a Microsoft Identity Provider under authentication. But there, I can only add human active directory users; the Shiny API system assigned identity was not available there. How do I authorize Shiny API?
  • I've also created an app registration for the legacy app. Is this neccessary?
  • Would using gRPC instead of REST solve anything?

Solution

  • I've found out how to do it:

    1. Create a managed identity for Shiny* (Write down the Object (principal) ID)

    2. Create an app registration for Legacy by adding 'Microsoft Authentication' in authentication. (Write down the App (client) ID)

    3. Go to the app registration. Choose app roles. Create an app role (e.g. Legacy.Access) (Write down the App role ID)

    4. Go to the Enterprise Application (in AAD). (Write down the Object ID)

    5. In properties, choose "Yes" for Assignment required

    6. In users and groups, add the users that have access. You want to see the ID from step 1 here too, but this cannot be done through UI.

    7. Assign the client application access by running in the cloud shell (powershell):

      $managedIdentityObjectId="(see step 1)"
      $appRoleId="(see step 3)"
      $serverServicePrincipalObjectId="(see step 4)"
      Connect-AzureAD
      New-AzureADServiceAppRoleAssignment `
           -ObjectId $managedIdentityObjectId `
           -Id $appRoleId `
           -PrincipalId $managedIdentityObjectId `
           -ResourceId $serverServicePrincipalObjectId
      
    8. Use the ID from step 3. to acquire a token in the Shiny application.