{"id":1654,"date":"2021-10-21T18:53:41","date_gmt":"2021-10-22T01:53:41","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/azure-sdk\/?p=1654"},"modified":"2021-10-22T14:50:15","modified_gmt":"2021-10-22T21:50:15","slug":"announcing-the-azure-identity-2-0-client-library-and-plugin-packages-for-javascript","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/azure-sdk\/announcing-the-azure-identity-2-0-client-library-and-plugin-packages-for-javascript\/","title":{"rendered":"Announcing the Azure Identity 2.0 client library and plugin packages for JavaScript"},"content":{"rendered":"<h2>Announcing the Azure Identity 2.0 client library and plugin packages for JavaScript<\/h2>\n<p>For the last several months, the Azure SDK team has been building the next major iteration (version 2.0) of the Azure Identity client library for JavaScript (<a href=\"https:\/\/npmjs.com\/package\/@azure\/identity\">@azure\/identity<\/a>). Version 2.0 reached General Availability (GA) on October 15, 2021. As the cornerstone of our Azure Active Directory authentication\/authorization workflow, this new major version of <code>@azure\/identity<\/code> includes several improvements to the developer experience. Included are changes that reduce friction for developers who need to use <code>@azure\/identity<\/code> without native machine-code (NMC) dependencies.<\/p>\n<p>This article focuses on the new plugin API and packages. Our goals for this iteration of the Identity library required a breaking change and a new major version. We also made a handful of other improvements to enhance the developer experience of using <code>@azure\/identity<\/code> while largely maintaining API compatibility with the previous version. Some improvements include:<\/p>\n<ul>\n<li>A backend rework that uses the latest versions, features, and default settings of the Microsoft Authentication Library (MSAL).<\/li>\n<li><code>InteractiveBrowserCredential<\/code> now uses the Authorization Code Flow with Proof Key for Code Exchange (PKCE) by default. This change follows modern best practices for OAuth2\/OpenID Connect authentication, instead of the implicit grant flow used in previous iterations.<\/li>\n<li>The credentials&#8217; constructors and <code>getToken<\/code> implementations now evaluate certain error cases differently, and no longer produce <code>null<\/code>, instead throwing errors in all error cases.<\/li>\n<\/ul>\n<p>To migrate your app to version 2.0 of the Identity library, see the <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-js\/blob\/main\/sdk\/identity\/identity\/migration-v1-v2.md\">Migration guide<\/a>.<\/p>\n<h2>Plugin packages<\/h2>\n<p>The previous iteration of the Identity library optionally depended on the <a href=\"https:\/\/npmjs.com\/package\/keytar\"><code>keytar<\/code><\/a> package. The package allowed access to the Azure account credentials stored in Visual Studio (VS) Code&#8217;s <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=ms-vscode.azure-account\">Azure Account extension<\/a>. To support the goals for the next iteration of Identity, a new persistent token caching feature was introduced. This feature:<\/p>\n<ul>\n<li>Enables caching of access tokens between process sessions in a secure store.<\/li>\n<li>Required a dependency on <a href=\"https:\/\/www.npmjs.com\/package\/@azure\/msal-node-extensions\">@azure\/msal-node-extensions<\/a>, which relies on NMC to communicate with the Windows Data Protection API.<\/li>\n<\/ul>\n<p>Several customers reported issues resulting from our dependence on these NMC modules, even &#8220;peer&#8221; or &#8220;optional&#8221; dependence. For example, some customers were unable or reasonably unwilling to build or use the modules because of security concerns. Sometimes security constraints in their CI\/CD environments were to blame. Also, the newest versions of <code>keytar<\/code> provide prebuilt binaries for many of the most common runtime platforms; however, there are situations that cause the <code>keytar<\/code> installation to reject these prebuilt binaries and attempt to build itself. The <code>@azure\/msal-node-extensions<\/code> package doesn&#8217;t provide prebuilt binaries at this time. A build is always required to use it. Building these packages requires a full C\/C++ build toolchain, such as:<\/p>\n<ul>\n<li>VS C++ build tools on Windows<\/li>\n<li>XCode Command-Line tools on macOS<\/li>\n<li>GCC\/Clang and development headers on Linux<\/li>\n<\/ul>\n<p>These requirements and the confusion around them added friction to the development process. The result was an unsatisfactory first-time experience with the <code>@azure\/identity<\/code> package.<\/p>\n<p>In the 2.0 release of <code>@azure\/identity<\/code>, we&#8217;ve introduced a plugin API and two plugin packages. The new plugin architecture allows us to deliver an <code>@azure\/identity<\/code> package that&#8217;s free of NMC dependencies by default\u2014not even &#8220;optional&#8221; or &#8220;peer&#8221; dependencies. However, it also allows us to support use cases that rely on NMC implementations through plugin packages. The plugin packages encapsulate these NMC implementations, and can be used in tandem with the <code>@azure\/identity<\/code> package to augment its functionality and include those features.<\/p>\n<p><strong>Developer Note:<\/strong> The plugin packages were originally classified as &#8220;extension&#8221; packages. After all, they &#8220;extend&#8221; the functionality of the <code>@azure\/identity<\/code> package. Through UX studies and testing, we learned that this &#8220;extension&#8221; terminology could be confusing. Study participants often confused the <code>@azure\/identity-vscode<\/code> package with an &#8220;extension&#8221; of VS Code itself. VS Code uses the same term to describe its <a href=\"https:\/\/marketplace.visualstudio.com\/vscode\">marketplace extensions<\/a>. As a result, we decided to use the term &#8220;plugin&#8221; instead, to reduce this confusion, especially as one of our plugin packages relates to VS Code!<\/p>\n<h3>Use a plugin package<\/h3>\n<p>All plugin packages follow the same basic structure. A new top-level function, named <code>useIdentityPlugin<\/code>, is exported from <code>@azure\/identity<\/code>. Apps can use this function to add a plugin implementation to the <code>@azure\/identity<\/code> package at runtime. The app code should call this function as early as possible. For example, in the module\/script body immediately after importing the <code>@azure\/identity<\/code> package. The following sample shows the initialization of the <code>@azure\/identity-vscode<\/code> package (discussed further below):<\/p>\n<pre><code class=\"language-javascript\">import { vsCodePlugin } from \"@azure\/identity-vscode\";\r\nimport { useIdentityPlugin, DefaultAzureCredential } from \"@azure\/identity\";\r\n\r\n\/\/ This function should be called once, as soon as possible in the execution flow of the app.\r\nuseIdentityPlugin(vsCodePlugin);\r\n\r\n\/\/ Now, my app is augmented with the features of the VSCode plugin, which enables `DefaultAzureCredential` to\r\n\/\/ search the VS Code Azure Account extension's token cache and use its session.\r\n\r\nasync function main() {\r\n    const credential = new DefaultAzureCredential();\r\n\r\n    \/\/ Use the credential to authenticate a service client from an Azure SDK package, such as `@azure\/storage-blob`.\r\n}\r\n\r\nmain().catch((error) =&gt; {\r\n    console.error(error);\r\n    process.exit(1);\r\n})<\/code><\/pre>\n<h3><code>@azure\/identity-vscode<\/code><\/h3>\n<p>This plugin enables <code>VisualStudioCodeCredential<\/code>, which relies on <code>keytar<\/code> to search the VS Code Azure Account extension&#8217;s token cache and use its stored session. Without this plugin, <code>VisualStudioCodeCredential<\/code> instances will throw an error that directs the reader to install it. Since <code>VisualStudioCodeCredential<\/code> is part of the <code>DefaultAzureCredential<\/code> chain, this plugin also enables VS Code Azure Account authentication in <code>DefaultAzureCredential<\/code> instances. Previously, we only required that you install the <code>keytar<\/code> package. As such, this breaking change in <code>@azure\/identity<\/code> 2.0 requires a change to your app code to continue using this credential type.<\/p>\n<h4>Before<\/h4>\n<pre><code class=\"language-javascript\">import { VisualStudioCodeCredential } from \"@azure\/identity\";\r\n\r\nasync function main() {\r\n    const credential = new VisualStudioCodeCredential();\r\n\r\n    \/\/ Somewhere in the execution of your app, `credential.getToken` will be called, and it will throw an error.\r\n}\r\n\r\nmain().catch((error) =&gt; {\r\n    console.error(error);\r\n    process.exit(1);\r\n});<\/code><\/pre>\n<p>With the previous iteration of the <code>@azure\/identity<\/code> package, this app would execute as expected as long as the <code>keytar<\/code> package is available. In the new iteration, this app yields the following error message:<\/p>\n<pre><code>CredentialUnavailableError: No implementation of `VisualStudioCodeCredential` is available. You must install the identity-vscode plugin package (`npm install --save-dev @azure\/identity-vscode`) and enable it by importing `useIdentityPlugin` from `@azure\/identity` and calling `useIdentityPlugin(vsCodePlugin)` before creating a `VisualStudioCodeCredential`.\r\n    at VisualStudioCodeCredential.getToken (...\/node_modules\/@azure\/identity\/src\/credentials\/visualStudioCodeCredential.ts:184:13)<\/code><\/pre>\n<h4>After<\/h4>\n<p>To resolve this error, follow the instructions in the error message by:<\/p>\n<ol>\n<li>Installing the <code>@azure\/identity-vscode<\/code> package.\n<pre><code class=\"language-bash\">npm install --save-dev @azure\/identity-vscode<\/code><\/pre>\n<\/li>\n<li>Importing <code>useIdentityPlugin<\/code> from <code>@azure\/identity<\/code>.<\/li>\n<li>Importing <code>vsCodePlugin<\/code> from <code>@azure\/identity-vscode<\/code>.<\/li>\n<li>Calling <code>useIdentityPlugin(vsCodePlugin)<\/code>.<\/li>\n<\/ol>\n<pre><code class=\"language-javascript\">import { vsCodePlugin } from \"@azure\/identity-vscode\";\r\nimport { useIdentityPlugin, VisualStudioCodeCredential } from \"@azure\/identity\";\r\n\r\nuseIdentityPlugin(vsCodePlugin);\r\n\r\nasync function main() {\r\n    const credential = new VisualStudioCodeCredential();\r\n\r\n    \/\/ Somewhere in the execution of your app, `credential.getToken` will be called, and it will now work as expected.\r\n}\r\n\r\nmain().catch((error) =&gt; {\r\n    console.error(error);\r\n    process.exit(1);\r\n});<\/code><\/pre>\n<h3><code>@azure\/identity-cache-persistence<\/code><\/h3>\n<p>A second plugin package was added that enables persistent (between process sessions) caching of access tokens. The plugin allows a credential to reuse tokens from a previous Node.js instance. As a result, the authentication flow isn&#8217;t repeated. The tokens are placed in a secure store that requires NMC to access. The store&#8217;s location and configuration is defined by the host operating system:<\/p>\n<ul>\n<li>On Windows, it uses a file that is encrypted using the Windows Data Protection API (DPAPI).<\/li>\n<li>On macOS, it uses the macOS Keychain.<\/li>\n<li>On Linux, it uses <code>libsecret<\/code>, which will itself use a secure store such as the system keyring (depending on the system configuration).<\/li>\n<\/ul>\n<p>This capability can reduce:<\/p>\n<ul>\n<li>The number of times the authentication flow is required while using the app.<\/li>\n<li>Excessive authentication requests when an app starts if a previous instance&#8217;s tokens can be reused.<\/li>\n<\/ul>\n<p>Persistent token caching is an opt-in feature. It&#8217;s enabled by using the <code>@azure\/identity-cache-persistence<\/code> plugin package:<\/p>\n<pre><code class=\"language-javascript\">import { useIdentityPlugin, DeviceCodeCredential } from \"@azure\/identity\";\r\nimport { cachePersistencePlugin } from \"@azure\/identity-cache-persistence\";\r\n\r\nuseIdentityPlugin(cachePersistencePlugin);\r\n\r\nasync function main() {\r\n  \/\/ DeviceCodeCredential has an interactive authentication flow, so it will be useful to re-use a pre-existing token\r\n  \/\/ if one exists. If we don't use token cache persistence, a developer\/user will have to enter the code into a web\r\n  \/\/ page once every time the app starts.\r\n  const credential = new DeviceCodeCredential({\r\n    tokenCachePersistenceOptions: {\r\n      \/\/ This option must be set to `true` to enable the feature\r\n      enabled: true,\r\n\r\n      \/\/ If the following option is set to `true`, the access tokens may be stored in an UNSAFE, UNENCRYPTED file.\r\n      \/\/ ONLY ENABLE THIS IF YOU'RE SURE YOU WANT IT.\r\n      \/\/ unsafeAllowUnencryptedStorage: false,\r\n\r\n      \/\/ The cache persistence plugin supports multiple namespaces. If you provide a `name` for the cache, it can only\r\n      \/\/ use tokens from other credentials that used the same `name`.\r\n      \/\/ name: \"myCustomCacheName\"\r\n    }\r\n  });\r\n}\r\n\r\nmain().catch((error) =&gt; {\r\n  console.error(error);\r\n  process.exit(1);\r\n});<\/code><\/pre>\n<p><strong>Note<\/strong>: If <code>tokenCachePersistenceOptions<\/code> are provided without installing and using <code>cachePersistencePlugin<\/code>, the app yields an error similar to the one above for the VS Code Azure Account extension:<\/p>\n<pre><code>Error: Persistent token caching was requested, but no persistence provider was configured. You must install the identity-cache-persistence plugin package (`npm install --save @azure\/identity-cache-persistence`) and enable it by importing `useIdentityPlugin` from `@azure\/identity` and calling `useIdentityPlugin(cachePersistencePlugin)` before using `tokenCachePersistenceOptions`.\r\n    at new MsalNode (...\/node_modules\/@azure\/identity\/src\/msal\/nodeFlows\/nodeCommon.ts:93:13)\r\n    at new MsalDeviceCode (...\/node_modules\/@azure\/identity\/src\/msal\/nodeFlows\/msalDeviceCode.ts:28:5)\r\n    at new DeviceCodeCredential (...\/node_modules\/@azure\/identity\/src\/credentials\/deviceCodeCredential.ts:52:21)<\/code><\/pre>\n<h2>Summary<\/h2>\n<p>The version 2.0 release of <code>@azure\/identity<\/code> contributes to an excellent Azure SDK developer and end-user experience. We created the Azure Identity library as a central, turnkey authentication solution for the Azure SDK. The new plugin architecture and packages enable an even smoother first-use experience. Apps can still opt in to features provided by NMC modules without creating a true dependency on them. These changes grew out of feedback from customers like you who use the Azure SDK for JavaScript to build amazing apps and services. For more information, see the <em>README<\/em> files corresponding to each of the relevant packages:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/azure\/azure-sdk-for-js\/blob\/main\/sdk\/identity\/identity\/README.md\">@azure\/identity<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/azure\/azure-sdk-for-js\/blob\/main\/sdk\/identity\/identity-vscode\/README.md\">@azure\/identity-vscode<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/azure\/azure-sdk-for-js\/blob\/main\/sdk\/identity\/identity-cache-persistence\/README.md\">@azure\/identity-cache-persistence<\/a><\/li>\n<\/ul>\n<p><!-- FOOTER: DO NOT EDIT OR REMOVE --><\/p>\n<p><div  class=\"d-flex justify-content-center\"><a class=\"cta_button_link btn-primary mb-24\" href=\"https:\/\/aka.ms\/azsdk\/releases\" target=\"_blank\">Azure SDK Releases<\/a><\/div><\/p>\n<h2>Azure SDK Blog Contributions<\/h2>\n<p>Thanks for reading this Azure SDK blog post. We hope you learned something new, and we welcome you to share the post. We\u2019re open to Azure SDK blog contributions from our readers. To get started, contact us at <a href=\"mailto:azsdkblog@microsoft.com\">azsdkblog@microsoft.com<\/a> with your idea, and we&#8217;ll set you up 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 REST API Guidelines: <a href=\"https:\/\/aka.ms\/azapi\/guidelines\">aka.ms\/azapi\/guidelines<\/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>Announcing the GA release of the version 2.0 Azure Identity client library for JavaScript\/TypeScript.<\/p>\n","protected":false},"author":73478,"featured_media":1659,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[841,159,24,733],"class_list":["post-1654","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure-sdk","tag-azure-identity","tag-javascript","tag-releases","tag-typescript"],"acf":[],"blog_post_summary":"<p>Announcing the GA release of the version 2.0 Azure Identity client library for JavaScript\/TypeScript.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts\/1654","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\/73478"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/comments?post=1654"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts\/1654\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/media\/1659"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/media?parent=1654"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/categories?post=1654"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/tags?post=1654"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}