Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Azure Identity library credential chains doc #42049

Merged
merged 43 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
dc077a7
Add Azure Identity library credential chains doc
scottaddie Aug 6, 2024
fea4adb
Update mermaid diagrams
scottaddie Aug 6, 2024
6ddc219
Fix code snippets
scottaddie Aug 6, 2024
c16e889
Add H1
scottaddie Aug 6, 2024
974b800
Move sample code
scottaddie Aug 6, 2024
5e24f11
Add 2 more code samples
scottaddie Aug 6, 2024
364aca4
Edit diagrams
scottaddie Aug 6, 2024
97fad94
Replace list with table
scottaddie Aug 6, 2024
d2704b4
Rename directory
scottaddie Aug 6, 2024
d51dc98
Tweak wording
scottaddie Aug 6, 2024
071e3d1
Accessibility improvements
scottaddie Aug 7, 2024
e7e4462
Remove unnecessary http file
scottaddie Aug 7, 2024
bd08dde
Add links to credentials
scottaddie Aug 7, 2024
57cb725
Update diagrams
scottaddie Aug 7, 2024
b95817d
Update credential name
scottaddie Aug 7, 2024
8dcd874
Edit pass
scottaddie Aug 7, 2024
4bbc644
More edits
scottaddie Aug 7, 2024
04a73aa
Update title
scottaddie Aug 7, 2024
33948b8
Edit pass
scottaddie Aug 7, 2024
2533545
Add sequence diagram
scottaddie Aug 7, 2024
811f6cd
Update benefits
scottaddie Aug 7, 2024
8b5bbd2
Add metadata to includes
scottaddie Aug 7, 2024
f955fcc
Move mermaid markup files to includes folder
scottaddie Aug 8, 2024
9b04999
Fix build warnings
scottaddie Aug 8, 2024
7e34959
Fix lightboxes
scottaddie Aug 8, 2024
03569d4
Fix images
scottaddie Aug 8, 2024
a682f93
React to feedback
scottaddie Aug 12, 2024
8cb046b
Add line highlighting
scottaddie Aug 12, 2024
04b4877
Small edits
scottaddie Aug 12, 2024
76bb5fc
Move sample app
scottaddie Aug 13, 2024
662b36e
Add a debug section
scottaddie Aug 13, 2024
3a3f19e
Edits to debug section
scottaddie Aug 13, 2024
71ad1a6
More edits to debug section
scottaddie Aug 13, 2024
4068aaf
Fix heading
scottaddie Aug 13, 2024
2b61dc6
React to Maor feedback
scottaddie Aug 13, 2024
2b65d5a
Add missing tab IDs
scottaddie Aug 13, 2024
071c325
Small edit
scottaddie Aug 13, 2024
d4f03ed
Link to env vars section in README
scottaddie Aug 13, 2024
2b6cdc4
Remove lightboxes
scottaddie Aug 14, 2024
c0cfde2
React to Bill's feedback
scottaddie Aug 14, 2024
a0da0bd
React to David's feedback
scottaddie Aug 14, 2024
86bd740
Update docs/azure/sdk/snippets/authentication/credential-chains/Progr…
scottaddie Aug 14, 2024
98f74e8
Convert text to note
scottaddie Aug 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/azure/TOC.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
href: ./sdk/authentication/create-token-credentials-from-configuration.md
- name: Additional auth methods
href: ./sdk/authentication/additional-methods.md
- name: Credential chains
href: ./sdk/authentication/credential-chains.md
- name: Resource management
href: ./sdk/resource-management.md
- name: Dependency injection
Expand Down Expand Up @@ -118,4 +120,4 @@
- name: All samples
href: /samples/browse/?languages=csharp%2Caspx-csharp%2Cfsharp%2Cvb
- name: API reference
href: /dotnet/api/overview/azure/?view=azure-dotnet&preserve-view=true
href: /dotnet/api/overview/azure/?view=azure-dotnet&preserve-view=true
132 changes: 132 additions & 0 deletions docs/azure/sdk/authentication/credential-chains.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
---
title: 'Credential chains in the Azure Identity library for .NET'
description: 'This article describes the DefaultAzureCredential and ChainedTokenCredential classes in the Azure Identity library.'
ms.topic: conceptual
ms.date: 08/13/2024
---

# Credential chains in the Azure Identity library for .NET

The Azure Identity library provides *credentials*—public classes derived from the Azure Core library's [TokenCredential](/dotnet/api/azure.core.tokencredential?view=azure-dotnet&preserve-view=true) class. A credential represents a distinct authentication flow for acquiring an access token from Microsoft Entra ID. These credentials can be chained together to form an ordered sequence of authentication mechanisms to be attempted.
scottaddie marked this conversation as resolved.
Show resolved Hide resolved

## How a chained credential works

At runtime, a credential chain attempts to authenticate using the sequence's first credential. If that credential fails to acquire an access token, the next credential in the sequence is attempted, and so on, until an access token is successfully obtained. The following sequence diagram illustrates this behavior:

:::image type="content" source="../media/mermaidjs/ChainSequence.svg" alt-text="Credential chain sequence diagram":::

## Why use credential chains

A chained credential can offer the following benefits:

- **Environment awareness**: Automatically selects the most appropriate credential based on the environment in which the app is running. Without it, you'd have to write code like this:

:::code language="csharp" source="../snippets/authentication/credential-chains/Program.cs" id="snippet_NoChain":::

- **Seamless transitions**: Your app can move from local development to your staging or production environment without changing authentication code.
- **Improved resiliency**: Includes a fallback mechanism that moves to the next credential when the prior fails to acquire an access token.

## How to choose a chained credential

There are two disparate philosophies to credential chaining:

- **"Tear down" a chain**: Start with a preconfigured chain and exclude what you don't need. For this approach, see the [DefaultAzureCredential overview](#defaultazurecredential-overview) section.
- **"Build up" a chain**: Start with an empty chain and include only what you need. For this approach, see the [ChainedTokenCredential overview](#chainedtokencredential-overview) section.

## DefaultAzureCredential overview

[DefaultAzureCredential](/dotnet/api/azure.identity.defaultazurecredential?view=azure-dotnet&preserve-view=true) is an opinionated, preconfigured chain of credentials. It's designed to support many environments, along with the most common authentication flows and developer tools. In graphical form, the underlying chain looks like this:

:::image type="content" source="../media/mermaidjs/DefaultAzureCredentialAuthFlow.svg" alt-text="DefaultAzureCredential auth flowchart":::

The order in which `DefaultAzureCredential` attempts credentials follows.

| Order | Credential | Description | Enabled by default? |
|-------|---------------------|-------------|---------------------|
| 1 | [Environment][env-cred] |Reads a collection of environment variables to determine if an application service principal (application user) is configured for the app. If so, `DefaultAzureCredential` uses these values to authenticate the app to Azure. This method is most often used in server environments but can also be used when developing locally. | Yes |
| 2 | [Workload Identity][wi-cred] |If the app is deployed to an Azure host with Workload Identity enabled, authenticate that account. | Yes |
| 3 | [Managed Identity][mi-cred] |If the app is deployed to an Azure host with Managed Identity enabled, authenticate the app to Azure using that Managed Identity. | Yes |
| 4 | [Visual Studio][vs-cred] |If the developer authenticated to Azure by logging into Visual Studio, authenticate the app to Azure using that same account. | Yes |
| 5 | [Azure CLI][az-cred] |If the developer authenticated to Azure using Azure CLI's `az login` command, authenticate the app to Azure using that same account. | Yes |
| 6 | [Azure PowerShell][pwsh-cred] |If the developer authenticated to Azure using Azure PowerShell's `Connect-AzAccount` cmdlet, authenticate the app to Azure using that same account. | Yes |
| 7 | [Azure Developer CLI][azd-cred] |If the developer authenticated to Azure using Azure Developer CLI's `azd auth login` command, authenticate with that account. | Yes |
| 8 | [Interactive browser][int-cred] |If enabled, interactively authenticate the developer via the current system's default browser. | No |

[env-cred]: /dotnet/api/azure.identity.environmentcredential?view=azure-dotnet&preserve-view=true
[wi-cred]: /dotnet/api/azure.identity.workloadidentitycredential?view=azure-dotnet&preserve-view=true
[mi-cred]: /dotnet/api/azure.identity.managedidentitycredential?view=azure-dotnet&preserve-view=true
[vs-cred]: /dotnet/api/azure.identity.visualstudiocredential?view=azure-dotnet&preserve-view=true
[az-cred]: /dotnet/api/azure.identity.azureclicredential?view=azure-dotnet&preserve-view=true
[pwsh-cred]: /dotnet/api/azure.identity.azurepowershellcredential?view=azure-dotnet&preserve-view=true
[azd-cred]: /dotnet/api/azure.identity.azuredeveloperclicredential?view=azure-dotnet&preserve-view=true
[int-cred]: /dotnet/api/azure.identity.interactivebrowsercredential?view=azure-dotnet&preserve-view=true

In its simplest form, you can use the parameterless version of `DefaultAzureCredential` as follows:

:::code language="csharp" source="../snippets/authentication/credential-chains/Program.cs" id="snippet_Dac":::

### How to customize DefaultAzureCredential

To remove a credential from `DefaultAzureCredential`, use the corresponding `Exclude`-prefixed property in [DefaultAzureCredentialOptions](/dotnet/api/azure.identity.defaultazurecredentialoptions?view=azure-dotnet&preserve-view=true#properties). For example:
scottaddie marked this conversation as resolved.
Show resolved Hide resolved

:::code language="csharp" source="../snippets/authentication/credential-chains/Program.cs" id="snippet_DacExcludes" highlight="4-5":::

In the preceding code sample, `EnvironmentCredential` and `WorkloadIdentityCredential` are removed from the credential chain. As a result, the first credential to be attempted is `ManagedIdentityCredential`. The modified chain looks like this:

:::image type="content" source="../media/mermaidjs/DefaultAzureCredentialExcludes.svg" alt-text="DefaultAzureCredential using Excludes properties":::

> [!NOTE]
> `InteractiveBrowserCredential` is excluded by default and therefore isn't shown in the preceding diagram. To include `InteractiveBrowserCredential`, use constructor <xref:Azure.Identity.DefaultAzureCredential.%23ctor%28System.Boolean%29>.

As more `Exclude`-prefixed properties are set to `true` (credential exclusions are configured), the advantages of using `DefaultAzureCredential` diminish. In such cases, `ChainedTokenCredential` is a better choice and requires less code. To illustrate, these two code samples behave the same way:

### [DefaultAzureCredential](#tab/dac)

:::code language="csharp" source="../snippets/authentication/credential-chains/Program.cs" id="snippet_DacEquivalents":::

### [ChainedTokenCredential](#tab/ctc)

:::code language="csharp" source="../snippets/authentication/credential-chains/Program.cs" id="snippet_CtcEquivalents":::

---

## ChainedTokenCredential overview

[ChainedTokenCredential](/dotnet/api/azure.identity.chainedtokencredential?view=azure-dotnet&preserve-view=true) is an empty chain to which you add credentials to suit your app's needs. For example:

:::code language="csharp" source="../snippets/authentication/credential-chains/Program.cs" id="snippet_Ctc":::

The preceding code sample creates a tailored credential chain comprised of two credentials. The user-assigned managed identity variant of `ManagedIdentityCredential` is attempted first, followed by `VisualStudioCredential`, if necessary. In graphical form, the chain looks like this:

:::image type="content" source="../media/mermaidjs/ChainedTokenCredentialAuthFlow.svg" alt-text="ChainedTokenCredential":::

> [!TIP]
> For improved performance, optimize credential ordering in `ChainedTokenCredential` for your production environment. Credentials intended for use in the local development environment should be added last.

## Usage guidance for DefaultAzureCredential

`DefaultAzureCredential` is undoubtedly the easiest way to get started with the Azure Identity library, but with that convenience comes tradeoffs. Once you deploy your app to Azure, you should understand the app's authentication requirements. For that reason, strongly consider moving from `DefaultAzureCredential` to one of the following solutions:

- A specific `TokenCredential` implementation, such as `ManagedIdentityCredential`. See the [**Derived** list](/dotnet/api/azure.core.tokencredential?view=azure-dotnet&preserve-view=true#definition) for options.
- A pared-down `ChainedTokenCredential` implementation optimized for the Azure environment in which your app runs.

Here's why:

- **Debugging challenges**: When authentication fails, it can be challenging to debug and identify the offending credential. You must enable logging to see the progression from one credential to the next and the success/failure status of each. For more information, see [Debug a chained credential](#debug-a-chained-credential).
- **Performance overhead**: The process of sequentially trying multiple credentials can introduce performance overhead. For example, when running on a local development machine, managed identity is unavailable. Consequently, `ManagedIdentityCredential` always fails in the local development environment, unless explicitly disabled via its corresponding `Exclude`-prefixed property.
- **Unpredictable behavior**: `DefaultAzureCredential` checks for the presence of certain [environment variables](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/README.md#environment-variables). It's possible that someone could add or modify these environment variables at the system level on the host machine. Those changes apply globally and therefore alter the behavior of `DefaultAzureCredential` at runtime in any app running on that machine.

## Debug a chained credential

To diagnose an unexpected issue or to understand what a chained credential is doing, [enable logging](../logging.md) in your app. Optionally, filter the logs to only those events emitted from the Azure Identity library. For example:

:::code language="csharp" source="../snippets/authentication/credential-chains/Program.cs" id="snippet_FilteredLogging":::

For illustration purposes, assume the parameterless form of `DefaultAzureCredential` was used to authenticate a request to a Log Analytics workspace. The app ran in the local development environment, and Visual Studio was authenticated to an Azure account. The next time the app ran, the following pertinent entries appeared in the output:

:::code language="output" source="../snippets/authentication/credential-chains/dac-logs.txt":::

In the preceding output, notice that:

- `EnvironmentCredential`, `WorkloadIdentityCredential`, and `ManagedIdentityCredential` each failed to acquire a Microsoft Entra access token, in that order.
- The `DefaultAzureCredential credential selected:`-prefixed entry indicates the credential that was selected&mdash;`VisualStudioCredential` in this case. Since `VisualStudioCredential` succeeded, no credentials beyond it were used.
17 changes: 0 additions & 17 deletions docs/azure/sdk/authentication/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,3 @@ When an app is run on a developer's workstation during local development, it mus
## Use DefaultAzureCredential in an application

[!INCLUDE [Implement DefaultAzureCredential](<../includes/implement-defaultazurecredential.md>)]

### Explore the sequence of DefaultAzureCredential authentication methods

Internally, `DefaultAzureCredential` implements a chain of credential providers for authenticating applications to Azure resources. Each credential provider is able to detect if credentials of that type are configured for the app. `DefaultAzureCredential` sequentially checks each provider in order and uses the credentials from the first provider that has credentials configured.

The order and locations in which `DefaultAzureCredential` looks for credentials is found at [DefaultAzureCredential](/dotnet/api/overview/azure/identity-readme?view=azure-dotnet&preserve-view=true#defaultazurecredential).

| Credential type | Description |
|-------------------------------|-------------|
| Environment | `DefaultAzureCredential` reads a set of environment variables to determine if an application service principal (application user) has been set for the app. If so, `DefaultAzureCredential` uses these values to authenticate the app to Azure.<br><br>This method is most often used in server environments but can also be used when developing locally. |
| Workload Identity | If the app is deployed to an Azure host with Workload Identity enabled, `DefaultAzureCredential` will authenticate that account. |
| Managed Identity | If the app is deployed to an Azure host with Managed Identity enabled, `DefaultAzureCredential` will authenticate the app to Azure using that Managed Identity. Authentication using a Managed Identity is discussed in the [Authentication in server environments](#authentication-in-server-environments) section of this document.<br><br>This method is only available when the app is hosted in Azure using a service like Azure App Service, Azure Functions, or Azure Virtual Machines. |
| Visual Studio | If the developer has authenticated to Azure by logging into Visual Studio, `DefaultAzureCredential` will authenticate the app to Azure using that same account. |
| Azure CLI | If the developer has authenticated to Azure using Azure CLI's `az login` command, `DefaultAzureCredential` will authenticate the app to Azure using that same account. |
| Azure PowerShell | If the developer has authenticated to Azure using Azure PowerShell's `Connect-AzAccount` cmdlet, `DefaultAzureCredential` will authenticate the app to Azure using that same account. |
| Azure Developer CLI | If the developer has authenticated to Azure using Azure Developer CLI's `azd auth login` command, `DefaultAzureCredential` will authenticate with that account. |
| Interactive | If enabled, `DefaultAzureCredential` will interactively authenticate the developer via the current system's default browser. By default, this option is disabled. |
35 changes: 35 additions & 0 deletions docs/azure/sdk/includes/mermaidjs/ChainSequence.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
ms.topic: include
ms.date: 08/07/2024
---

```mermaid
%% STEPS TO GENERATE IMAGE
%% =======================
%% 1. Install mermaid CLI v10.9.1 (see https://github.com/mermaid-js/mermaid-cli/blob/master/README.md):
%% npm i -g @mermaid-js/[email protected]
%% 2. Run command: mmdc -i ChainSequence.md -o ../../media/mermaidjs/ChainSequence.svg

sequenceDiagram
autonumber;

participant A as .NET app;
participant B as Credential chain;
participant C as TokenCredential instance;

A->>B: Authenticate to Microsoft Entra ID;
activate B;
B->>B: GetToken;
loop Traverse TokenCredential collection until AccessToken received
B->>C: Fetch token;
activate C;
C->>C: GetToken;
break when Result is AccessToken
C-->>B: Result;
end;
deactivate C;
end;

B-->>A: AccessToken;
deactivate B;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
ms.topic: include
ms.date: 08/07/2024
---

```mermaid
%% STEPS TO GENERATE IMAGE
%% =======================
%% 1. Install mermaid CLI v10.9.1 (see https://github.com/mermaid-js/mermaid-cli/blob/master/README.md):
%% npm i -g @mermaid-js/[email protected]
%% 2. Run command: mmdc -i ChainedTokenCredentialAuthFlow.md -o ../../media/mermaidjs/ChainedTokenCredentialAuthFlow.svg

%%{
init: {
'theme': 'base',
'themeVariables': {
'tertiaryBorderColor': '#fff',
'tertiaryColor': '#fff'
}
}
}%%

flowchart LR;
C(Managed Identity):::deployed --> D(Visual Studio):::developer;

%% Define styles for credential type boxes
classDef deployed fill:#95C37E, stroke:#71AD4C, stroke-width:2px;
classDef developer fill:#F5AF6F, stroke:#EB7C39, stroke-width:2px;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
ms.topic: include
ms.date: 08/07/2024
---

```mermaid
%% STEPS TO GENERATE IMAGE
%% =======================
%% 1. Install mermaid CLI v10.9.1 (see https://github.com/mermaid-js/mermaid-cli/blob/master/README.md):
%% npm i -g @mermaid-js/[email protected]
%% 2. Run command: mmdc -i DefaultAzureCredentialAuthFlow.md -o ../../media/mermaidjs/DefaultAzureCredentialAuthFlow.svg

%%{
init: {
'theme': 'base',
'themeVariables': {
'tertiaryBorderColor': '#fff',
'tertiaryColor': '#fff'
}
}
}%%

flowchart LR;
accTitle: DefaultAzureCredential authentication flow;
accDescr: Flowchart showing the credential chain implemented by DefaultAzureCredential;

subgraph CREDENTIAL TYPES;
direction LR;
Deployed(Deployed service):::deployed ~~~ Developer(Developer tool):::developer ~~~ Interactive(Interactive):::interactive;
end;

subgraph CREDENTIALS;
direction LR;
A(Environment):::deployed --> B(Workload Identity):::deployed --> C(Managed Identity):::deployed --> D(Visual Studio):::developer --> E(Azure CLI):::developer --> F(Azure PowerShell):::developer --> G(Azure Developer CLI):::developer --> H(Interactive browser):::interactive;
end;

%% Define styles for credential type boxes
classDef deployed fill:#95C37E, stroke:#71AD4C, stroke-width:2px;
classDef developer fill:#F5AF6F, stroke:#EB7C39, stroke-width:2px;
classDef interactive fill:#A5A5A5, stroke:#828282, stroke-dasharray:5 5, stroke-width:2px;

%% Add API ref links to credential type boxes
click A "https://learn.microsoft.com/dotnet/api/azure.identity.environmentcredential?view=azure-dotnet" _blank;
click B "https://learn.microsoft.com/dotnet/api/azure.identity.workloadidentitycredential?view=azure-dotnet" _blank;
click C "https://learn.microsoft.com/dotnet/api/azure.identity.managedidentitycredential?view=azure-dotnet" _blank;
click D "https://learn.microsoft.com/dotnet/api/azure.identity.visualstudiocredential?view=azure-dotnet" _blank;
click E "https://learn.microsoft.com/dotnet/api/azure.identity.azureclicredential?view=azure-dotnet" _blank;
click F "https://learn.microsoft.com/dotnet/api/azure.identity.azurepowershellcredential?view=azure-dotnet" _blank;
click G "https://learn.microsoft.com/dotnet/api/azure.identity.azuredeveloperclicredential?view=azure-dotnet" _blank
click H "https://learn.microsoft.com/dotnet/api/azure.identity.interactivebrowsercredential?view=azure-dotnet" _blank;
```
Loading
Loading