Use Azure Access Token in Web API to retrieve Azure Secret

595 Views Asked by At

I am developing a Website using Azure AD authentication. Users login using their Azure AD credential. When a website action is invoked by the users, the web front end (Angular) calls a Web API end point (.Net 6), passing the Azure Access Token to the Web API. The end point then makes a call to Azure Key Vault to retrieve a secret, and then do other work.

Currently, I am able to make the Web API retrieve Key Vault Secret using Azure Service Principal via using ClientSecretCredential

var credential = new ClientSecretCredential(TenantId, ClientId, ClientSecret);
var client = new SecretClient(new Uri(VaultName), credential);
var success = await client.SetSecretAsync(secretName, value);

The code works well, but I'd like to use the login user's credential instead of the service principal account to retrieve the vault secret instead. The Web API only receives an Access Token, so, I am trying to construct a Azure.Core.TokenCredential object from the access token but to no avail. None of the classes that are derived from Azure.Core.TokenCredentialin the documentation have a constructor that can do that.

Both the Web front-end and Web API are hosted outside of Azure. Can anyone shed some lights on how to achieve my goal?

Azure.Identity.AuthorizationCodeCredential
Azure.Identity.AzureCliCredential
Azure.Identity.AzureDeveloperCliCredential
Azure.Identity.AzurePowerShellCredential
Azure.Identity.ChainedTokenCredential
Azure.Identity.ClientAssertionCredential
Azure.Identity.ClientCertificateCredential
Azure.Identity.ClientSecretCredential
Azure.Identity.DefaultAzureCredential
Azure.Identity.DeviceCodeCredential
Azure.Identity.EnvironmentCredential
Azure.Identity.InteractiveBrowserCredential
Azure.Identity.ManagedIdentityCredential
Azure.Identity.OnBehalfOfCredential
Azure.Identity.SharedTokenCacheCredential
Azure.Identity.UsernamePasswordCredential
Azure.Identity.VisualStudioCodeCredential
Azure.Identity.VisualStudioCredential
Azure.Identity.WorkloadIdentityCredential

Thanks a lot.

1

There are 1 best solutions below

0
SaiVamshiKrishna On

Here is the way I am able to retrieve the key vault secret by following methods

Method-1 : Using Azure.Identity.DefaultAzureCredential

Configured appsetting.json

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "microsoft.onmicrosoft.com",
    "TenantId": "*********-*********-****-***********",
    "ClientId": "*******-*******-*****-**********,
    "CallbackPath": "/signin-oidc",
    "ClientSecret": "********-******-*****-******",
    "Scopes": "User.Read",
    "ClientCertificates": []
  },
  "KeyVault": {
    "VaultUri": "https://YourKeyvault.vault.azure.net/"
  },

`Controller.cs

    [HttpGet]
    [Route("generate")]
    public ActionResult<string> GenerateToken(string secretName)
    {
        string keyVaultUri = _configuration["KeyVault:VaultUri"];
        var client = new SecretClient(new Uri(keyVaultUri), new DefaultAzureCredential());

        try
        {
            KeyVaultSecret secret = client.GetSecret(secretName);
            return Ok(secret.Value);
        }
        catch (RequestFailedException ex)
        {
            return BadRequest(ex.Message);
        }
    }

Result

Stored Secret Name in Vault enter image description here

enter image description here

Method-2 : Using Azure.Identity.OnBehalfOfCredential

Thanks for @Stephen Cleary comments

As Per the Azure.Identity, OnBehalfOfCredential expects clientSecret also as an argument to be passed

Controller.cs

    [HttpGet("{secretName}")]
    public IActionResult GetSecret(string secretName)
    {
        try
        {
            var keyVaultUri = new Uri(_configuration["KeyVault:VaultUri"]);
            var userAccessToken = HttpContext.GetTokenAsync("access_token").Result;

            // Create an OnBehalfOfCredential
            var onBehalfOfCredential = new OnBehalfOfCredential("tenantId", "clientId", "clientsecret",
                userAccessToken);
            var client = new SecretClient(keyVaultUri, onBehalfOfCredential);
            var secret = client.GetSecret(secretName);
            return Ok(secret.Value.Value);
        }
        catch (Exception ex)
        {
            return BadRequest($"Error: {ex.Message}");
        }
    }

Result enter image description here