Azure Identity 301 - ChainedTokenCredential

"Azure Identity 301"

Azure Identity is an Azure SDK library that abstracts all the authentication complexities so you can get back to building your Azure solutions.

In Azure Identity 101, we learned about DefaultAzureCredential, which allows you to quickly add authentication to your application with a single line of code:

var client = new SecretClient(vaultUri, new DefaultAzureCredential());

In Azure Identity 201, we learned about DefaultAzureCredentialOptions, which allows you to configure various DefaultAzureCredential options. For example if you want to set the user-assigned Managed Identity client Id you would do the following:

var client = new SecretClient(vaultUri,
    new DefaultAzureCredential(
        new DefaultAzureCredentialOptions { ManagedIdentityClientId = clientId }
    )
);

In Azure Identity 202, we learned about all of the Environment Variables that Azure Identity inspects, which you can override at the system or terminal level. This is convenient when you need to change a setting in an environment without changing code.

In this Azure Identity 301 post we’ll take a look at using individual credential types, EnvironmentCredential and ChainedTokenCredential - which allows you to create your own chain of credentials to suit your application needs.

Individual Credential Types

Up until this point, we’ve been using DefaultAzureCredential which is an opinionated and heavily customer-researched chain of credential types. Refer to Azure Identity 101 for the full list of credential types it attempts to get a token from.

DefaultAzureCredential is amazingly useful for getting started quickly. Just new-it-up and go. But, let’s say that you are 100% sure your application will only ever use the Azure CLI to authenticate users, which could happen if it is an internal-developer centric tool. If that is the case, then you could simply new up an AzureCliCredential object and use that just like you used DefaultAzureCredential.

Here’s what that would look like:

var client = new SecretClient(vaultUri, new AzureCliCredential());

The benefit of using a discreet credential type is that Azure libraries will only attempt to get a token from that one type and you know where your token is coming from. The downside is that your application will fail if it is unable to get a token from that type.

You can find the full list of credential types here: Azure.Identity Namespace.

Environment Credential

EnvironmentCredential is also a chain of credentials, that includes credentials that authenticate via service principal, app or user. They include ClientSecretCredential, UsernamePasswordCredential, and ClientCertificateCredential. It is include as the first credential type in DefaultAzureCredential, but you can also use it directly:

var client = new SecretClient(vaultUri, new EnvironmentCredential());

You’d use this type directly if you know your app will only ever authenticate with one of those types and you’d like to take advantage of Azure Identity’s built in support for well known Environment Variables.

You can learn more about all of the supported Environment Variables here: Azure Identity 202

Chained Token Credential

ChainedTokenCredential is a type that allows you to easily build your own chain of credentials. For example, let’s say that you are 100% sure you want to use Azure CLI for local development and Managed Identity for your production cloud environment. You could use DefaultAzureCredential for this scenario, because that chain includes both ManagedIdentityCredential and AzureCLiCredential. It will attempt to get tokens in that order and short-circuit when it gets a token, so in a production environment the AzureCliCredential won’t even be executed.

But if you use DefaultAzureCredential in this scenario, then there’s a little bit of unknown in exactly how much time it takes to go attempt the credentials that are in the chain that you know you’ll never use. For example, if you know you won’t ever need to try AzurePowerShellCredential, then you could exclude it with this:

var client = new SecretClient(vaultUri,
    new DefaultAzureCredential(
        new DefaultAzureCredentialOptions { ExcludeAzurePowerShellCredential = true }
    )
);

But let’s say you want to also not include the VisualStudioCodeCredential, that would look like this:

var client = new SecretClient(vaultUri,
    new DefaultAzureCredential(
        new DefaultAzureCredentialOptions { ExcludeAzurePowerShellCredential = true, ExcludeVisualStudioCodeCredential = true }
    )
);

You’d get to a point where you have so many Exclude...Credential statements that DefaultAzureCredential starts to gets cumbersome.

This is where ChainedTokenCredential come into the picture.

When…

  1. You know the exact list of credentials you want your application to attempt. For example: ManagedIdentityCredential (cloud) and AzureCliCredential (local).
  2. You would rather build a custom list rather than use the DefaultAzureCredentialOptions.Exclude...Credential options.

It’s very easy to create your own chain. For example, with the Azure CLI for local and Managed Identity for cloud, you could new-up a ChainedTokenCredential object like this:

var client = new SecretClient(vaultUri,
    new ChainedTokenCredential(
        new ManagedIdentityCredential(),
        new AzureCliCredential()
    )
);

This will tell the Azure Identity library to try to get a token from Managed Identity first and then Azure CLI. When building your own chain it is recommended that you try production credentials first followed by developer based credentials. That way developer credential types are never used in production.

Conclusion

I hope this post helped you expand your Azure Identity horizons and helps you build your own chain and understand why you’d do so.

Feel free to reach out with any questions.

Jon