AzureAD / microsoft-identity-web

Helps creating protected web apps and web APIs with Microsoft identity platform and Azure AD B2C
MIT License
665 stars 204 forks source link

[Feature Request] Add support for ITokenAcquisition and debugging locally with Managed Identity #2895

Open SWarnberg opened 1 month ago

SWarnberg commented 1 month ago

Reading the documentation in Calling APIs with Managed Identity, you get the impression that it would be possible to use the id web library instead of Azure.Identity for getting tokens with Managed Identity. However, it doesn't seem to work when debugging locally in Visual Studio, as DefaultAzureCredentials do. Is it supposed to work?

Also, the solution and documentation is only focused on console applications, using IDownstreamApi. A more relevant example would be for a Web Api that calls a Web Api with ITokenAcquisition, since there are more suitable strongly typed proxy clients, like Refit. But that doesn't seem to work either?

In my mind, the configuration in "AzureAd" would have a setting for ManagedIdentity, and not in the "downstream api" section. Currently, it only supports federated clients with user assigned MI's.

Getting a token in code works, when deployed in Azure, with the parameter tokenAcquisitionOptions, but since it doesn't work when debugging it won't be pretty, and you would like it to be configurable in appsettings (if you'd like to do ClientCredentials locally for instance).

string token = await _tokenAcquisition.GetAccessTokenForAppAsync("api://{api-uri}/.default",
  tokenAcquisitionOptions: new TokenAcquisitionOptions { ManagedIdentity = new() });
Ukkie007 commented 2 weeks ago

Testing locally is definitely necessary. If an upstream api 'has' a managed identity and the downstream api has an app registration with an app role (i.e. 'ManagedIdRole') and the Managed Identity (Enterprise app) has permissions to the ManagedIdRole, I'd expect to have an appsettings.json with the App (Client) Id of the downstreamapi to acquire the tokens.

jmprieur commented 2 weeks ago

Thanks for the feedback It's not the design that was chosen. The managed identity is not your app, and can only do limited client credentials for the moment, therefore we chose to expose it as an option of the token acquisition or DownstreamApi.

Because Managed identity is not available locally, I would recommend you use FIC+MSI instead and have 2 credential descriptions in your ClientCredentials collection:

   "ClientCredentials": [
    {
       "SourceType": "SignedAssertionFromManagedIdentity",
       "ManagedIdentityClientId": "GUID"
   },
   {
       "SourceType": "KeyVault",
       "KeyVaultUrl": "https://msidlabs.vault.azure.net/",
       "KeyVaultCertificateName": "IDLABS-APP-Confidential-Client-Cert"
     }
    ],
SWarnberg commented 1 week ago

Hi

As I wrote, I could cope with clientcredentials while debugging (secret or certificate) and MSI when deployed, using different appsettings files. So, with appsettings.Development.json containing SourceType ClientSecret or KeyVault and appsettings.json containing MSI only. This should mean that I can use the same code when acquiring the token:

string token = await _tokenAcquisition.GetAccessTokenForAppAsync("api://{guid}/.default");

However, it doesn't work. When using above code, I get the error:

{"statusCode":400,"message":"No User Assigned or Delegated Managed Identity found for specified ClientId/ResourceId/PrincipalId.","correlationId":"19b96155-11ea-451f-9194-4e38ed69ede3"}

But with the tokenAcquisitionOptions it works.

In your sample above @jmprieur you also have an undocumented setting, ManagedIdentityClientId (the referred documentation has another pattern). That is for user-assigned identities, right? So, with system-assigned identities it should be skipped.

SWarnberg commented 1 week ago

Note, I don't want to use user-assigned identities or FIC.