Connect to an Azure key vault from a program on any laptop using user identity
Tags: azurekeyvault
Published: 2021-01-17 22:02:04

<sub><span>Photo by <a href="https://unsplash.com/@judebeck">Jude Beck</a> on <a href="https://unsplash.com/s/photos/bank-vault">Unsplash</a></span></sub>


Connecting from a Managed Service Identity (MSI) to an Azure Key Vault is pretty [well documented](https://docs.microsoft.com/en-us/samples/azure-samples/app-service-msi-keyvault-dotnet/keyvault-msi-appservice-sample/). But how can we achieve this from a program on a laptop using user account ?


# Azure Active Directory Application

First we will require an application registered to the Azure Active Directory of your subscription, with the right **user_impersonation**.

Write down, the application identifier, and the redirect uri if any, and the directory identifier of your subscription.

# Program

In your program, you will have to:
- add the package **Microsoft.Identity.Client** to your application
- Get the Token from Azure using the following code
```csharp
            IPublicClientApplication app = PublicClientApplicationBuilder.Create(applicationId)
                                                                        .WithRedirectUri(redirectUri)
                                                                        .WithAuthority($"https://login.microsoftonline.com/{directoryId}")
                                                                        .WithTenantId(directoryId)
                                                                        .Build();
            string[] scopes = new string[] { "https://vault.azure.net/user_impersonation" };
            Microsoft.Identity.Client.AuthenticationResult result = null;
            var accounts = await app.GetAccountsAsync();

            try
            {
                result = await app.AcquireTokenSilent(scopes,
                                                    accounts.FirstOrDefault())
                    .ExecuteAsync();
            }
            catch (MsalUiRequiredException msalUiEx)
            {
                // A MsalUiRequiredException happened on AcquireTokenSilent.
                // This indicates you need to call AcquireTokenInteractive to acquire a token
                //System.Diagnostics.Debug.WriteLine($"MsalUiRequiredException: {msalUiEx.Message}");

                try
                {
                    result = await app.AcquireTokenInteractive(scopes)
                        .ExecuteAsync();
                    //  Msal.Utils.extractIdToken
                }
                catch (MsalException msalex)
                {
                    throw;
                }
            }

```

- then, we can instantiate a keyvault client using the token
```csharp
            HttpClient client = new HttpClient();
            keyVaultClient = new KeyVaultClient(async (authority, resource, scope) => 
                                                { 
                                                    return result.AccessToken;
                                                }, client);
```

Note that
- AcquireTokenInteractive will request from the user to fill its account / password using the configured parameters (using only work and school account or not) in a popup
- the token is available in result.AccessToken, which will expire at result.ExpiresOn
- the user account has to have an access policy to the key vault
- Scopes cannot be combined if it relates to different resources ( "https://vault.azure.net/user_impersonation", "User.Read" can't work for example, 2 calls has to be made)
- [Github issue providing a lot of informations](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/1932) 


Hope this helps !