skip to Main Content

Request you to understand my question, before you downgrade or suggest delete. As I have to use the REST API with .Net framework 4 and 4.5. My applications are hosted both in Azure ( as app service) and on Azure VM.

I know there Azure has a concept of managed identity. However, I’m trying to implement fetching secrets from Azure Key vault using REST API. The applications are using .Net framework 4 and 4.5.

the code is as below:

    string keyVaultUrl = "https://KeyVault.vault.azure.net";
    string secretName = "Test";
   
    string tenantId = "tenantId"; 
    string clientId = "clientId";  
    string clientSecret = "clientSecret Vaule "; 

I’m getting a access token by calling a custom method as below:

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

The above code works fine.

For me, its like fetching one secret from the Key vault by exposing another secret.

I have seen lots of post says using "managed identity". As said earlier "I have to use the REST API with .Net framework 4 and 4.5. My applications are hosted both in Azure ( as app service) and on Azure VM." I believe in this case ""managed identity" is not applicable – specifically when its comes to REST and .Net 4/.net 4.5 and when application does not supports required Key vault and Entra ID related namespace ( e.g. key vault "Microsoft.Azure.KeyVault" namespace.)

My question is what is the best ways to store "clientSecret" as its getting used to fetch the secrets from Key vault ? Where can I store the client "clientSecret" and use in the code?

Hope my question is understandable. Please let me know. Thanks

2

Answers


  1. As far as i know, the common method is to store secrets, such as the secret to access the key vault, in environment variables and then accessing the env-vars through your code.

    Is this helpfull?

    Login or Signup to reply.
  2. Note that: ClientID is mandatory to generate access token, if you do not want to make use of client secret then you can generate access token using Interactive flow or Username/Password flow.

    For an application to make it as Public you need to set Allow public client flows as YES:

    enter image description here

    But according to Microsoft Username/Password flow is not recommended due to security issues.

    class Program
    {
        private const string TenantId = "your-tenant-id"; 
        private const string ClientId = "your-client-id"; 
        private const string Resource = "https://vault.azure.net"; 
    
        static async Task Main(string[] args)
        {
            string username = "[email protected]"; 
            string password = "yourpassword"; 
    
            try
            {
                var app = PublicClientApplicationBuilder.Create(ClientId)
                    .WithTenantId(TenantId)
                    .Build();
    
                var securePassword = new System.Security.SecureString();
                foreach (char c in password)
                {
                    securePassword.AppendChar(c);
                }
    
                var result = await app.AcquireTokenByUsernamePassword(
                    new[] { $"{Resource}/.default" },
                    username,
                    securePassword)
                    .ExecuteAsync();
    
                Console.WriteLine("Access Token: " + result.AccessToken);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error: " + ex.Message);
            }
        }
    }
    

    You can also make use of InteractiveBrowserCredential flow which do not need client secret:

    class Program
    {
        private const string ClientId = "ClientID"; 
        private const string TenantId = "TenantID"; 
        private const string Resource = "https://vault.azure.net";
    
        static async Task Main(string[] args)
        {
            var credential = new InteractiveBrowserCredential(new InteractiveBrowserCredentialOptions
            {
                ClientId = ClientId,
                TenantId = TenantId
            });
    
            var tokenRequestContext = new TokenRequestContext(new[] { $"{Resource}/.default" });
    
            var token = await credential.GetTokenAsync(tokenRequestContext);
    
            Console.WriteLine("Access Token: " + token.Token);
        }
    }
    

    enter image description here

    If the above does not resolve the issue, then you have to Store the clientSecret in environment variables. This is a simple method and keeps sensitive data out of your codebase as suggested by Provadis.

    string clientSecret = Environment.GetEnvironmentVariable("YourClientSecretEnvironmentVariable");
    
    • OR use a separate method to fetch the clientSecret before using it to obtain the access token.
    string clientSecret = await GetSecretFromKeyVault(keyVaultUrl, "YourClientSecretName");
    string accessToken = await GetAccessToken(tenantId, clientId, clientSecret);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search