AskMe
AskMe

Reputation: 2583

How to get access token in Azure

I'm trying to fetch the secrets from the Azure key vault from .Net console application using REST API. Below is the code I'm trying to use for this from net.

Below way I'm trying to get access token and secret value:

 using Newtonsoft.Json;
 using System;
  using System.Net.Http;
  using System.Net.Http.Headers;
  using System.Text;
 using System.Text.Json;

 namespace KeyVaultSecretFetcher
 {
 class Program
 {
    static async Task Main(string[] args)
    {
        // Replace with your Key Vault URL, secret name, and authentication token
        string keyVaultUrl = "https://KeyVault.vault.azure.net";
        string secretName = "Test3";
        //string accessToken = "<your-access-token>";
        string tenantId = "tenantId";  // Your tenant ID
        string clientId = "clientId";  // Your application (client) ID
        string clientSecret = "clientSecret Vaule ";  // Your client secret
        
       
        string accessToken = await GetAccessToken(tenantId, clientId, clientSecret);

        HttpClient client = new HttpClient();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

        string
 secretUrl = $"{keyVaultUrl}/secrets/{secretName}?api-version=7.3";

        HttpResponseMessage response = await client.GetAsync(secretUrl);

        if (response.IsSuccessStatusCode)
        {
            string responseBody = await response.Content.ReadAsStringAsync();
            var secret = System.Text.Json.JsonSerializer.Deserialize<Secret>(responseBody);
            Console.WriteLine("Secret value: " + secret.Value);
        }
        else
        {
            Console.WriteLine("Error fetching secret: " + response.StatusCode);
        }
    }

    private static async Task<string> GetAccessToken(string tenantId, string clientId, string clientSecret)
    {
        using (var client = new HttpClient())
        {
            var body = new StringContent($"grant_type=client_credentials&client_id={clientId}&client_secret={clientSecret}&resource=https://vault.azure.net", Encoding.UTF8, "application/x-www-form-urlencoded");

            var response = await client.PostAsync($"https://login.microsoftonline.com/{tenantId}/oauth2/token", body);
            response.EnsureSuccessStatusCode();

            var jsonResponse = await response.Content.ReadAsStringAsync();
            dynamic tokenResponse = JsonConvert.DeserializeObject(jsonResponse);
            return tokenResponse.access_token;
        }
    }

    class Secret
    {
        public string Value { get; set; }
    }
  }
 }

However, I'm unable to fetch the secret value. Is there anything wrong in the code or settings?

output

Notes

This is how API permission is given:

API permission

and, app permission is disabled somehow (not sure why). So I have given delegated permission as below:

App permission disabled

How to get the secret value? I need to achieve this via REST API only.

Upvotes: 0

Views: 128

Answers (1)

Sridevi
Sridevi

Reputation: 22552

I have one key vault named srikv2810 with access configured as Azure RBAC as below:

enter image description here

Now I created one secret named secret01 in above key vault with value as:

enter image description here

To get this secret value via REST API with token generated using service principal, make sure to add "Key Vault Secrets User" role to application under key vault.

Initially, I registered one application and granted same API permissions as below:

enter image description here

Now, I added "Key Vault Secrets User" role to above app registration under key vault like this:

enter image description here

When I ran your code in my environment to get secret value, I too got blank results:

enter image description here

To resolve this, make use of below modified code where I got secret content successfully in response:

using Newtonsoft.Json;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json.Serialization;

namespace KeyVaultSecretFetcher
{
    class Program
    {
        static async Task Main(string[] args)
        {
            string keyVaultUrl = "https://kvname.vault.azure.net";
            string secretName = "secret1";
            string tenantId = "tenantId";
            string clientId = "appId";
            string clientSecret = "secret";

            string accessToken = await GetAccessToken(tenantId, clientId, clientSecret);

            HttpClient client = new HttpClient();
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

            string secretUrl = $"{keyVaultUrl}/secrets/{secretName}?api-version=7.3";

            HttpResponseMessage response = await client.GetAsync(secretUrl);

            string responseBody = await response.Content.ReadAsStringAsync();

            if (response.IsSuccessStatusCode)
            {
                try
                {
                    var secret = System.Text.Json.JsonSerializer.Deserialize<Secret>(responseBody);
                    Console.WriteLine("Secret value: " + secret?.Value);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error deserializing secret value: " + ex.Message);
                }
            }
            else
            {
                Console.WriteLine($"Error fetching secret: {response.StatusCode}");
            }
        }

        private static async Task<string> GetAccessToken(string tenantId, string clientId, string clientSecret)
        {
            using (var client = new HttpClient())
            {
                var body = new StringContent($"grant_type=client_credentials&client_id={clientId}&client_secret={clientSecret}&resource=https://vault.azure.net", Encoding.UTF8, "application/x-www-form-urlencoded");

                var response = await client.PostAsync($"https://login.microsoftonline.com/{tenantId}/oauth2/token", body);
                response.EnsureSuccessStatusCode();

                var jsonResponse = await response.Content.ReadAsStringAsync();
                dynamic tokenResponse = JsonConvert.DeserializeObject(jsonResponse);
                return tokenResponse.access_token;
            }
        }

        class Secret
        {
            [JsonPropertyName("value")]
            public string Value { get; set; }
        }
    }
}

Response:

enter image description here

Upvotes: 1

Related Questions