{"id":369,"date":"2020-08-18T12:33:32","date_gmt":"2020-08-18T19:33:32","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/azure-sdk\/?p=369"},"modified":"2020-08-18T12:33:32","modified_gmt":"2020-08-18T19:33:32","slug":"azure-identity-august-2020-ga","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/azure-sdk\/azure-identity-august-2020-ga\/","title":{"rendered":"Azure SDK: What&#8217;s new in the Azure Identity August 2020 General Availability Release"},"content":{"rendered":"<p>Since we shipped the first Azure Identity library preview in June 2019, it has been a vital part of building Azure cloud solutions. We have received great feedback from our development community and have added new features and have fixed many bugs. However, most of the changes have been in preview in the past few months. Today, we are proud to share the stable release in .NET, Java, Python, and JavaScript\/TypeScript with you. This blog will give you a brief introduction to what we are bringing in this release.<\/p>\n<p>In this release, we have added support for more environments and developer platforms, without compromising the simplicity of the <code>DefaultAzureCredential<\/code> class. It&#8217;s now easier than ever to authenticate your cloud application on your local workstation, with your choice of IDE or developer tool. When the application is deployed to Azure, you are given more control and insights on how your application is authenticated.<\/p>\n<h2>Getting Started<\/h2>\n<p>Use the links below to find the August release of each language:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.nuget.org\/packages\/Azure.Identity\/1.2.0\">.NET 1.2.0<\/a><\/li>\n<li><a href=\"https:\/\/search.maven.org\/artifact\/com.azure\/azure-identity\/1.1.0\/jar\">Java 1.1.0<\/a><\/li>\n<li><a href=\"https:\/\/pypi.org\/project\/azure-identity\/1.4.0\/\">Python 1.4.0<\/a><\/li>\n<li><a href=\"https:\/\/www.npmjs.com\/package\/@azure\/identity\/v\/1.1.0\">JavaScript\/TypeScript 1.1.0<\/a><\/li>\n<\/ul>\n<h2>DefaultAzureCredential Updates<\/h2>\n<p>In the Azure Identity November 2019 release, <code>DefaultAzureCredential<\/code> supported reading credentials from environment variables, Managed Identity, Windows shared token cache, and interactively in the browser (for .NET &amp; Python), in that order. In this new release, <code>DefaultAzureCredential<\/code> is much more powerful, supporting a set of new environments in the following order (a merged list of all languages):<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-content\/uploads\/sites\/58\/2020\/08\/20200816-default-azure-credential-flow.png\" alt=\"default azure credential flow\" \/><\/p>\n<ul>\n<li><strong>Environment<\/strong> &#8211; The <code>DefaultAzureCredential<\/code> will read account information specified via environment variables and use it to authenticate.<\/li>\n<li><strong>Managed Identity<\/strong> &#8211; If the application is deployed to an Azure host with Managed Identity enabled, the <code>DefaultAzureCredential<\/code> will authenticate with that account.<\/li>\n<li><strong>Shared Token Cache<\/strong> (<em>updated, .NET, Java, Python only<\/em>) &#8211; Shared token cache is now also supported on Mac OS and Linux, in addition to Windows. If the developer has authenticated via tools that write to the shared token cache, the <code>DefaultAzureCredential<\/code> will authenticate with that account.<\/li>\n<li><strong>IntelliJ<\/strong> (<em>new, Java only<\/em>) &#8211; If the developer has authenticated via <a href=\"https:\/\/plugins.jetbrains.com\/plugin\/8053-azure-toolkit-for-intellij\">Azure Toolkit for IntelliJ<\/a>, the <code>DefaultAzureCredential<\/code> will authenticate with that account.<\/li>\n<li><strong>Visual Studio<\/strong> (<em>new, .NET only<\/em>) &#8211; If the developer has authenticated via Visual Studio, the <code>DefaultAzureCredential<\/code> will authenticate with that account.<\/li>\n<li><strong>Visual Studio Code<\/strong> (<em>new<\/em>) &#8211; If the developer has authenticated via the <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=ms-vscode.azure-account\">Visual Studio Code Azure Account extension<\/a>, the <code>DefaultAzureCredential<\/code> will authenticate with that account.<\/li>\n<li><strong>Azure CLI<\/strong> (<em>new<\/em>) &#8211; If the developer has authenticated an account via the <a href=\"https:\/\/docs.microsoft.com\/cli\/azure\/install-azure-cli?view=azure-cli-latest\">Azure CLI<\/a> <code>az login<\/code> command, the <code>DefaultAzureCredential<\/code> will authenticate with that account.<\/li>\n<li><strong>Interactive<\/strong> (<em>.NET, Python only<\/em>) &#8211; If enabled the <code>DefaultAzureCredential<\/code> will interactively authenticate the developer via the current system&#8217;s default browser.<\/li>\n<\/ul>\n<p>Using the <code>DefaultAzureCredential<\/code> remains the same as the previous releases:<\/p>\n<pre><code class=\"csharp\">\/\/ .NET\nvar client = new SecretClient(new Uri(keyVaultUrl), new DefaultAzureCredential());\n<\/code><\/pre>\n<pre><code class=\"java\">\/\/ Java\nDefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();\n\nSecretClient secretClient = new SecretClientBuilder()\n    .vaultUrl(keyVaultUrl)\n    .credential(credential)\n    .buildClient();\n<\/code><\/pre>\n<pre><code class=\"javascript\">\/\/ JavaScript\nconst client = new SecretClient(keyVaultUrl, new DefaultAzureCredential());\n<\/code><\/pre>\n<pre><code class=\"py\"># Python\nclient = SecretClient(vault_url, DefaultAzureCredential())\n<\/code><\/pre>\n<h2>More Credential Types<\/h2>\n<p>Not only is the DefaultAzureCredential updated to support these environments, you can also pick the specific credential to use. Here are the list of credentials grouped by usage types:<\/p>\n<h3>Authenticating Azure Hosted Applications<\/h3>\n<table>\n<thead>\n<tr>\n<th>credential<\/th>\n<th>usage<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>DefaultAzureCredential<\/code><\/td>\n<td>provides a simplified authentication experience to quickly start developing applications run in the Azure cloud<\/td>\n<\/tr>\n<tr>\n<td><code>ChainedTokenCredential<\/code><\/td>\n<td>allows users to define custom authentication flows composing multiple credentials<\/td>\n<\/tr>\n<tr>\n<td><code>ManagedIdentityCredential<\/code><\/td>\n<td>authenticates the managed identity of an Azure resource<\/td>\n<\/tr>\n<tr>\n<td><code>EnvironmentCredential<\/code><\/td>\n<td>authenticates a service principal or user via credential information specified in environment variables<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Authenticating Service Principals<\/h3>\n<table>\n<thead>\n<tr>\n<th>credential<\/th>\n<th>usage<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>ClientSecretCredential<\/code><\/td>\n<td>authenticates a service principal using a secret<\/td>\n<\/tr>\n<tr>\n<td><code>ClientCertificateCredential<\/code><\/td>\n<td>authenticates a service principal using a certificate<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Authenticating Users<\/h3>\n<table>\n<thead>\n<tr>\n<th>credential<\/th>\n<th>usage<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>InteractiveBrowserCredential<\/code><\/td>\n<td>interactively authenticates a user with the default system browser<\/td>\n<\/tr>\n<tr>\n<td><code>DeviceCodeCredential<\/code><\/td>\n<td>interactively authenticates a user on devices with limited UI<\/td>\n<\/tr>\n<tr>\n<td><code>UsernamePasswordCredential<\/code><\/td>\n<td>authenticates a user with a username and password<\/td>\n<\/tr>\n<tr>\n<td><code>AuthorizationCodeCredential<\/code><\/td>\n<td>authenticate a user with a previously obtained authorization code<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Authenticating via Development Tools<\/h3>\n<table>\n<thead>\n<tr>\n<th>credential<\/th>\n<th>usage<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>VisualStudioCredential<\/code><\/td>\n<td>authenticate in a development environment with Visual Studio<\/td>\n<\/tr>\n<tr>\n<td><code>IntelliJCredential<\/code><\/td>\n<td>authenticate in a development environment with the account in Azure Toolkit for IntelliJ<\/td>\n<\/tr>\n<tr>\n<td><code>VisualStudioCodeCredential<\/code><\/td>\n<td>authenticate in a development environment with Visual Studio Code<\/td>\n<\/tr>\n<tr>\n<td><code>AzureCliCredential<\/code><\/td>\n<td>authenticate in a development environment with the Azure CLI<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Here are the examples to use <code>VisualStudioCodeCredential<\/code> in JavaScript\/TypeScript and Python:<\/p>\n<pre><code class=\"javascript\">\/\/ JavaScript\nconst client = new SecretClient(keyVaultUrl, new VisualStudioCodeCredential());\n<\/code><\/pre>\n<pre><code class=\"py\"># Python\nclient = SecretClient(vault_url, VisualStudioCodeCredential())\n<\/code><\/pre>\n<p>Here is an example to use <code>VisualStudioCredential<\/code> in .NET:<\/p>\n<pre><code class=\"csharp\">var client = new SecretClient(new Uri(keyVaultUrl), new VisualStudioCredential());\n<\/code><\/pre>\n<p>You can learn about how to configure your Visual Studio for this credential in <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-net\/tree\/master\/sdk\/identity\/Azure.Identity#authenticating-via-visual-studio\">Authenticating via Visual Studio<\/a>.<\/p>\n<p>Here is an example to use <code>IntelliJCredential<\/code> in Java on Windows:<\/p>\n<pre><code class=\"java\">IntelliJCredential intelliJCredential = new IntelliJCredentialBuilder()\n    .keePassDatabasePath(\"C:\\Users\\user\\AppData\\Roaming\\JetBrains\\IdeaIC2020.1\\c.kdbx\")\n    .build();\n\nSecretClient client = new SecretClientBuilder()\n    .vaultUrl(\"https:\/\/{YOUR_VAULT_NAME}.vault.azure.net\")\n    .credential(intelliJCredential)\n    .buildClient();\n<\/code><\/pre>\n<p>The <code>keePassDatabasePath<\/code> setter is not required on Mac OS or Linux. You can learn about how to configure your IntelliJ IDEA for this credential in <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-java\/wiki\/Set-up-Your-Environment-for-Authentication#sign-in-azure-toolkit-for-intellij-for-intellijcredential\">Sign in Azure Toolkit for IntelliJ for IntelliJCredential<\/a>.<\/p>\n<p>You can learn about how to configure your Visual Studio Code for this credential in <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-java\/wiki\/Set-up-Your-Environment-for-Authentication#sign-in-visual-studio-code-azure-account-extension-for-visualstudiocodecredential\">Sign in Visual Studio Code Azure Account Extension for VisualStudioCodeCredential<\/a>.<\/p>\n<blockquote>\n<p><strong>Note:<\/strong> All credential implementations in the Azure Identity library are threadsafe, and a single credential instance can be used by multiple service clients.<\/p>\n<\/blockquote>\n<h2>More Configurability<\/h2>\n<h3>User-assigned Managed Identity<\/h3>\n<p>You can configure the client ID for a user managed identity:<\/p>\n<pre><code class=\"csharp\">\/\/ .NET\nvar credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = userAssignedClientId });\n\nvar client = new SecretClient(new Uri(keyVaultUrl), credential);\n<\/code><\/pre>\n<pre><code class=\"java\">\/\/ Java\nDefaultAzureCredential defaultCredential = new DefaultAzureCredentialBuilder()\n    .managedIdentityClientId(\"&lt;MANAGED_IDENTITY_CLIENT_ID&gt;\")\n    .build();\n\nSecretClient client = new SecretClientBuilder()\n    .vaultUrl(\"https:\/\/{YOUR_VAULT_NAME}.vault.azure.net\")\n    .credential(defaultCredential)\n    .buildClient();\n<\/code><\/pre>\n<pre><code class=\"javascript\">\/\/ JavaScript\nvar credential = new DefaultAzureCredential({ managedIdentityClientId: userAssignedClientId });\n\nconst client = new SecretClient(keyVaultUrl, credential);\n<\/code><\/pre>\n<pre><code class=\"py\"># Python\n# Set environment variable AZURE_CLIENT_ID=&lt;MANAGED_IDENTITY_CLIENT_ID&gt;\nclient = SecretClient(vault_url, DefaultAzureCredential())\n<\/code><\/pre>\n<h3>Authenticate to a Specific Tenant<\/h3>\n<p>By default, the credentials will authenticate a user account to its home tenant. You can configure specifically which tenant to authenticate to on all the credentials. This is useful if you are authenticating to a guest tenant, or your application is multi-tenant enabled.<\/p>\n<pre><code class=\"csharp\">\/\/ .NET\nvar credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { VisualStudioTenantId = contosoTenantId });\n\nvar client = new SecretClient(new Uri(keyVaultUrl), credential);\n<\/code><\/pre>\n<pre><code class=\"java\">\/\/ Java\nDefaultAzureCredential defaultCredential = new DefaultAzureCredentialBuilder()\n    .tenantId(\"&lt;CONTOSO_TENANT_ID&gt;\")\n    .build();\n\nSecretClient client = new SecretClientBuilder()\n    .vaultUrl(\"https:\/\/{YOUR_VAULT_NAME}.vault.azure.net\")\n    .credential(defaultCredential)\n    .buildClient();\n<\/code><\/pre>\n<pre><code class=\"javascript\">\/\/ JavaScript\nvar credential = new DefaultAzureCredential({ tenantId: contosoTenantId });\n\nconst client = new SecretClient(keyVaultUrl, credential);\n<\/code><\/pre>\n<pre><code class=\"py\"># Python\nclient = SecretClient(vault_url, DefaultAzureCredential(visual_studio_code_tenant_id=contoso_tenant_id))\n<\/code><\/pre>\n<h3>Build a Custom Credential Chain<\/h3>\n<p><code>DefaultAzureCredential<\/code> uses a credential chain internally to attempt authentication with multiple credentials. Each credential in the Azure Identity throws <code>CredentialUnavailableException<\/code> if it cannot find the required environment to authenticate. If it can find the environment but fails to authenticate, it will throw a different type of exception. The chain skips all the <code>CredentialUnavailableExceptions<\/code> in the chain, until a token is acquired, or a different type of exception is thrown.<\/p>\n<p>We can build our own <code>ChainedTokenCredential<\/code> once we understand this logic. For example, if you would like to use Azure CLI for authentication on your workstation, and system-assigned managed identity when your application is deployed to Azure:<\/p>\n<pre><code class=\"csharp\">\/\/ .NET\n\/\/ authenticate using managed identity if it is available otherwise use the Azure CLI to auth\nvar credential = new ChainedTokenCredential(new ManagedIdentityCredential(), new AzureCliCredential());\n\nvar eventHubProducerClient = new EventHubProducerClient(\"myeventhub.eventhubs.windows.net\", \"myhubpath\", credential);\n<\/code><\/pre>\n<pre><code class=\"java\">\/\/ Java\nChainedTokenCredential credential = new ChainedTokenCredentialBuilder()\n    .addFirst(new ManagedIdentityCredentialBuilder().build())\n    .addLast(new AzureCliCredentialBuilder().build())\n    .build();\n\nSecretClient client = new SecretClientBuilder()\n    .vaultUrl(\"https:\/\/{YOUR_VAULT_NAME}.vault.azure.net\")\n    .credential(defaultCredential)\n    .buildClient();\n<\/code><\/pre>\n<pre><code class=\"javascript\">\/\/ JavaScript\n\/\/ When an access token is requested, the chain will try each\n\/\/ credential in order, stopping when one provides a token\nconst firstCredential = new ManagedIdentityCredential();\nconst secondCredential = new AzureCliCredential();\nconst credentialChain = new ChainedTokenCredential(firstCredential, secondCredential);\n\nconst { KeyClient } = require(\"@azure\/keyvault-keys\");\nconst client = new KeyClient(vaultUrl, credentialChain);\n<\/code><\/pre>\n<pre><code class=\"python\"># Python\nmanaged_identity = ManagedIdentityCredential()\nazure_cli = AzureCliCredential()\ncredential_chain = ChainedTokenCredential(managed_identity, azure_cli)\n\nclient = EventHubClient(host, event_hub_path, credential_chain)\n<\/code><\/pre>\n<h2>Other Improvements<\/h2>\n<h3>Logging Improvements<\/h3>\n<p>We are printing more information in our logs for easier diagnostics. Using the Java library as an example, with the following code:<\/p>\n<pre><code class=\"java\">\/\/ Java\nDefaultAzureCredential defaultCredential = new DefaultAzureCredentialBuilder().build();\n\nSecretClient client = new SecretClientBuilder()\n    .vaultUrl(\"https:\/\/{YOUR_VAULT_NAME}.vault.azure.net\")\n    .credential(defaultCredential)\n    .buildClient();\n\nclient.getSecret(\"{SECRET_NAME}\");\n<\/code><\/pre>\n<p>When run locally on a workstation with Visual Studio Code installed, the following log will be printed:<\/p>\n<pre><code>[main] INFO com.azure.security.keyvault.secrets.SecretAsyncClient - Retrieving secret - the-secret\n[reactor-http-nio-1] ERROR com.azure.identity.EnvironmentCredential - EnvironmentCredential authentication unavailable. Environment variables are not fully configured.\n[reactor-http-nio-1] INFO com.azure.identity.DefaultAzureCredential - Azure Identity =&gt; Attempted credential EnvironmentCredential is unavailable.\n[reactor-http-nio-1] ERROR com.azure.identity.implementation.IdentityClient - ManagedIdentityCredential authentication unavailable. Connection to IMDS endpoint cannot be established, connect timed out.\n[reactor-http-nio-1] ERROR com.azure.identity.ManagedIdentityCredential - Azure Identity =&gt; ERROR in getToken() call for scopes [https:\/\/vault.azure.net\/.default]: ManagedIdentityCredential authentication unavailable. Connection to IMDS endpoint cannot be established, connect timed out.\n[reactor-http-nio-1] INFO com.azure.identity.DefaultAzureCredential - Azure Identity =&gt; Attempted credential ManagedIdentityCredential is unavailable.\n[ForkJoinPool.commonPool-worker-19] ERROR com.azure.identity.SharedTokenCacheCredential - Azure Identity =&gt; ERROR in getToken() call for scopes [https:\/\/vault.azure.net\/.default]: SharedTokenCacheCredential authentication unavailable. No accounts were found in the cache.\n[ForkJoinPool.commonPool-worker-19] INFO com.azure.identity.DefaultAzureCredential - Azure Identity =&gt; Attempted credential SharedTokenCacheCredential is unavailable.\n[ForkJoinPool.commonPool-worker-19] ERROR com.azure.identity.implementation.IntelliJCacheAccessor - IntelliJ Authentication not available. Please log in with Azure Tools for IntelliJ plugin in the IDE.\n[ForkJoinPool.commonPool-worker-19] ERROR com.azure.identity.IntelliJCredential - Azure Identity =&gt; ERROR in getToken() call for scopes [https:\/\/vault.azure.net\/.default]: IntelliJ Authentication not available. Please log in with Azure Tools for IntelliJ plugin in the IDE.\n[ForkJoinPool.commonPool-worker-19] INFO com.azure.identity.DefaultAzureCredential - Azure Identity =&gt; Attempted credential IntelliJCredential is unavailable.\n[ForkJoinPool.commonPool-worker-5] INFO com.azure.identity.VisualStudioCodeCredential - Azure Identity =&gt; getToken() result for scopes [https:\/\/vault.azure.net\/.default]: SUCCESS\n[ForkJoinPool.commonPool-worker-5] INFO com.azure.identity.DefaultAzureCredential - Azure Identity =&gt; Attempted credential VisualStudioCodeCredential returns a token\n[reactor-http-nio-3] INFO com.azure.security.keyvault.secrets.SecretAsyncClient - Retrieved secret - the-secret\n<\/code><\/pre>\n<p>When run in an Azure environment with managed identity available, the following log will be printed:<\/p>\n<pre><code>[main] INFO com.azure.security.keyvault.secrets.SecretAsyncClient - Retrieving secret - secret\n[reactor-http-epoll-1] INFO com.azure.identity.ManagedIdentityCredential - Azure Identity =&gt; Managed Identity environment: MSI_ENDPOINT\n[reactor-http-epoll-1] INFO com.azure.identity.ManagedIdentityCredential - Azure Identity =&gt; getToken() result for scopes [https:\/\/vault.azure.net\/.default]: SUCCESS\n[reactor-http-epoll-1] INFO com.azure.security.keyvault.secrets.SecretAsyncClient - Retrieved secret - secret\n<\/code><\/pre>\n<p>You will be able to tell which credentials have been attempted, what are the reasons for skipping them, and which credential is eventually picked to complete the authentication.<\/p>\n<p>When using <code>EnvironmentCredential<\/code>, you will also be able to tell what environment variables are missing from the log. With the following code:<\/p>\n<pre><code class=\"java\">\/\/ Java\nEnvironmentCredential credential = new EnvironmentCredentialBuilder().build();\n\nSecretClient client = new SecretClientBuilder()\n    .vaultUrl(\"https:\/\/{YOUR_VAULT_NAME}.vault.azure.net\")\n    .credential(credential)\n    .buildClient();\n\nclient.getSecret(\"{SECRET_NAME}\");\n<\/code><\/pre>\n<p>and <code>AZURE_CLIENT_ID<\/code> and <code>AZURE_TENANT_ID<\/code> environment variables set, the SDK will print the following log:<\/p>\n<pre><code>[main] ERROR com.azure.identity.EnvironmentCredential - Azure Identity =&gt; ERROR in EnvironmentCredential: Failed to create a ClientSecretCredential or ClientCertificateCredential. Missing required environment variable either AZURE_CLIENT_SECRET or AZURE_CLIENT_CERTIFICATE_PATH\n[main] ERROR com.azure.identity.EnvironmentCredential - Azure Identity =&gt; ERROR in EnvironmentCredential: Failed to determine an authentication scheme based on the available environment variables. Please specify AZURE_TENANT_ID and AZURE_CLIENT_SECRET to authenticate through a ClientSecretCredential; AZURE_TENANT_ID and AZURE_CLIENT_CERTIFICATE_PATH to authenticate through a ClientCertificateCredential; or AZURE_USERNAME and AZURE_PASSWORD to authenticate through a UserPasswordCredential.\n<\/code><\/pre>\n<h3>Proactive Token Refresh<\/h3>\n<p>In previous versions of the Azure Identity libraries, the tokens returned have been modified by us to leave a 2-minute buffer. The <code>isExpired()<\/code> method on them will return true 2 minutes before when the token will actually expire. The token policy will then refresh it. This is to accommodate the delay between the token acquisition time to the time Azure services receive the request. This is especially useful when the application is under high load &#8211; in those situations, an authenticated request carrying a token in its header could be queued up outside the HTTP connection pool for a prolonged period of time. When the request gets finally sent to Azure, the user only finds out the token has expired.<\/p>\n<p>There are also community feedback on making their cloud applications more robust against AAD down times. If AAD is down for a few minutes, they would like the Azure Identity library to offer a way for them to proactively get a new token &#8211; so that they always have a more up-to-date token and not wait until the last minute to refresh, only to find out AAD is down.<\/p>\n<p>Thus, the August release of the .NET, Java, and Python libraries are now equipped with a proactive token refresh design (JavaScript\/Typescript support is coming in a future release). 5 minutes before the token expiry, when a request comes in, the <code>BearerTokenAuthenticationPolicy<\/code> will attempt a token refresh &#8211; and if this refresh fails (e.g. AAD is unresponsive), the previously cached token will be attached to the request to be sent on Azure. The next request coming in after a 30-second timeout will trigger another token refresh attempt, and again &#8211; if this fails, the previously cached token will be attached. This continues until the previously cache token also expires, and only until when will the library throw the authentication error.<\/p>\n<p>All these behaviors are already enabled by default and no user configuration is needed.<\/p>\n<h3>AzureAuthorityHosts<\/h3>\n<p>When creating a credential, you can specify the authority host the credential should connect to when acquiring a token. We are now adding a new Type <code>AzureAuthorityHost<\/code> with a set of known authority hosts in Azure. For example, to use Azure Germany cloud:<\/p>\n<pre><code class=\"csharp\">\/\/ .NET\nvar credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { AuthorityHost = AzureAuthorityHosts.AzureGermany });\n\nvar client = new SecretClient(new Uri(keyVaultUrl), credential);\n<\/code><\/pre>\n<pre><code class=\"java\">\/\/ Java\nDefaultAzureCredential credential = new DefaultAzureCredentialBuilder()\n    .authorityHost(AzureAuthorityHosts.AZURE_GERMANY)\n    .build();\n\nSecretClient secretClient = new SecretClientBuilder()\n    .vaultUrl(\"https:\/\/mysecretkeyvault.vault.azure.net\")\n    .credential(credential)\n    .buildClient();\n<\/code><\/pre>\n<pre><code class=\"javascript\">\/\/ JavaScript\nvar credential = new DefaultAzureCredential({ authorityHost: AzureAuthorityHosts.AzureGermany });\n\nconst client = new SecretClient(keyVaultUrl, credential);\n<\/code><\/pre>\n<pre><code class=\"py\"># Python\nclient = SecretClient(vault_url, DefaultAzureCredential(authority=AzureAuthorityHosts.AzureGermany))\n<\/code><\/pre>\n<h2>Community acknowledgements<\/h2>\n<p>Community feedback has played an important role in the development of this release. Some features, like proactive token refresh, the idea comes entirely from the community. I&#8217;d like to give special thanks to the following community members and many others who has contributed in one way or another to the making of this release. Every time you open an issue, suggest a fix in a pull request, or even hit the &#8220;like&#8221; button on an issue, helps us in our understanding of what you&#8217;d like to see in our libraries.<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/thoemmi\">thoemmi<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/PaulVrugt\">PaulVrugt<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/tpajurek-dtml\">tpajurek-dtml<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/kallolborah\">kallolborah<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/ajaiswal595\">ajaiswal595<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/Szaraq\">Szaraq<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/ybjoony\">ybjoony<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/chris-j-h\">chris-j-h<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/washcycle\">washcycle<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/ms-lolo\">ms-lolo<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/violetviolinist\">violetviolinist<\/a><\/li>\n<\/ul>\n<p>Cheers!<\/p>\n<p><!-- FOOTER: DO NOT EDIT OR REMOVE --><\/p>\n<h2>Azure SDK Blog Contributions<\/h2>\n<p>Thank you for reading this Azure SDK blog post! We hope that you learned something new and welcome you to share this post. We are open to Azure SDK blog contributions. Please contact us at <a href=\"&#109;&#x61;&#105;&#x6c;&#116;&#x6f;&#58;&#x61;z&#115;&#x64;&#107;&#x62;&#108;&#x6f;&#103;&#x40;&#109;&#105;&#x63;&#114;&#x6f;&#115;&#x6f;&#102;&#x74;&#46;&#x63;o&#109;\">&#x61;z&#115;&#x64;&#107;&#x62;&#108;&#x6f;&#103;&#x40;&#109;&#105;&#x63;&#114;&#x6f;&#115;&#x6f;&#102;&#x74;&#46;&#x63;o&#109;<\/a> with your topic and we&#8217;ll get you setup as a guest blogger.<\/p>\n<ul>\n<li>Azure SDK Website: <a href=\"https:\/\/aka.ms\/azsdk\">aka.ms\/azsdk<\/a><\/li>\n<li>Azure SDK Intro (3 minute video): <a href=\"https:\/\/aka.ms\/azsdk\/intro\">aka.ms\/azsdk\/intro<\/a><\/li>\n<li>Azure SDK Intro Deck (PowerPoint deck): <a href=\"https:\/\/aka.ms\/azsdk\/intro\/deck\">aka.ms\/azsdk\/intro\/deck<\/a><\/li>\n<li>Azure SDK Releases: <a href=\"https:\/\/aka.ms\/azsdk\/releases\">aka.ms\/azsdk\/releases<\/a><\/li>\n<li>Azure SDK Blog: <a href=\"https:\/\/aka.ms\/azsdk\/blog\">aka.ms\/azsdk\/blog<\/a><\/li>\n<li>Azure SDK Twitter: <a href=\"https:\/\/twitter.com\/AzureSDK\">twitter.com\/AzureSDK<\/a><\/li>\n<li>Azure SDK Design Guidelines: <a href=\"https:\/\/aka.ms\/azsdk\/guide\">aka.ms\/azsdk\/guide<\/a><\/li>\n<li>Azure SDKs &amp; Tools: <a href=\"https:\/\/azure.microsoft.com\/downloads\">azure.microsoft.com\/downloads<\/a><\/li>\n<li>Azure SDK Central Repository: <a href=\"https:\/\/github.com\/azure\/azure-sdk#azure-sdk\">github.com\/azure\/azure-sdk<\/a><\/li>\n<li>Azure SDK for .NET: <a href=\"https:\/\/github.com\/azure\/azure-sdk-for-net\">github.com\/azure\/azure-sdk-for-net<\/a><\/li>\n<li>Azure SDK for Java: <a href=\"https:\/\/github.com\/azure\/azure-sdk-for-java\">github.com\/azure\/azure-sdk-for-java<\/a><\/li>\n<li>Azure SDK for Python: <a href=\"https:\/\/github.com\/azure\/azure-sdk-for-python\">github.com\/azure\/azure-sdk-for-python<\/a><\/li>\n<li>Azure SDK for JavaScript\/TypeScript: <a href=\"https:\/\/github.com\/azure\/azure-sdk-for-js\">github.com\/azure\/azure-sdk-for-js<\/a><\/li>\n<li>Azure SDK for Android: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-android\">github.com\/Azure\/azure-sdk-for-android<\/a><\/li>\n<li>Azure SDK for iOS: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-ios\">github.com\/Azure\/azure-sdk-for-ios<\/a><\/li>\n<li>Azure SDK for Go: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-go\">github.com\/Azure\/azure-sdk-for-go<\/a><\/li>\n<li>Azure SDK for C: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-c\">github.com\/Azure\/azure-sdk-for-c<\/a><\/li>\n<li>Azure SDK for C++: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-cpp\">github.com\/Azure\/azure-sdk-for-cpp<\/a><\/li>\n<\/ul>\n<p><!-- FOOTER: DO NOT EDIT OR REMOVE --><\/p>\n","protected":false},"excerpt":{"rendered":"<p>An introduction of the new features in the Azure Identity library, including changes to DefaultAzureCredential, new credential additions, more configurations, and other improvements.<\/p>\n","protected":false},"author":31991,"featured_media":350,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[734,706,158,160,705],"class_list":["post-369","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure-sdk","tag-azure","tag-azuresdk","tag-identity","tag-java","tag-sdk"],"acf":[],"blog_post_summary":"<p>An introduction of the new features in the Azure Identity library, including changes to DefaultAzureCredential, new credential additions, more configurations, and other improvements.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts\/369","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/users\/31991"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/comments?post=369"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts\/369\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/media\/350"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/media?parent=369"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/categories?post=369"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/tags?post=369"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}