This post is part of a series on Managed Identity. For an introduction, see Managed Identity – Part I. For a post that shows you how to connect your application to different types of Azure resources using Managed Identity see Managed Identity – Part II. Stay tuned for future posts.
Elaborating on Part I and Part II, this blog post will show you how to debug your Managed Identity enabled application locally.
Normally debugging something when running it locally shouldn’t deserve its own blog post. With Managed Identity there are some things to take into account when debugging since it heavily depends on the Azure platform. So here we are 😊
Azure Service Authentication
The first thing you need to do is configure the account to use when debugging applications from Visual Studio by checking if the correct account is selected. To do this go to Tools – Options – “Azure Service Authentication” and choose/configure the right account.
Choose an account for your apps to authenticate and access Azure resources with when debugging from Visual Studio.
When you’re running applications locally without debugging from Visual Studio, for instance by manually executing func start or running your console app, you need to do some extra magic…
For those of you who have the Azure extension in Visual Studio Code; you’re probably familiar with the Device Login. The same process goes for logging in into command line environments. You can sign in interactively through your browser with the az login command. This used to tell you to go to https://microsoft.com/devicelogin and enter a random code as shown here:
With the most recent versions of the Azure CLI, this is even simpler. You execute az login, a browser is opened where you login to your account and you’re done. This looks like the image below. As you can see, this command automatically finds all subscriptions to which you have access right after you logged in.
Connecting to resources
Connecting to Key Vault simply works. The AzureServiceTokenProvider has a KeyVaultTokenCallback we can pass into the constructor of the KeyVaultClient using a KeyVaultClient.AuthenticationCallback and the result is our locally running application being authenticated to connect to the Key Vault (depending on the rights we gave ourselves, of course).
Connecting to other Azure resources while running locally, like Azure SQL for instance, is a bit more challenging. Let’s start by taking the steps necessary:
Create a SQL Server and SQL Database
Add your user account to an AD group and set it as the AD admin *
Currently, Microsoft accounts (like live.com, outlook.com) cannot be set as admin. Only users and security groups within your organization can be set as admin.
private const string RESOURCE = "https://database.windows.net/";
private const string CONNECTIONSTRING = "Server=tcp:<YOUR_SERVER_NAME>.database.windows.net,1433;Initial Catalog=<YOUR_DATABASE_NAME>;";
using (var connection = new SqlConnection(CONNECTIONSTRING))
var tokenProvider = new AzureServiceTokenProvider();
connection.AccessToken = await tokenProvider.GetAccessTokenAsync(RESOURCE);
// Do your magic to the database!
And here is the result:
SqlException - "Login failed for user 'NT AUTHORITY\\ANONYMOUS LOGON'."
Why don’t I have access?
Wait… what? Looking into the details, we’ll find that the call to GetAccessTokenAsync went through fine and even provided us with a token. Then why is that not working? And what’s up with that ‘anonymous logon’?
Even more puzzling is the fact that, when deploying this to Azure, it actually works.
Deconstructing the token we got using a tool like jwt.ms or jwt.io shows that the audience for the token is exactly what we expected it to be: https://database.windows.net. The issuer however seems to be off. It’s not the same as our Azure Active Directory tenant.
Apparently, when using an Microsoft account (mine’s an Outlook.com one, migrated over from the good old Hotmail days) you need to explicitly specify the tenant id you want to use. This can either be the Directory ID of your Azure Active Directory that you can find on the Azure Active Directory properties blade, or the xxx.onmicrosoft.com name associated with it. The call to GetAccessTokenAsync then changes into this:
After this change, we can see the token we’re getting is actually from my Azure Active Directory tenant.
Running applications locally but still leveraging the power of Managed Identity is very well possible. Although there are a few caveats. So whenever you’re running into your local user not being able to connect to an Azure Resource using Managed Identity: check if you specified the Tenant ID!