From a4bb2c280869c081a08df521ae63472c4ddc2419 Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Sat, 24 Apr 2021 02:22:25 +0000 Subject: [PATCH 01/22] WIP --- .../identity/samples/AzureIdentityExamples.md | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index eacb00c861a7..6ec1aa503f31 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -9,6 +9,17 @@ - [Authenticating Azure Hosted Applications](#authenticating-azure-hosted-applications) - [Chaining credentials](#chaining-credentials) - [Authenticating With Azure Stack using Azure Identity](#authenticating-with-azure-stack-using-azure-identity) +- [Authenticating With Azure Stack using Azure Identity](#authenticating-with-azure-stack-using-azure-identity) +- [Advanced Examples](#advanced-examples) + - [Custom Credentials](#custom-credentials) + - [Authenticating with a pre-fetched access token](authenticating-with-a-pre-fetched-access-token). + - [Authenticating with MSAL directly](authenticating-with-msal-directly). + - [Authenticating with the Confidential Client](authenticating-with-the-confidential-client). + - [Authenticating with the On Behalf Flow](authenticating-with-the-on-behalf-flow). + - [Authenticating with Key Vault Certificates](#authenticating-with-key-vault-certificates) + - [Rolling Certificates](#rolling-certificates) + +### On Behalf Flow ## Introduction @@ -431,6 +442,110 @@ function main() { } ``` +## Advanced Examples + +With all the information given so far, we can explore some advanced usages of the `@azure/identity` credentials. + +### Custom Credentials + +The `@azure/identity` library covers a broad range of Azure Active Directory authentication scenarios. However, it's possible the credential implementations provided might not meet the specific needs your application, or an application might want to avoid taking a dependency on the `@azure/identity` library. + +In this section we'll examine some example cases in which it might make sense to write a credential on your own. + +#### Authenticating with a pre-fetched access token + +The `@azure/identity` library does not contain a `TokenCredential` implementation which can be constructed directly with an `AccessToken`. This is intentionally omitted as a main line scenario as access tokens expire frequently and have constrained usage. However, there are some scenarios where authenticating a service client with a pre-fetched token is necessary. + +In this example, `StaticTokenCredential` implements the `TokenCredential` abstraction. It takes a pre-fetched access token in its constructor as an `AccessToken`, and simply returns that from its implementation of `getToken()`. + +```ts +class StaticTokenCredential implements TokenCredential { + constructor(private accessToken: AccessToken) { + } + async getToken(): Promise { + return this.accessToken; + } +} +``` + +Once the application has defined this credential type instances of it can be used to authenticate Azure SDK clients. The following example shows an how an application already using some other mechanism for acquiring tokens (in this case the hypothetical method `getTokenForScope()`) could use the `StaticTokenCredential` to authenticate a `BlobClient`. + +```C# Snippet:StaticTokenCredentialUsage +const token = getTokenForScope("https://storage.azure.com/.default"); + +const credential = new StaticTokenCredential(token); + +const client = new BlobClient("https://aka.ms/bloburl", credential); +``` + +It should be noted when using this custom credential type, it is the responsibility of the caller to ensure that the token is valid, and contains the correct claims needed to authenticate calls from the particular service client. For instance in the above case the token must have the scope "https://storage.azure.com/.default" to authorize calls to Azure Blob Storage. + +#### Authenticating with MSAL Directly + +Some applications already use the MSAL library's `ConfidentialClientApplication` or `PublicClientApplication` to authenticate portions of their application. In these cases the application might want to use the same to authenticate Azure SDK clients so to take advantage of token caching the client application is doing and prevent unnecessary authentication calls or user prompting. + +#### Authenticating with the Confidential Client + +In this example the `ConfidentialClientApplicationCredential` is constructed with an instance of `ConfidentialClientApplication` it then implements `getToken()` using the `acquireTokenByClientCredential()` method to acquire a token. + +```ts +class ConfidentialClientCredential implements TokenCredential { + constructor (private confidentialApp: msalNode.ConfidentialClientApplication) { + } + async getToken(scopes: string | string[]): Promise { + return this.confidentialApp.acquireTokenByClientCredential({ scopes: Array.isArray(scopes) ? scopes : [scopes] }); + } +} +``` + +The users could then use the `ConfidentialClientApplicationCredential` to authenticate a `BlobClient` with an MSAL `ConfidentialClientApplication`: + +```ts +const confidentialClient = new msalNode.ConfidentialClientApplication({ + // MSAL Configuration +}); + +const client = new SecretClient("https://myvault.vault.azure.net/", new ConfidentialClientCredential(confidentialClient)); +``` + +### Authenticating with the On Behalf Of Flow + +Currently the `@azure/identity` library doesn't provide a credential type for clients which need to authenticate via the On Behalf Of flow. While future support for this is planned, users requiring this immediately will have to implement their own `TokenCredential` class. + +In this example the `OnBehalfOfCredential` accepts a client Id, client secret, and a user's access token. It then creates an instance of `ConfidentialClientApplication` from MSAL to obtain an OBO token which can be used to authenticate client requests. + +```ts +class OnBehalfOfCredential implements TokenCredential { + private confidentialApp: msalNode.ConfidentialClientApplication; + + constructor (private clientId: string, private clientSecret: string, private userAccessToken: string) { + this.confidentialApp = new msalNode.ConfidentialClientApplication({ + auth: { + clientId, + clientSecret + } + }); + } + async getToken(scopes: string | string[]): Promise { + return this.confidentialApp.acquireTokenOnBehalfOf({ + scopes: Array.isArray(scopes) ? scopes : [scopes], + oboAssertion: this.userAccessToken + }); + } +} +``` + +The following example shows an how the `OnBehalfOfCredential` could be used to authenticate a `SecretClient`. + +```ts +const oboCredential = new OnBehalfOfCredential(clientId, clientSecret, userAccessToken); + +const client = new SecretClient("https://myvault.vault.azure.net/", oboCredential); +``` +### Authenticating with Key Vault Certificates + +### Rolling Certificates + [azure_cli]: https://docs.microsoft.com/cli/azure From 2a465ac6fb8c97a1390cf9b91f904501329df3a4 Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Mon, 26 Apr 2021 23:50:38 +0000 Subject: [PATCH 02/22] wip --- .../identity/samples/AzureIdentityExamples.md | 159 ++++++++++++++++-- 1 file changed, 149 insertions(+), 10 deletions(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index 6ec1aa503f31..ef3595023c3c 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -1,6 +1,7 @@ # Table of contents - [Introduction](#introduction) +- [Requirements](#requirements) - [Authenticating client side browser applications](#authenticating-client-side-browser-applications) - [Authenticating server side applications](#authenticating-server-side-applications) - [Authenticating User Accounts](#authenticating-user-accounts) @@ -19,12 +20,22 @@ - [Authenticating with Key Vault Certificates](#authenticating-with-key-vault-certificates) - [Rolling Certificates](#rolling-certificates) -### On Behalf Flow - ## Introduction Authenticating your application, users, and principals is an integral part of working with the Azure Client Libraries. The Azure Identity library provides multiple ways to authenticate, each with a flexible configuration that covers most scenarios. In this document we will go over some of these scenarios and provide small examples that can be used as a starting point for your needs. +## Requirements + +Many of these samples will require you to have installed the following packages: + +- [@azure/identity](https://www.npmjs.com/package/@azure/identity). +- [@azure/core-http](https://www.npmjs.com/package/@azure/core-http). +- [@azure/keyvault-secrets](https://www.npmjs.com/package/@azure/keyvault-secrets). + +You can install them with: `npm i @azure/identity @azure/core-http @azure/keyvault-secrets`. + +In the cases in which other packages are necessary, we will mention which packages and how to install them. + ## Authenticating client side browser applications For client side applications running in the browser, the `InteractiveBrowserCredential` provides the simplest user authentication experience and is the only credential type that we support in the browser. To get started, you will want to configure an AAD application for interactive browser authentication. Please refer to the [Single-page application: App registration guide](https://docs.microsoft.com/azure/active-directory/develop/scenario-spa-app-registration) for additional information on how to configure your app registration for the browser. @@ -250,7 +261,7 @@ function withDeviceCodeCredential() { This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `UsernamePasswordCredential`. The user must **not** have Multi-factor auth turned on. -Apart from user name and password, this credential requires you to know the tenant Id and client Id. To get the client Id, first [register your application][quickstart-register-app] +Apart from user name and password, this credential requires you to know the tenant Id and client Id. To get the client Id, first [register your application][quickstart-register-app]. ```ts /** @@ -277,7 +288,7 @@ Next, prompt the user to login at the URL documented at [Microsoft identity plat Then create an API at the redirect URL with the following code to access the Key Vault service. -For a complete example using the authorization code flow in Electron please refer to [our electron sample](https://github.com/Azure/azure-sdk-for-js/blob/master/samples/frameworks/electron/ts/src/authProvider.ts) +For a complete example using the authorization code flow in Electron please refer to [our electron sample](https://github.com/Azure/azure-sdk-for-js/blob/master/samples/frameworks/electron/ts/src/authProvider.ts). ```ts /** @@ -384,7 +395,7 @@ function withUserManagedIdentityCredential() { ## Chaining credentials -The `ChainedTokenCredential` class provides the ability to link together multiple credential instances to be tried sequentially when authenticating. The following example demonstrates creating a credential which will attempt to authenticate a `SecretClient` from the [@azure/keyvault-secrerts][secrets_client_library] using managed identity, and fall back to certificate authentication if a managed identity is unavailable in the current environment. +The `ChainedTokenCredential` class provides the ability to link together multiple credential instances to be tried sequentially when authenticating. The following example demonstrates creating a credential which will attempt to authenticate a `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] using managed identity, and fall back to certificate authentication if a managed identity is unavailable in the current environment. ```ts function withChainedTokenCredential() { @@ -454,11 +465,15 @@ In this section we'll examine some example cases in which it might make sense to #### Authenticating with a pre-fetched access token +Our package `@azure/core-http` exports a `TokenCredential` interface which is used by the `@azure/identity` package to define a common public API for all of the Identity credentials that we offer. + The `@azure/identity` library does not contain a `TokenCredential` implementation which can be constructed directly with an `AccessToken`. This is intentionally omitted as a main line scenario as access tokens expire frequently and have constrained usage. However, there are some scenarios where authenticating a service client with a pre-fetched token is necessary. In this example, `StaticTokenCredential` implements the `TokenCredential` abstraction. It takes a pre-fetched access token in its constructor as an `AccessToken`, and simply returns that from its implementation of `getToken()`. ```ts +import { TokenCredential } from '@azure/core-http'; + class StaticTokenCredential implements TokenCredential { constructor(private accessToken: AccessToken) { } @@ -468,14 +483,16 @@ class StaticTokenCredential implements TokenCredential { } ``` -Once the application has defined this credential type instances of it can be used to authenticate Azure SDK clients. The following example shows an how an application already using some other mechanism for acquiring tokens (in this case the hypothetical method `getTokenForScope()`) could use the `StaticTokenCredential` to authenticate a `BlobClient`. +Once the application has defined this credential type instances of it can be used to authenticate Azure SDK clients. The following example shows an how an application already using some other mechanism for acquiring tokens (in this case the hypothetical method `getTokenForScope()`) could use the `StaticTokenCredential` to authenticate a `SecretClient` from `@azure/keyvault-secrets. + +```ts +import { SecretClient } from "@azure/keyvault-secrets"; -```C# Snippet:StaticTokenCredentialUsage -const token = getTokenForScope("https://storage.azure.com/.default"); +const token = getTokenForScope("https://vault.azure.net/.default"); const credential = new StaticTokenCredential(token); -const client = new BlobClient("https://aka.ms/bloburl", credential); +const client = new SecretClient("https://myvault.vault.azure.net/", credential); ``` It should be noted when using this custom credential type, it is the responsibility of the caller to ensure that the token is valid, and contains the correct claims needed to authenticate calls from the particular service client. For instance in the above case the token must have the scope "https://storage.azure.com/.default" to authorize calls to Azure Blob Storage. @@ -488,7 +505,12 @@ Some applications already use the MSAL library's `ConfidentialClientApplication` In this example the `ConfidentialClientApplicationCredential` is constructed with an instance of `ConfidentialClientApplication` it then implements `getToken()` using the `acquireTokenByClientCredential()` method to acquire a token. +Make sure to install `msal-node` with: `npm i @azure/msal-node`. Then you'll be able to write code similar to the following: + ```ts +import { TokenCredential } from "@azure/core-http"; +import * as msalNode from "@azure/msal-node"; + class ConfidentialClientCredential implements TokenCredential { constructor (private confidentialApp: msalNode.ConfidentialClientApplication) { } @@ -498,9 +520,12 @@ class ConfidentialClientCredential implements TokenCredential { } ``` -The users could then use the `ConfidentialClientApplicationCredential` to authenticate a `BlobClient` with an MSAL `ConfidentialClientApplication`: +Users could then use the `ConfidentialClientApplicationCredential` to authenticate a `SecretClient` from `@azure/keyvault-secrets` with an MSAL `ConfidentialClientApplication`: ```ts +import { SecretClient } from "@azure/keyvault-secrets"; +import * as msalNode from "@azure/msal-node"; + const confidentialClient = new msalNode.ConfidentialClientApplication({ // MSAL Configuration }); @@ -515,6 +540,9 @@ Currently the `@azure/identity` library doesn't provide a credential type for cl In this example the `OnBehalfOfCredential` accepts a client Id, client secret, and a user's access token. It then creates an instance of `ConfidentialClientApplication` from MSAL to obtain an OBO token which can be used to authenticate client requests. ```ts +import { TokenCredential } from "@azure/core-http"; +import * as msalNode from "@azure/msal-node"; + class OnBehalfOfCredential implements TokenCredential { private confidentialApp: msalNode.ConfidentialClientApplication; @@ -544,8 +572,119 @@ const client = new SecretClient("https://myvault.vault.azure.net/", oboCredentia ``` ### Authenticating with Key Vault Certificates +Azure Key Vault allows users to create certificates that can be used to authenticate Azure SDK clients. + +Certificates can be created through different means. You may follow any of the following approaches: + +- [Quickstart: Set and retrieve a certificate from Azure Key Vault using the Azure portal](https://docs.microsoft.com/en-us/azure/key-vault/certificates/quick-create-portal). +- [Quickstart: Azure Key Vault certificate client library for JavaScript (version 4)](https://docs.microsoft.com/en-us/azure/key-vault/certificates/quick-create-node). + +Once you have a certificate, you may export the certificate with the Azure CLI following the steps at: [Export certificates from Azure Key Vault](https://docs.microsoft.com/en-us/azure/key-vault/certificates/how-to-export-certificate?tabs=azure-cli). + +You can also export your certificate through the portal by going to your Key Vault, going to a specific certificate, then downloading the certificate in PFX/PEM format. + +Once you have a Key Vault certificate downloaded, go to Azure Active Directory, find the Enterprise app you want to authenticate against, go to `Certificates & secrets` and then upload the certificate. + +After that, you'll be able to authenticate by pointing the `@azure/identity`'s `ClientCertificateCredential` to the path where your PEM certificate is, as follows: + +```ts +const credential = new ClientCertificateCredential( + "", + "", + " +); +``` + ### Rolling Certificates +Long running applications may have the need to roll certificates during process execution. Certificate rotation is not currently supported by the `ClientCertificateCredential` which treats the certificate used to construct the credential as immutable. This means that any clients constructed with an `ClientCertificateCredential` using a particular cert would fail to authenticate requests after that cert has been rolled and the original is no longer valid. + +However, if an application wants to roll this certificate without creating new service clients, it can accomplish this by creating its own `TokenCredential` implementation which wraps the `ClientCertificateCredential`. The implementation of this custom credential `TokenCredential` would somewhat depend on how the application handles certificate rotation. + +### Explicit rotation + +If the application gets notified of certificate rotations and it can directly respond, it might choose to wrap the `ClientCertificateCredential` in a custom credential which provides a means for rotating the certificate. + +```ts +import { TokenCredential, GetTokenOptions, AccessToken } from '@azure/core-http'; +import { ClientCertificateCredential } from "@azure/identity"; + +class RotatableCertificateCredential implements TokenCredential { + private readonly tenantId: string; + private readonly clientId: string; + private credential: ClientCertificateCredential; + + constructor(tenantId: string, clientId: string, PEMCertificatePath: string) { + this.tenantId = tenantId; + this.clientId = clientId; + this.credential = new ClientCertificateCredential(tenantId, clientId, PEMCertificatePath); + } + + async getToken(scopes: string | string[], options?: GetTokenOptions): Promise { + return credential.getToken(scopes, options); + } + + rotateCertificate(PEMCertificatePath: string) { + credential = new ClientCertificateCredential(_tenantId, _clientId, PEMCertificatePath); + } +} +``` + +The above example shows a custom credential type `RotatableCertificateCredential` which provides a `rotateCertificate`. The implementation internally relies on an instance of `ClientCertificateCredential`, and `rotateCertificate` simply replaces this instance with a new one using the new certificate path. + +### Implicit rotation + +Some applications might want to respond to certificate rotations which are external to the application, for instance a separate process rotates the certificate by updating it on disk. Here the application create a custom credential which checks for certificate updates when tokens are requested. + +```ts +import { TokenCredential, GetTokenOptions, AccessToken } from '@azure/core-http'; +import { ClientCertificateCredential } from "@azure/identity"; + +class RotatingCertificateCredential implements TokenCredential { + private readonly tenantId: string; + private readonly clientId: string; + private readonly certificatePath: string; + private promise: Promise | null = null; + private credential: ClientCertificateCredential; + private lastModified: number = 0; + + constructor(tenantId: string, clientId: string, certificatePath: string) { + this.tenantId = tenantId; + this.clientId = clientId; + this.certificatePath = certificatePath; + + refreshCertificate(); + } + + async getToken(scopes: string | string[], options?: GetTokenOptions): Promise { + await refreshCertificate(); + + return this.credential.getToken(scopes, options); + } + + refreshCertificate(): Promise { + if (this.promise) { + return this.promise; + } + return new Promise((resolve, reject) => { + fs.stat(this.certificatePath, (err, stats) => { + if (err) { + reject(err); + } else { + if (this.lastModified < stats.mtime) { + this.lastModified = stats.mtime; + this.credential = new ClientCertificateCredential(this.tenantId, this.clientId, this.certificatePath); + this.promise = null; + } + } + }) + }); + } +} +``` + +In this example the custom credential type `RotatingCertificateCredential` again uses a `ClientCertificateCredential` instance to retrieve tokens. However, in this case it will attempt to refresh the certificate prior to obtaining the token. The method `RefreshCertificate` will query to see if the certificate has changed, and if so it will replace `this.credential` with a new instance of the certificate credential using the same certificate path. + [azure_cli]: https://docs.microsoft.com/cli/azure From ba60cf2b12e6867558ae51e9ed33b247a52fd102 Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Tue, 27 Apr 2021 00:20:24 +0000 Subject: [PATCH 03/22] good for a review --- .../identity/samples/AzureIdentityExamples.md | 165 ++++++++++-------- 1 file changed, 91 insertions(+), 74 deletions(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index ef3595023c3c..2589d8d78cae 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -13,10 +13,10 @@ - [Authenticating With Azure Stack using Azure Identity](#authenticating-with-azure-stack-using-azure-identity) - [Advanced Examples](#advanced-examples) - [Custom Credentials](#custom-credentials) - - [Authenticating with a pre-fetched access token](authenticating-with-a-pre-fetched-access-token). - - [Authenticating with MSAL directly](authenticating-with-msal-directly). - - [Authenticating with the Confidential Client](authenticating-with-the-confidential-client). - - [Authenticating with the On Behalf Flow](authenticating-with-the-on-behalf-flow). + - [Authenticating with a pre-fetched access token](#authenticating-with-a-pre-fetched-access-token). + - [Authenticating with MSAL directly](#authenticating-with-msal-directly). + - [Authenticating with the Confidential Client](#authenticating-with-the-confidential-client). + - [Authenticating with the On Behalf Flow](#authenticating-with-the-on-behalf-flow). - [Authenticating with Key Vault Certificates](#authenticating-with-key-vault-certificates) - [Rolling Certificates](#rolling-certificates) @@ -26,13 +26,13 @@ Authenticating your application, users, and principals is an integral part of wo ## Requirements -Many of these samples will require you to have installed the following packages: +Many of the code samples in this document will require you to have installed the following packages: - [@azure/identity](https://www.npmjs.com/package/@azure/identity). - [@azure/core-http](https://www.npmjs.com/package/@azure/core-http). - [@azure/keyvault-secrets](https://www.npmjs.com/package/@azure/keyvault-secrets). -You can install them with: `npm i @azure/identity @azure/core-http @azure/keyvault-secrets`. +You can install them with: `npm install @azure/identity @azure/core-http @azure/keyvault-secrets`. In the cases in which other packages are necessary, we will mention which packages and how to install them. @@ -439,7 +439,7 @@ else, if the Identity provider of your Azure Stack is Active Directory Federatio The following example demonstrates authenticating a `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] against an Azure Key Vault hosted in Azure Stack. ```ts -function main() { +async function main() { const credential = new ClientSecretCredential( "", "", @@ -463,16 +463,16 @@ The `@azure/identity` library covers a broad range of Azure Active Directory aut In this section we'll examine some example cases in which it might make sense to write a credential on your own. -#### Authenticating with a pre-fetched access token +### Authenticating with a pre-fetched access token Our package `@azure/core-http` exports a `TokenCredential` interface which is used by the `@azure/identity` package to define a common public API for all of the Identity credentials that we offer. -The `@azure/identity` library does not contain a `TokenCredential` implementation which can be constructed directly with an `AccessToken`. This is intentionally omitted as a main line scenario as access tokens expire frequently and have constrained usage. However, there are some scenarios where authenticating a service client with a pre-fetched token is necessary. +The `@azure/identity` library does not contain a `TokenCredential` implementation which can be constructed directly with an `AccessToken`. This is intentionally omitted as a main line scenario as access tokens expire frequently and have constrained usage. However, we understand there may be some scenarios where authenticating a service client with a pre-fetched token is necessary. -In this example, `StaticTokenCredential` implements the `TokenCredential` abstraction. It takes a pre-fetched access token in its constructor as an `AccessToken`, and simply returns that from its implementation of `getToken()`. +In this example, `StaticTokenCredential` implements the `TokenCredential` abstraction. It takes a pre-fetched access token in its constructor as an `AccessToken` (defined on `@azure/core-http`), and simply returns that from its implementation of `getToken()`. ```ts -import { TokenCredential } from '@azure/core-http'; +import { TokenCredential, AccessToken } from '@azure/core-http'; class StaticTokenCredential implements TokenCredential { constructor(private accessToken: AccessToken) { @@ -483,39 +483,45 @@ class StaticTokenCredential implements TokenCredential { } ``` -Once the application has defined this credential type instances of it can be used to authenticate Azure SDK clients. The following example shows an how an application already using some other mechanism for acquiring tokens (in this case the hypothetical method `getTokenForScope()`) could use the `StaticTokenCredential` to authenticate a `SecretClient` from `@azure/keyvault-secrets. +Once the application has defined this credential, it can be used to authenticate Azure SDK clients. The following example shows how an application already using some other mechanism for acquiring tokens (in this case the hypothetical method `getTokenForScope()`) could use the `StaticTokenCredential` to authenticate a `SecretClient` from `@azure/keyvault-secrets`. ```ts import { SecretClient } from "@azure/keyvault-secrets"; -const token = getTokenForScope("https://vault.azure.net/.default"); +async function main() { + const token = getTokenForScope("https://vault.azure.net/.default"); -const credential = new StaticTokenCredential(token); + const credential = new StaticTokenCredential(token); -const client = new SecretClient("https://myvault.vault.azure.net/", credential); + const client = new SecretClient("https://myvault.vault.azure.net/", credential); +} ``` -It should be noted when using this custom credential type, it is the responsibility of the caller to ensure that the token is valid, and contains the correct claims needed to authenticate calls from the particular service client. For instance in the above case the token must have the scope "https://storage.azure.com/.default" to authorize calls to Azure Blob Storage. +It should be noted when using this custom credential type, it is the responsibility of the caller to ensure that the token is valid, and contains the correct claims needed to authenticate calls from the particular service client. For instance in the above case the token must have the scope "https://vault.azure.net/.default" to authorize calls to Azure Blob Storage. -#### Authenticating with MSAL Directly +### Authenticating with MSAL Directly -Some applications already use the MSAL library's `ConfidentialClientApplication` or `PublicClientApplication` to authenticate portions of their application. In these cases the application might want to use the same to authenticate Azure SDK clients so to take advantage of token caching the client application is doing and prevent unnecessary authentication calls or user prompting. +Some applications already use the MSAL library's `ConfidentialClientApplication` or `PublicClientApplication` to authenticate portions of their application. In these cases, the application might want to use the same to authenticate Azure SDK clients, to take advantage of the token caching the MSAL client application is doing, and to prevent unnecessary authentication calls. -#### Authenticating with the Confidential Client +#### Authenticating with the MSAL Confidential Client In this example the `ConfidentialClientApplicationCredential` is constructed with an instance of `ConfidentialClientApplication` it then implements `getToken()` using the `acquireTokenByClientCredential()` method to acquire a token. -Make sure to install `msal-node` with: `npm i @azure/msal-node`. Then you'll be able to write code similar to the following: +Make sure to install `msal-node` with: `npm install @azure/msal-node`. Then you'll be able to write code similar to the following: ```ts -import { TokenCredential } from "@azure/core-http"; +import { TokenCredential, AccessToken } from "@azure/core-http"; import * as msalNode from "@azure/msal-node"; class ConfidentialClientCredential implements TokenCredential { - constructor (private confidentialApp: msalNode.ConfidentialClientApplication) { + constructor(private confidentialApp: msalNode.ConfidentialClientApplication) { } async getToken(scopes: string | string[]): Promise { - return this.confidentialApp.acquireTokenByClientCredential({ scopes: Array.isArray(scopes) ? scopes : [scopes] }); + const result = await this.confidentialApp.acquireTokenByClientCredential({ scopes: Array.isArray(scopes) ? scopes : [scopes] }); + return { + token: result.accessToken, + expiresOnTimestamp: result.expiresOn.getTime() + } } } ``` @@ -526,27 +532,29 @@ Users could then use the `ConfidentialClientApplicationCredential` to authentica import { SecretClient } from "@azure/keyvault-secrets"; import * as msalNode from "@azure/msal-node"; -const confidentialClient = new msalNode.ConfidentialClientApplication({ - // MSAL Configuration -}); +async function main() { + const confidentialClient = new msalNode.ConfidentialClientApplication({ + // MSAL Configuration + }); -const client = new SecretClient("https://myvault.vault.azure.net/", new ConfidentialClientCredential(confidentialClient)); + const client = new SecretClient("https://myvault.vault.azure.net/", new ConfidentialClientCredential(confidentialClient)); +} ``` -### Authenticating with the On Behalf Of Flow +#### Authenticating with the On Behalf Of Flow -Currently the `@azure/identity` library doesn't provide a credential type for clients which need to authenticate via the On Behalf Of flow. While future support for this is planned, users requiring this immediately will have to implement their own `TokenCredential` class. +Currently the `@azure/identity` library doesn't provide a credential type for clients which need to authenticate via the On Behalf Of flow. While future support for this is planned, users currently requiring this will have to implement their own `TokenCredential` class. In this example the `OnBehalfOfCredential` accepts a client Id, client secret, and a user's access token. It then creates an instance of `ConfidentialClientApplication` from MSAL to obtain an OBO token which can be used to authenticate client requests. ```ts -import { TokenCredential } from "@azure/core-http"; +import { TokenCredential, AccessToken } from "@azure/core-http"; import * as msalNode from "@azure/msal-node"; class OnBehalfOfCredential implements TokenCredential { private confidentialApp: msalNode.ConfidentialClientApplication; - constructor (private clientId: string, private clientSecret: string, private userAccessToken: string) { + constructor(private clientId: string, private clientSecret: string, private userAccessToken: string) { this.confidentialApp = new msalNode.ConfidentialClientApplication({ auth: { clientId, @@ -555,10 +563,14 @@ class OnBehalfOfCredential implements TokenCredential { }); } async getToken(scopes: string | string[]): Promise { - return this.confidentialApp.acquireTokenOnBehalfOf({ + const result = await this.confidentialApp.acquireTokenOnBehalfOf({ scopes: Array.isArray(scopes) ? scopes : [scopes], oboAssertion: this.userAccessToken }); + return { + token: result.accessToken, + expiresOnTimestamp: result.expiresOn.getTime() + }; } } ``` @@ -566,15 +578,19 @@ class OnBehalfOfCredential implements TokenCredential { The following example shows an how the `OnBehalfOfCredential` could be used to authenticate a `SecretClient`. ```ts -const oboCredential = new OnBehalfOfCredential(clientId, clientSecret, userAccessToken); +import { SecretClient } from "@azure/keyvault-secrets"; + +async function main() { + const oboCredential = new OnBehalfOfCredential(clientId, clientSecret, userAccessToken); -const client = new SecretClient("https://myvault.vault.azure.net/", oboCredential); + const client = new SecretClient("https://myvault.vault.azure.net/", oboCredential); +} ``` ### Authenticating with Key Vault Certificates Azure Key Vault allows users to create certificates that can be used to authenticate Azure SDK clients. -Certificates can be created through different means. You may follow any of the following approaches: +Certificates can be created through different means. You may follow any of these approaches: - [Quickstart: Set and retrieve a certificate from Azure Key Vault using the Azure portal](https://docs.microsoft.com/en-us/azure/key-vault/certificates/quick-create-portal). - [Quickstart: Azure Key Vault certificate client library for JavaScript (version 4)](https://docs.microsoft.com/en-us/azure/key-vault/certificates/quick-create-node). @@ -583,7 +599,7 @@ Once you have a certificate, you may export the certificate with the Azure CLI f You can also export your certificate through the portal by going to your Key Vault, going to a specific certificate, then downloading the certificate in PFX/PEM format. -Once you have a Key Vault certificate downloaded, go to Azure Active Directory, find the Enterprise app you want to authenticate against, go to `Certificates & secrets` and then upload the certificate. +Once you have a Key Vault certificate downloaded, go to Azure Active Directory, find the Enterprise app you want to authenticate with, go to `Certificates & secrets` and then upload the certificate. After that, you'll be able to authenticate by pointing the `@azure/identity`'s `ClientCertificateCredential` to the path where your PEM certificate is, as follows: @@ -591,7 +607,7 @@ After that, you'll be able to authenticate by pointing the `@azure/identity`'s ` const credential = new ClientCertificateCredential( "", "", - " + "" ); ``` @@ -621,11 +637,11 @@ class RotatableCertificateCredential implements TokenCredential { } async getToken(scopes: string | string[], options?: GetTokenOptions): Promise { - return credential.getToken(scopes, options); + return this.credential.getToken(scopes, options); } rotateCertificate(PEMCertificatePath: string) { - credential = new ClientCertificateCredential(_tenantId, _clientId, PEMCertificatePath); + this.credential = new ClientCertificateCredential(this.tenantId, this.clientId, PEMCertificatePath); } } ``` @@ -639,47 +655,48 @@ Some applications might want to respond to certificate rotations which are exter ```ts import { TokenCredential, GetTokenOptions, AccessToken } from '@azure/core-http'; import { ClientCertificateCredential } from "@azure/identity"; +import * as fs from "fs"; class RotatingCertificateCredential implements TokenCredential { - private readonly tenantId: string; - private readonly clientId: string; - private readonly certificatePath: string; - private promise: Promise | null = null; - private credential: ClientCertificateCredential; - private lastModified: number = 0; - - constructor(tenantId: string, clientId: string, certificatePath: string) { - this.tenantId = tenantId; - this.clientId = clientId; - this.certificatePath = certificatePath; - - refreshCertificate(); - } + private readonly tenantId: string; + private readonly clientId: string; + private readonly certificatePath: string; + private promise: Promise | null = null; + private credential: ClientCertificateCredential; + private lastModified: number = 0; + + constructor(tenantId: string, clientId: string, certificatePath: string) { + this.tenantId = tenantId; + this.clientId = clientId; + this.certificatePath = certificatePath; - async getToken(scopes: string | string[], options?: GetTokenOptions): Promise { - await refreshCertificate(); + this.refreshCertificate(); + } - return this.credential.getToken(scopes, options); - } + async getToken(scopes: string | string[], options?: GetTokenOptions): Promise { + await this.refreshCertificate(); - refreshCertificate(): Promise { - if (this.promise) { - return this.promise; - } - return new Promise((resolve, reject) => { - fs.stat(this.certificatePath, (err, stats) => { - if (err) { - reject(err); - } else { - if (this.lastModified < stats.mtime) { - this.lastModified = stats.mtime; - this.credential = new ClientCertificateCredential(this.tenantId, this.clientId, this.certificatePath); - this.promise = null; - } - } - }) - }); + return this.credential.getToken(scopes, options); + } + + refreshCertificate(): Promise { + if (this.promise) { + return this.promise; } + return new Promise((resolve, reject) => { + fs.stat(this.certificatePath, (err, stats) => { + if (err) { + reject(err); + } else { + if (this.lastModified < stats.mtime.getTime()) { + this.lastModified = stats.mtime.getTime(); + this.credential = new ClientCertificateCredential(this.tenantId, this.clientId, this.certificatePath); + this.promise = null; + } + } + }) + }); + } } ``` From e091f444b6f6c2d8fcd46211de128051e79efd85 Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Tue, 27 Apr 2021 00:33:44 +0000 Subject: [PATCH 04/22] removing en-us --- sdk/identity/identity/samples/AzureIdentityExamples.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index 2589d8d78cae..d3851e8bf28c 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -592,10 +592,10 @@ Azure Key Vault allows users to create certificates that can be used to authenti Certificates can be created through different means. You may follow any of these approaches: -- [Quickstart: Set and retrieve a certificate from Azure Key Vault using the Azure portal](https://docs.microsoft.com/en-us/azure/key-vault/certificates/quick-create-portal). -- [Quickstart: Azure Key Vault certificate client library for JavaScript (version 4)](https://docs.microsoft.com/en-us/azure/key-vault/certificates/quick-create-node). +- [Quickstart: Set and retrieve a certificate from Azure Key Vault using the Azure portal](https://docs.microsoft.com/azure/key-vault/certificates/quick-create-portal). +- [Quickstart: Azure Key Vault certificate client library for JavaScript (version 4)](https://docs.microsoft.com/azure/key-vault/certificates/quick-create-node). -Once you have a certificate, you may export the certificate with the Azure CLI following the steps at: [Export certificates from Azure Key Vault](https://docs.microsoft.com/en-us/azure/key-vault/certificates/how-to-export-certificate?tabs=azure-cli). +Once you have a certificate, you may export the certificate with the Azure CLI following the steps at: [Export certificates from Azure Key Vault](https://docs.microsoft.com/azure/key-vault/certificates/how-to-export-certificate?tabs=azure-cli). You can also export your certificate through the portal by going to your Key Vault, going to a specific certificate, then downloading the certificate in PFX/PEM format. From 611ff8ae54d45b6e15554abe62e45412de582c78 Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Fri, 7 May 2021 00:53:32 +0000 Subject: [PATCH 05/22] feedback by Maor --- .../identity/samples/AzureIdentityExamples.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index d3851e8bf28c..80209b3029a2 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -142,7 +142,9 @@ function withDefaultAzureCredential() { For clients that have a default browser available and for client-side applications running in the browser, the `InteractiveBrowserCredential` provides the simplest user authentication experience. In the sample below an application authenticates a `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] using the `InteractiveBrowserCredential`. -> For client side applications running in the browser, the `InteractiveBrowserCredential` is the only credential type that is supported. You will also need to configure your app registration for single-page applications. Please refer to the [Single-Page application: App registration guide](https://docs.microsoft.com/azure/active-directory/develop/scenario-spa-app-registration) for more information. +For Node.js, if a `clientId` is provided, the Azure Active Directory application will need to be configured to have a "Mobile and desktop applications" redirect endpoint. Follow our guide on [setting up Redirect URIs for Desktop apps that calls to web APIs](https://docs.microsoft.com/azure/active-directory/develop/scenario-desktop-app-registration#redirect-uris). + +For client side applications running in the browser, the `InteractiveBrowserCredential` is the only credential type that is supported. You will also need to configure your app registration for single-page applications. Please refer to the [Single-Page application: App registration guide](https://docs.microsoft.com/azure/active-directory/develop/scenario-spa-app-registration) for more information. ```ts function withInteractiveBrowserCredential() { @@ -455,8 +457,6 @@ async function main() { ## Advanced Examples -With all the information given so far, we can explore some advanced usages of the `@azure/identity` credentials. - ### Custom Credentials The `@azure/identity` library covers a broad range of Azure Active Directory authentication scenarios. However, it's possible the credential implementations provided might not meet the specific needs your application, or an application might want to avoid taking a dependency on the `@azure/identity` library. @@ -472,7 +472,7 @@ The `@azure/identity` library does not contain a `TokenCredential` implementatio In this example, `StaticTokenCredential` implements the `TokenCredential` abstraction. It takes a pre-fetched access token in its constructor as an `AccessToken` (defined on `@azure/core-http`), and simply returns that from its implementation of `getToken()`. ```ts -import { TokenCredential, AccessToken } from '@azure/core-http'; +import { TokenCredential, AccessToken } from "@azure/core-http"; class StaticTokenCredential implements TokenCredential { constructor(private accessToken: AccessToken) { @@ -507,7 +507,9 @@ Some applications already use the MSAL library's `ConfidentialClientApplication` In this example the `ConfidentialClientApplicationCredential` is constructed with an instance of `ConfidentialClientApplication` it then implements `getToken()` using the `acquireTokenByClientCredential()` method to acquire a token. -Make sure to install `msal-node` with: `npm install @azure/msal-node`. Then you'll be able to write code similar to the following: +For more information aboutMSAL, please refer to [the README of the `@azure/msal-node` package][msal_node_readme]. + +> You'll need to install the [@azure/msal-node][msal_node_npm] package for this sample. ```ts import { TokenCredential, AccessToken } from "@azure/core-http"; @@ -590,10 +592,7 @@ async function main() { Azure Key Vault allows users to create certificates that can be used to authenticate Azure SDK clients. -Certificates can be created through different means. You may follow any of these approaches: - -- [Quickstart: Set and retrieve a certificate from Azure Key Vault using the Azure portal](https://docs.microsoft.com/azure/key-vault/certificates/quick-create-portal). -- [Quickstart: Azure Key Vault certificate client library for JavaScript (version 4)](https://docs.microsoft.com/azure/key-vault/certificates/quick-create-node). +Key Vault Certificates can be created through different means. For example, using the Azure CLI: [Quickstart: Set and retrieve a certificate from Azure Key Vault using Azure CLI](https://docs.microsoft.com/en-us/azure/key-vault/certificates/quick-create-cli). Once you have a certificate, you may export the certificate with the Azure CLI following the steps at: [Export certificates from Azure Key Vault](https://docs.microsoft.com/azure/key-vault/certificates/how-to-export-certificate?tabs=azure-cli). @@ -712,3 +711,5 @@ In this example the custom credential type `RotatingCertificateCredential` again [quickstart-register-app]: https://docs.microsoft.com/azure/active-directory/develop/quickstart-register-app [app-register-service-principal]: https://docs.microsoft.com/azure/active-directory/develop/app-objects-and-service-principals [service_principal_azure_powershell]: https://docs.microsoft.com/powershell/azure/create-azure-service-principal-azureps +[msal_node_readme]: https://github.com/sadasant/microsoft-authentication-library-for-js/tree/acquireWithDeviceCode-interval-fix/lib/msal-node +[msal_node_npm]: https://www.npmjs.com/package/@azure/msal-node From d54e2dbe7d55e19aa560c3f15abbffc462442adf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodr=C3=ADguez?= Date: Fri, 7 May 2021 19:45:53 -0400 Subject: [PATCH 06/22] Removing the last en-us --- sdk/identity/identity/samples/AzureIdentityExamples.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index 80209b3029a2..1f8570cd1419 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -592,7 +592,7 @@ async function main() { Azure Key Vault allows users to create certificates that can be used to authenticate Azure SDK clients. -Key Vault Certificates can be created through different means. For example, using the Azure CLI: [Quickstart: Set and retrieve a certificate from Azure Key Vault using Azure CLI](https://docs.microsoft.com/en-us/azure/key-vault/certificates/quick-create-cli). +Key Vault Certificates can be created through different means. For example, using the Azure CLI: [Quickstart: Set and retrieve a certificate from Azure Key Vault using Azure CLI](https://docs.microsoft.com/azure/key-vault/certificates/quick-create-cli). Once you have a certificate, you may export the certificate with the Azure CLI following the steps at: [Export certificates from Azure Key Vault](https://docs.microsoft.com/azure/key-vault/certificates/how-to-export-certificate?tabs=azure-cli). From 4031fa5a80ffe085c4658785ca7a3d8b08e54005 Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Thu, 10 Jun 2021 23:28:11 +0000 Subject: [PATCH 07/22] addressing the core-auth install instructions https://github.com/Azure/azure-sdk-for-js/pull/15031#discussion_r629052094 --- .../identity/samples/AzureIdentityExamples.md | 35 ++++++++----------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index 1f8570cd1419..5bba8411ae8b 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -24,18 +24,6 @@ Authenticating your application, users, and principals is an integral part of working with the Azure Client Libraries. The Azure Identity library provides multiple ways to authenticate, each with a flexible configuration that covers most scenarios. In this document we will go over some of these scenarios and provide small examples that can be used as a starting point for your needs. -## Requirements - -Many of the code samples in this document will require you to have installed the following packages: - -- [@azure/identity](https://www.npmjs.com/package/@azure/identity). -- [@azure/core-http](https://www.npmjs.com/package/@azure/core-http). -- [@azure/keyvault-secrets](https://www.npmjs.com/package/@azure/keyvault-secrets). - -You can install them with: `npm install @azure/identity @azure/core-http @azure/keyvault-secrets`. - -In the cases in which other packages are necessary, we will mention which packages and how to install them. - ## Authenticating client side browser applications For client side applications running in the browser, the `InteractiveBrowserCredential` provides the simplest user authentication experience and is the only credential type that we support in the browser. To get started, you will want to configure an AAD application for interactive browser authentication. Please refer to the [Single-page application: App registration guide](https://docs.microsoft.com/azure/active-directory/develop/scenario-spa-app-registration) for additional information on how to configure your app registration for the browser. @@ -465,14 +453,16 @@ In this section we'll examine some example cases in which it might make sense to ### Authenticating with a pre-fetched access token -Our package `@azure/core-http` exports a `TokenCredential` interface which is used by the `@azure/identity` package to define a common public API for all of the Identity credentials that we offer. +Our package `@azure/core-auth` exports a `TokenCredential` interface which is used by the `@azure/identity` package to define a common public API for all of the Identity credentials that we offer. The `@azure/identity` library does not contain a `TokenCredential` implementation which can be constructed directly with an `AccessToken`. This is intentionally omitted as a main line scenario as access tokens expire frequently and have constrained usage. However, we understand there may be some scenarios where authenticating a service client with a pre-fetched token is necessary. -In this example, `StaticTokenCredential` implements the `TokenCredential` abstraction. It takes a pre-fetched access token in its constructor as an `AccessToken` (defined on `@azure/core-http`), and simply returns that from its implementation of `getToken()`. +In this example, `StaticTokenCredential` implements the `TokenCredential` abstraction. It takes a pre-fetched access token in its constructor as an `AccessToken` (defined on `@azure/core-auth`), and simply returns that from its implementation of `getToken()`. + +> You'll need to install the [@azure/core-auth][core_auth] package for this sample. ```ts -import { TokenCredential, AccessToken } from "@azure/core-http"; +import { TokenCredential, AccessToken } from "@azure/core-auth"; class StaticTokenCredential implements TokenCredential { constructor(private accessToken: AccessToken) { @@ -509,10 +499,10 @@ In this example the `ConfidentialClientApplicationCredential` is constructed wit For more information aboutMSAL, please refer to [the README of the `@azure/msal-node` package][msal_node_readme]. -> You'll need to install the [@azure/msal-node][msal_node_npm] package for this sample. +> You'll need to install the [@azure/msal-node][msal_node_npm] and the the [@azure/core-auth][core_auth] package for this sample. ```ts -import { TokenCredential, AccessToken } from "@azure/core-http"; +import { TokenCredential, AccessToken } from "@azure/core-auth"; import * as msalNode from "@azure/msal-node"; class ConfidentialClientCredential implements TokenCredential { @@ -549,8 +539,10 @@ Currently the `@azure/identity` library doesn't provide a credential type for cl In this example the `OnBehalfOfCredential` accepts a client Id, client secret, and a user's access token. It then creates an instance of `ConfidentialClientApplication` from MSAL to obtain an OBO token which can be used to authenticate client requests. +> You'll need to install the [@azure/core-auth][core_auth] package for this sample. + ```ts -import { TokenCredential, AccessToken } from "@azure/core-http"; +import { TokenCredential, AccessToken } from "@azure/core-auth"; import * as msalNode from "@azure/msal-node"; class OnBehalfOfCredential implements TokenCredential { @@ -620,8 +612,10 @@ However, if an application wants to roll this certificate without creating new s If the application gets notified of certificate rotations and it can directly respond, it might choose to wrap the `ClientCertificateCredential` in a custom credential which provides a means for rotating the certificate. +> You'll need to install the [@azure/core-auth][core_auth] package for this sample. + ```ts -import { TokenCredential, GetTokenOptions, AccessToken } from '@azure/core-http'; +import { TokenCredential, GetTokenOptions, AccessToken } from '@azure/core-auth'; import { ClientCertificateCredential } from "@azure/identity"; class RotatableCertificateCredential implements TokenCredential { @@ -652,7 +646,7 @@ The above example shows a custom credential type `RotatableCertificateCredential Some applications might want to respond to certificate rotations which are external to the application, for instance a separate process rotates the certificate by updating it on disk. Here the application create a custom credential which checks for certificate updates when tokens are requested. ```ts -import { TokenCredential, GetTokenOptions, AccessToken } from '@azure/core-http'; +import { TokenCredential, GetTokenOptions, AccessToken } from '@azure/core-auth'; import { ClientCertificateCredential } from "@azure/identity"; import * as fs from "fs"; @@ -713,3 +707,4 @@ In this example the custom credential type `RotatingCertificateCredential` again [service_principal_azure_powershell]: https://docs.microsoft.com/powershell/azure/create-azure-service-principal-azureps [msal_node_readme]: https://github.com/sadasant/microsoft-authentication-library-for-js/tree/acquireWithDeviceCode-interval-fix/lib/msal-node [msal_node_npm]: https://www.npmjs.com/package/@azure/msal-node +[core_auth]: https://www.npmjs.com/package/@azure/core-auth From 9b56a1b314c120a463827109fbe37aa9ba91cdc2 Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Thu, 10 Jun 2021 23:30:56 +0000 Subject: [PATCH 08/22] removed unnecessary async --- sdk/identity/identity/samples/AzureIdentityExamples.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index 5bba8411ae8b..767ff78a7e3f 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -429,7 +429,7 @@ else, if the Identity provider of your Azure Stack is Active Directory Federatio The following example demonstrates authenticating a `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] against an Azure Key Vault hosted in Azure Stack. ```ts -async function main() { +function main() { const credential = new ClientSecretCredential( "", "", From 00dd868c515df428dfb6636fb176f4c286c9d285 Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Fri, 11 Jun 2021 01:22:31 +0000 Subject: [PATCH 09/22] feedback, but I want to re-read tomorrow --- .../identity/samples/AzureIdentityExamples.md | 242 +++++++++++++----- 1 file changed, 183 insertions(+), 59 deletions(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index 767ff78a7e3f..066964afa49e 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -15,8 +15,9 @@ - [Custom Credentials](#custom-credentials) - [Authenticating with a pre-fetched access token](#authenticating-with-a-pre-fetched-access-token). - [Authenticating with MSAL directly](#authenticating-with-msal-directly). - - [Authenticating with the Confidential Client](#authenticating-with-the-confidential-client). - - [Authenticating with the On Behalf Flow](#authenticating-with-the-on-behalf-flow). + - [Authenticating with the @azure/msal-node Confidential Client](#authenticating-with-the-azure-msal-node-confidential-client). + - [Authenticating with the @azure/msal-node On Behalf Flow](#authenticating-with-the-azure-msal-node-on-behalf-flow). + - [Authenticating with the @azure/msal-browser Public Client](#authenticating-with-the-azure-msal-browser-public-client). - [Authenticating with Key Vault Certificates](#authenticating-with-key-vault-certificates) - [Rolling Certificates](#rolling-certificates) @@ -100,7 +101,7 @@ This example demonstrates authenticating the `SecretClient` from the [@azure/key * The default credential first checks environment variables for configuration. * If environment configuration is incomplete, it will try managed identity. */ -function withDefaultAzureCredential() { +function withDefaultAzureCredential () { const credential = new DefaultAzureCredential(); const client = new SecretClient(`https://key-vault-name.vault.azure.net`, credential); } @@ -116,7 +117,7 @@ For more information about how to configure a user assigned managed identity for /** * The default credential will use the user assigned managed identity with the specified client ID. */ -function withDefaultAzureCredential() { +function withDefaultAzureCredential () { // Alternatively, you may set the environment variable AZURE_CLIENT_ID="" and omit the `managedIdentityClientId` // option when using `DefaultAzureCredential` - the two approaches are equivalent. const credential = new DefaultAzureCredential({ @@ -135,7 +136,7 @@ For Node.js, if a `clientId` is provided, the Azure Active Directory application For client side applications running in the browser, the `InteractiveBrowserCredential` is the only credential type that is supported. You will also need to configure your app registration for single-page applications. Please refer to the [Single-Page application: App registration guide](https://docs.microsoft.com/azure/active-directory/develop/scenario-spa-app-registration) for more information. ```ts -function withInteractiveBrowserCredential() { +function withInteractiveBrowserCredential () { const credential = new InteractiveBrowserCredential({ tenantId: "", clientId: "" @@ -162,7 +163,7 @@ Set up: /** * Authenticate with client secret. */ -function withClientSecretCredential() { +function withClientSecretCredential () { const credential = new ClientSecretCredential( "", "", @@ -189,7 +190,7 @@ Set up: /** * Authenticate with a client certificate. */ -function withEnvironmentCredential() { +function withEnvironmentCredential () { let credential = new EnvironmentCredential(); const client = new SecretClient("https://key-vault-name.vault.azure.net", credential); } @@ -212,7 +213,7 @@ Set up: /** * Authenticate with a client certificate. */ -function withClientCertificateCredential() { +function withClientCertificateCredential () { let credential = new ClientCertificateCredential( "", "", @@ -226,15 +227,13 @@ function withClientCertificateCredential() { This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `DeviceCodeCredential`. -For more information about how to configure an AAD application for device code flow please refer to [Enable applications for device code flow][device_code_flow]. - > The `DeviceCodeCredential` offers a credential that can be used with little to no setup - the user is free to use whatever browser they choose to complete the authentication process. ```ts /** * Authenticate with a device code. */ -function withDeviceCodeCredential() { +function withDeviceCodeCredential () { let credential = new DeviceCodeCredential( process.env.AZURE_TENANT_ID, process.env.AZURE_CLIENT_ID, @@ -247,6 +246,16 @@ function withDeviceCodeCredential() { } ``` +To authenticate a user through device code flow, use the following steps: + +1. Go to Azure Active Directory in Azure portal and find your app registration. +2. Navigate to the **Authentication** section. +3. Under **Advanced settings**, select `yes` on the option `Enable the following mobile and desktop flows`. + +You also need to be the admin of your tenant to grant consent to your application when you log in for the first time. + +If you can't configure the device code flow option on your Active Directory, then it may require your app to be multi-tenant. To make your app multi-tenant, navigate to the **Authentication** panel, then select **Accounts in any organizational directory**. Then, select _yes_ for Treat application as Public Client. + #### Authenticating a user account with username and password This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `UsernamePasswordCredential`. The user must **not** have Multi-factor auth turned on. @@ -257,7 +266,7 @@ Apart from user name and password, this credential requires you to know the tena /** * Authenticate with a client certificate. */ -function withClientCertificateCredential() { +function withClientCertificateCredential () { let credential = new UsernamePasswordCredential( "", "", @@ -284,7 +293,7 @@ For a complete example using the authorization code flow in Electron please refe /** * Authenticate with authorization code. */ -function withAuthCodeCredential() { +function withAuthCodeCredential () { const credential = new AuthorizationCodeCredential( "", "", @@ -332,7 +341,7 @@ to verify the account has been successfully configured. /** * Authenticate with Azure CLI. */ -function withAzureCliCredential() { +function withAzureCliCredential () { // As you can see in this example, the AzureCliCredential does not take any parameters, // instead relying on the Azure CLI authenticated user to authenticate. const credential = new AzureCliCredential(); @@ -348,7 +357,7 @@ This example demonstrates authenticating the `SecretClient` from the [@azure/key See more about how to configure your Visual Studio Code in the [Azure Account Extension page](https://marketplace.visualstudio.com/items?itemName=ms-vscode.azure-account) ```ts -function withVisualStudioCodeCredential() { +function withVisualStudioCodeCredential () { // As you can see in this example, the AzureCliCredential does not take any parameters, // instead relying on the Azure CLI authenticated user to authenticate. const credential = new AzureCliCredential(); @@ -367,7 +376,7 @@ For more information about how to configure your Azure resource for managed iden /** * Authenticate with a system assigned managed identity. */ -function withSystemAssignedManagedIdentityCredential() { +function withSystemAssignedManagedIdentityCredential () { const credential = new ManagedIdentityCredential(); const client = new SecretClient("https://key-vault-name.vault.azure.net", credential); @@ -376,7 +385,7 @@ function withSystemAssignedManagedIdentityCredential() { /** * Authenticate with a user assigned managed identity. */ -function withUserManagedIdentityCredential() { +function withUserManagedIdentityCredential () { const credential = new ManagedIdentityCredential(""); const client = new SecretClient("https://key-vault-name.vault.azure.net", credential); @@ -388,7 +397,7 @@ function withUserManagedIdentityCredential() { The `ChainedTokenCredential` class provides the ability to link together multiple credential instances to be tried sequentially when authenticating. The following example demonstrates creating a credential which will attempt to authenticate a `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] using managed identity, and fall back to certificate authentication if a managed identity is unavailable in the current environment. ```ts -function withChainedTokenCredential() { +function withChainedTokenCredential () { const credential = new ChainedTokenCredential( new ManagedIdentityCredential(""), new ClientSecretCredential("", "", "") @@ -429,7 +438,7 @@ else, if the Identity provider of your Azure Stack is Active Directory Federatio The following example demonstrates authenticating a `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] against an Azure Key Vault hosted in Azure Stack. ```ts -function main() { +function main () { const credential = new ClientSecretCredential( "", "", @@ -457,7 +466,7 @@ Our package `@azure/core-auth` exports a `TokenCredential` interface which is us The `@azure/identity` library does not contain a `TokenCredential` implementation which can be constructed directly with an `AccessToken`. This is intentionally omitted as a main line scenario as access tokens expire frequently and have constrained usage. However, we understand there may be some scenarios where authenticating a service client with a pre-fetched token is necessary. -In this example, `StaticTokenCredential` implements the `TokenCredential` abstraction. It takes a pre-fetched access token in its constructor as an `AccessToken` (defined on `@azure/core-auth`), and simply returns that from its implementation of `getToken()`. +In this example, `StaticTokenCredential` implements the `TokenCredential` abstraction. It takes a pre-fetched access token in its constructor as an [AccessToken](https://docs.microsoft.com/javascript/api/@azure/core-auth/accesstoken), and simply returns that from its implementation of `getToken()`. > You'll need to install the [@azure/core-auth][core_auth] package for this sample. @@ -465,9 +474,8 @@ In this example, `StaticTokenCredential` implements the `TokenCredential` abstra import { TokenCredential, AccessToken } from "@azure/core-auth"; class StaticTokenCredential implements TokenCredential { - constructor(private accessToken: AccessToken) { - } - async getToken(): Promise { + constructor (private accessToken: AccessToken) {} + async getToken (): Promise { return this.accessToken; } } @@ -478,7 +486,7 @@ Once the application has defined this credential, it can be used to authenticate ```ts import { SecretClient } from "@azure/keyvault-secrets"; -async function main() { +async function main () { const token = getTokenForScope("https://vault.azure.net/.default"); const credential = new StaticTokenCredential(token); @@ -491,29 +499,31 @@ It should be noted when using this custom credential type, it is the responsibil ### Authenticating with MSAL Directly -Some applications already use the MSAL library's `ConfidentialClientApplication` or `PublicClientApplication` to authenticate portions of their application. In these cases, the application might want to use the same to authenticate Azure SDK clients, to take advantage of the token caching the MSAL client application is doing, and to prevent unnecessary authentication calls. +Some applications already use the `@azure/msal-node` or `@azure/msal-browser` to authenticate portions of their application. In these cases, the application might want to use the same to authenticate Azure SDK clients, to take advantage of the token caching the MSAL client application is doing, and to prevent unnecessary authentication calls. -#### Authenticating with the MSAL Confidential Client +#### Authenticating with the @azure/msal-node Confidential Client -In this example the `ConfidentialClientApplicationCredential` is constructed with an instance of `ConfidentialClientApplication` it then implements `getToken()` using the `acquireTokenByClientCredential()` method to acquire a token. +In this example the [ConfidentialClientApplicationCredential](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md) is constructed with an instance of `ConfidentialClientApplication` it then implements `getToken()` using the `acquireTokenByClientCredential()` method to acquire a token. -For more information aboutMSAL, please refer to [the README of the `@azure/msal-node` package][msal_node_readme]. +You'll need to install the [@azure/msal-node][msal_node_npm] and the the [@azure/core-auth][core_auth] package for this sample. -> You'll need to install the [@azure/msal-node][msal_node_npm] and the the [@azure/core-auth][core_auth] package for this sample. +> For more information about MSAL for Node.js, please refer to [the README of the `@azure/msal-node` package][msal_node_readme]. +> For more information about working with the Confidential Client of MSAL, please refer to: [Initialization of MSAL (Node.js)](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md). ```ts import { TokenCredential, AccessToken } from "@azure/core-auth"; import * as msalNode from "@azure/msal-node"; class ConfidentialClientCredential implements TokenCredential { - constructor(private confidentialApp: msalNode.ConfidentialClientApplication) { - } - async getToken(scopes: string | string[]): Promise { - const result = await this.confidentialApp.acquireTokenByClientCredential({ scopes: Array.isArray(scopes) ? scopes : [scopes] }); + constructor (private confidentialApp: msalNode.ConfidentialClientApplication) {} + async getToken (scopes: string | string[]): Promise { + const result = await this.confidentialApp.acquireTokenByClientCredential({ + scopes: Array.isArray(scopes) ? scopes : [scopes] + }); return { token: result.accessToken, expiresOnTimestamp: result.expiresOn.getTime() - } + }; } } ``` @@ -524,22 +534,29 @@ Users could then use the `ConfidentialClientApplicationCredential` to authentica import { SecretClient } from "@azure/keyvault-secrets"; import * as msalNode from "@azure/msal-node"; -async function main() { +async function main () { const confidentialClient = new msalNode.ConfidentialClientApplication({ // MSAL Configuration }); - const client = new SecretClient("https://myvault.vault.azure.net/", new ConfidentialClientCredential(confidentialClient)); + const client = new SecretClient( + "https://myvault.vault.azure.net/", + new ConfidentialClientCredential(confidentialClient) + ); } ``` -#### Authenticating with the On Behalf Of Flow +#### Authenticating with the @azure/msal-node On Behalf Of Flow -Currently the `@azure/identity` library doesn't provide a credential type for clients which need to authenticate via the On Behalf Of flow. While future support for this is planned, users currently requiring this will have to implement their own `TokenCredential` class. +Currently the `@azure/identity` library doesn't provide a credential type for clients which need to authenticate via the [On Behalf of Flow](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-common/docs/request.md#on-behalf-of-flow). While future support for this is planned, users currently requiring this will have to implement their own `TokenCredential` class. In this example the `OnBehalfOfCredential` accepts a client Id, client secret, and a user's access token. It then creates an instance of `ConfidentialClientApplication` from MSAL to obtain an OBO token which can be used to authenticate client requests. -> You'll need to install the [@azure/core-auth][core_auth] package for this sample. +You'll need to install the [@azure/msal-node][msal_node_npm] and the the [@azure/core-auth][core_auth] package for this sample. + +> For more information about MSAL for Node.js, please refer to [the README of the `@azure/msal-node` package][msal_node_readme]. +> For more information about working with the Confidential Client of MSAL, please refer to: [Initialization of MSAL (Node.js)](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md). +> For more information about working with the On Behalf Flow with MSAL, please refer to: [On Behalf of Flow](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-common/docs/request.md#on-behalf-of-flow). ```ts import { TokenCredential, AccessToken } from "@azure/core-auth"; @@ -548,7 +565,11 @@ import * as msalNode from "@azure/msal-node"; class OnBehalfOfCredential implements TokenCredential { private confidentialApp: msalNode.ConfidentialClientApplication; - constructor(private clientId: string, private clientSecret: string, private userAccessToken: string) { + constructor ( + private clientId: string, + private clientSecret: string, + private userAccessToken: string + ) { this.confidentialApp = new msalNode.ConfidentialClientApplication({ auth: { clientId, @@ -556,7 +577,7 @@ class OnBehalfOfCredential implements TokenCredential { } }); } - async getToken(scopes: string | string[]): Promise { + async getToken (scopes: string | string[]): Promise { const result = await this.confidentialApp.acquireTokenOnBehalfOf({ scopes: Array.isArray(scopes) ? scopes : [scopes], oboAssertion: this.userAccessToken @@ -574,12 +595,105 @@ The following example shows an how the `OnBehalfOfCredential` could be used to a ```ts import { SecretClient } from "@azure/keyvault-secrets"; -async function main() { +async function main () { const oboCredential = new OnBehalfOfCredential(clientId, clientSecret, userAccessToken); const client = new SecretClient("https://myvault.vault.azure.net/", oboCredential); } ``` + +#### Authenticating with the @azure/msal-browser Public Client + +While `@azure/identity` provides some browser support, for users that need the full set of features provided by `@azure/msal-browser`, it is possible to implement a `TokenCredential` on top of MSAL's public API for the browsers. + +You'll need to install the [@azure/msal-browser][msal_browser_npm] and the the [@azure/core-auth][core_auth] package for this sample. + +> For more information about MSAL for browsers, please refer to [the README of the `@azure/msal-browser` package][msal_browser_readme]. + +For this example, we will define a `BrowserCredential` class that has a `getToken` method (which will use the Silent Authentication flow, retrieving the account from memory, as we want to prevent unnecessary redirections), and also a `prepare()` method that will try either to check if the account has previously authenticated, or to parse the redirection URI values if present, also a `hasAuthenticated` method which can be used to know if the authentication has taken place, and finally a `loginRedirect` method, which if called will trigger the authentication via redirection. + +```ts +import { TokenCredential, AccessToken } from "@azure/core-auth"; +import * as msalBrowser from "@azure/msal-browser"; + +class BrowserCredential implements TokenCredential { + private publicApp: msalBrowser.PublicClientApplication; + private hasAuthenticated: boolean = false; + + constructor (clientId, redirectUri) { + this.publicApp = new msalBrowser.PublicClientApplication({ + auth: { + clientId, + redirectUri + } + }); + } + + // Either confirm the account already exists in memory, or tries to parse the redirect URI values. + async prepare (): Promise { + try { + if (await this.publicApp.getActiveAccount()) { + this.hasAuthenticated = true; + return; + } + await this.publicApp.handleRedirectPromise(); + this.hasAuthenticated = true; + } catch (e) { + console.error("BrowserCredential prepare() failed", e); + } + } + + // Should be true if prepare() was successful. + isAuthenticated (): boolean { + return this.hasAuthenticated; + } + + // If called, triggers authentication via redirection. + async loginRedirect (scopes: string | string[]): Promise { + const loginRequest = { + scopes: Array.isArray(scopes) ? scopes : [scopes] + }; + await this.app.loginRedirect(loginRequest); + } + + // Tries to retrieve the token without triggering a redirection. + async getToken (scopes: string | string[]): Promise { + if (!this.hasAuthenticated) { + throw new Error("Authentication required"); + } + + const parameters: msalBrowser.SilentRequest = { + account: await this.publicApp.getActiveAccount(), + scopes + }; + + const result = await this.publicApp.acquireTokenSilent(parameters); + return { + token: result.accessToken, + expiresOnTimestamp: result.expiresOn.getTime() + }; + } +} +``` + +The following example shows an how the `BrowserCredential` could be used to authenticate a `ServiceBusClient`. Keep in mind that for this example to work, the redirect URI configured in the AAD application should point to the same page that runs this code originally (for example, `http://localhost:80`): + +```ts +import { ServiceBusClient } from "@azure/service-bus"; + +async function main () { + const browserCredential = new BrowserCredential(clientId, location.origin); + + await browserCredential.prepare(); + + if (!browserCredential.isAuthenticated()) { + await browserCredential.loginRedirect("https://servicebus.azure.net/.default"); + } + + const client = new ServiceBusClient(serviceBusEndpoint, browserCredential); +} +``` + ### Authenticating with Key Vault Certificates Azure Key Vault allows users to create certificates that can be used to authenticate Azure SDK clients. @@ -604,18 +718,18 @@ const credential = new ClientCertificateCredential( ### Rolling Certificates -Long running applications may have the need to roll certificates during process execution. Certificate rotation is not currently supported by the `ClientCertificateCredential` which treats the certificate used to construct the credential as immutable. This means that any clients constructed with an `ClientCertificateCredential` using a particular cert would fail to authenticate requests after that cert has been rolled and the original is no longer valid. +Long running applications may have the need to roll certificates during process execution. Certificate rotation is not currently supported by the `ClientCertificateCredential` which treats the certificate used to construct the credential as immutable. This means that any clients constructed with an `ClientCertificateCredential` using a particular cert would fail to authenticate requests after that cert has been rolled and the original is no longer valid. However, if an application wants to roll this certificate without creating new service clients, it can accomplish this by creating its own `TokenCredential` implementation which wraps the `ClientCertificateCredential`. The implementation of this custom credential `TokenCredential` would somewhat depend on how the application handles certificate rotation. -### Explicit rotation +#### Explicit rotation -If the application gets notified of certificate rotations and it can directly respond, it might choose to wrap the `ClientCertificateCredential` in a custom credential which provides a means for rotating the certificate. +If the application gets notified of certificate rotations and it can directly respond, it might choose to wrap the `ClientCertificateCredential` in a custom credential which provides a means for rotating the certificate. > You'll need to install the [@azure/core-auth][core_auth] package for this sample. ```ts -import { TokenCredential, GetTokenOptions, AccessToken } from '@azure/core-auth'; +import { TokenCredential, GetTokenOptions, AccessToken } from "@azure/core-auth"; import { ClientCertificateCredential } from "@azure/identity"; class RotatableCertificateCredential implements TokenCredential { @@ -623,30 +737,34 @@ class RotatableCertificateCredential implements TokenCredential { private readonly clientId: string; private credential: ClientCertificateCredential; - constructor(tenantId: string, clientId: string, PEMCertificatePath: string) { + constructor (tenantId: string, clientId: string, PEMCertificatePath: string) { this.tenantId = tenantId; this.clientId = clientId; this.credential = new ClientCertificateCredential(tenantId, clientId, PEMCertificatePath); } - async getToken(scopes: string | string[], options?: GetTokenOptions): Promise { + async getToken (scopes: string | string[], options?: GetTokenOptions): Promise { return this.credential.getToken(scopes, options); } - rotateCertificate(PEMCertificatePath: string) { - this.credential = new ClientCertificateCredential(this.tenantId, this.clientId, PEMCertificatePath); + rotateCertificate (PEMCertificatePath: string) { + this.credential = new ClientCertificateCredential( + this.tenantId, + this.clientId, + PEMCertificatePath + ); } } ``` The above example shows a custom credential type `RotatableCertificateCredential` which provides a `rotateCertificate`. The implementation internally relies on an instance of `ClientCertificateCredential`, and `rotateCertificate` simply replaces this instance with a new one using the new certificate path. -### Implicit rotation +#### Implicit rotation -Some applications might want to respond to certificate rotations which are external to the application, for instance a separate process rotates the certificate by updating it on disk. Here the application create a custom credential which checks for certificate updates when tokens are requested. +Some applications might want to respond to certificate rotations which are external to the application, for instance a separate process rotates the certificate by updating it on disk. Here the application create a custom credential which checks for certificate updates when tokens are requested. ```ts -import { TokenCredential, GetTokenOptions, AccessToken } from '@azure/core-auth'; +import { TokenCredential, GetTokenOptions, AccessToken } from "@azure/core-auth"; import { ClientCertificateCredential } from "@azure/identity"; import * as fs from "fs"; @@ -658,7 +776,7 @@ class RotatingCertificateCredential implements TokenCredential { private credential: ClientCertificateCredential; private lastModified: number = 0; - constructor(tenantId: string, clientId: string, certificatePath: string) { + constructor (tenantId: string, clientId: string, certificatePath: string) { this.tenantId = tenantId; this.clientId = clientId; this.certificatePath = certificatePath; @@ -666,13 +784,13 @@ class RotatingCertificateCredential implements TokenCredential { this.refreshCertificate(); } - async getToken(scopes: string | string[], options?: GetTokenOptions): Promise { + async getToken (scopes: string | string[], options?: GetTokenOptions): Promise { await this.refreshCertificate(); return this.credential.getToken(scopes, options); } - refreshCertificate(): Promise { + refreshCertificate (): Promise { if (this.promise) { return this.promise; } @@ -683,11 +801,15 @@ class RotatingCertificateCredential implements TokenCredential { } else { if (this.lastModified < stats.mtime.getTime()) { this.lastModified = stats.mtime.getTime(); - this.credential = new ClientCertificateCredential(this.tenantId, this.clientId, this.certificatePath); + this.credential = new ClientCertificateCredential( + this.tenantId, + this.clientId, + this.certificatePath + ); this.promise = null; } } - }) + }); }); } } @@ -705,6 +827,8 @@ In this example the custom credential type `RotatingCertificateCredential` again [quickstart-register-app]: https://docs.microsoft.com/azure/active-directory/develop/quickstart-register-app [app-register-service-principal]: https://docs.microsoft.com/azure/active-directory/develop/app-objects-and-service-principals [service_principal_azure_powershell]: https://docs.microsoft.com/powershell/azure/create-azure-service-principal-azureps -[msal_node_readme]: https://github.com/sadasant/microsoft-authentication-library-for-js/tree/acquireWithDeviceCode-interval-fix/lib/msal-node +[msal_node_readme]: https://github.com/sadasant/microsoft-authentication-library-for-js/tree/master/lib/msal-node [msal_node_npm]: https://www.npmjs.com/package/@azure/msal-node +[msal_browser_readme]: https://github.com/sadasant/microsoft-authentication-library-for-js/tree/master/lib/msal-browser +[msal_browser_npm]: https://www.npmjs.com/package/@azure/msal-browser [core_auth]: https://www.npmjs.com/package/@azure/core-auth From 6eb23d2ac7f32cfeef89265276f611bf936c1de9 Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Fri, 11 Jun 2021 01:24:50 +0000 Subject: [PATCH 10/22] small change --- sdk/identity/identity/samples/AzureIdentityExamples.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index 066964afa49e..938abb29c90c 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -133,7 +133,7 @@ For clients that have a default browser available and for client-side applicatio For Node.js, if a `clientId` is provided, the Azure Active Directory application will need to be configured to have a "Mobile and desktop applications" redirect endpoint. Follow our guide on [setting up Redirect URIs for Desktop apps that calls to web APIs](https://docs.microsoft.com/azure/active-directory/develop/scenario-desktop-app-registration#redirect-uris). -For client side applications running in the browser, the `InteractiveBrowserCredential` is the only credential type that is supported. You will also need to configure your app registration for single-page applications. Please refer to the [Single-Page application: App registration guide](https://docs.microsoft.com/azure/active-directory/develop/scenario-spa-app-registration) for more information. +For client side applications running in the browser, the `InteractiveBrowserCredential` is the only credential type that is supported. You will also need to configure your app registration for single-page applications and set the right permissions. Please refer to the [Single-Page application: App registration guide](https://docs.microsoft.com/azure/active-directory/develop/scenario-spa-app-registration) for more information. ```ts function withInteractiveBrowserCredential () { From b3ae5227834b4fccb70e7c298a2a894650d5dd94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodr=C3=ADguez?= Date: Thu, 10 Jun 2021 21:27:55 -0400 Subject: [PATCH 11/22] Update sdk/identity/identity/samples/AzureIdentityExamples.md Co-authored-by: Ramya Rao --- sdk/identity/identity/samples/AzureIdentityExamples.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index ea01e86ff6f1..19546c8ee26c 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -516,9 +516,9 @@ function main () { ### Custom Credentials -The `@azure/identity` library covers a broad range of Azure Active Directory authentication scenarios. However, it's possible the credential implementations provided might not meet the specific needs your application, or an application might want to avoid taking a dependency on the `@azure/identity` library. +The `@azure/identity` library covers a broad range of Azure Active Directory authentication scenarios. However, it's possible the credential implementations provided might not meet the specific needs your application, or an application might want to avoid taking a dependency on the `@azure/identity` library. In such cases, you may want to write your own credential. -In this section we'll examine some example cases in which it might make sense to write a credential on your own. +In this section we'll examine some such scenarios. ### Authenticating with a pre-fetched access token From eab45385925c7f71f04fdd03e6cecb214ec9e6ca Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Fri, 11 Jun 2021 01:31:50 +0000 Subject: [PATCH 12/22] small changes --- .../identity/samples/AzureIdentityExamples.md | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index 19546c8ee26c..e422553442bd 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -107,7 +107,7 @@ If your application is hosted in Azure, you can make use of [Managed Identity](h | Credential with example | Usage | | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [ManagedIdentityCredential](#authenticating-in-azure-with-managed-identity) | Authenticate in a virtual machine, app service, function app, cloud shell, or AKS environment on Azure, with system assigned managed identity, user assigned managed identity, or app registration (when working with AKS pod-identity). | +| [ManagedIdentityCredential](#authenticating-in-azure-with-managed-identity) | Authenticate in a virtual machine, app service, function app, cloud shell, or AKS environment on Azure, with system assigned managed identity, user assigned managed identity, or app registration (when working with AKS pod-identity). | | [DefaultAzureCredential](#authenticating-with-defaultazurecredential) | Tries `EnvironmentCredential`, `ManagedIdentityCredential`, `AzureCliCredential`, `AzurePowerShellCredential`, and other credentials sequentially until one of them succeeds. Use this to have your application authenticate using developer tools, service principals or managed identity based on what is available in the current environment without changing your code. | ### Examples @@ -121,7 +121,7 @@ This example demonstrates authenticating the `SecretClient` from the [@azure/key * The default credential first checks environment variables for configuration. * If environment configuration is incomplete, it will try managed identity. */ -function withDefaultAzureCredential () { +function withDefaultAzureCredential() { const credential = new DefaultAzureCredential(); const client = new SecretClient(`https://key-vault-name.vault.azure.net`, credential); } @@ -137,7 +137,7 @@ For more information about how to configure a user assigned managed identity for /** * The default credential will use the user assigned managed identity with the specified client ID. */ -function withDefaultAzureCredential () { +function withDefaultAzureCredential() { // Alternatively, you may set the environment variable AZURE_CLIENT_ID="" and omit the `managedIdentityClientId` // option when using `DefaultAzureCredential` - the two approaches are equivalent. const credential = new DefaultAzureCredential({ @@ -153,10 +153,10 @@ For clients that have a default browser available and for client-side applicatio For Node.js, if a `clientId` is provided, the Azure Active Directory application will need to be configured to have a "Mobile and desktop applications" redirect endpoint. Follow our guide on [setting up Redirect URIs for Desktop apps that calls to web APIs](https://docs.microsoft.com/azure/active-directory/develop/scenario-desktop-app-registration#redirect-uris). -For client side applications running in the browser, the `InteractiveBrowserCredential` is the only credential type that is supported. You will also need to configure your app registration for single-page applications and set the right permissions. Please refer to the [Single-Page application: App registration guide](https://docs.microsoft.com/azure/active-directory/develop/scenario-spa-app-registration) for more information. +For client side applications running in the browser, the `InteractiveBrowserCredential` is the only credential type that is supported. Please see [Authenticating client side browser applications](#authenticating-client-side-browser-applications). ```ts -function withInteractiveBrowserCredential () { +function withInteractiveBrowserCredential() { const credential = new InteractiveBrowserCredential({ tenantId: "", clientId: "" @@ -183,7 +183,7 @@ Set up: /** * Authenticate with client secret. */ -function withClientSecretCredential () { +function withClientSecretCredential() { const credential = new ClientSecretCredential( "", "", @@ -210,7 +210,7 @@ Set up: /** * Authenticate with a client certificate. */ -function withEnvironmentCredential () { +function withEnvironmentCredential() { let credential = new EnvironmentCredential(); const client = new SecretClient("https://key-vault-name.vault.azure.net", credential); } @@ -233,7 +233,7 @@ Set up: /** * Authenticate with a client certificate. */ -function withClientCertificateCredential () { +function withClientCertificateCredential() { let credential = new ClientCertificateCredential( "", "", @@ -253,7 +253,7 @@ This example demonstrates authenticating the `SecretClient` from the [@azure/key /** * Authenticate with a device code. */ -function withDeviceCodeCredential () { +function withDeviceCodeCredential() { let credential = new DeviceCodeCredential( process.env.AZURE_TENANT_ID, process.env.AZURE_CLIENT_ID, @@ -286,7 +286,7 @@ Apart from user name and password, this credential requires you to know the tena /** * Authenticate with a client certificate. */ -function withClientCertificateCredential () { +function withClientCertificateCredential() { let credential = new UsernamePasswordCredential( "", "", @@ -313,7 +313,7 @@ For a complete example using the authorization code flow in Electron please refe /** * Authenticate with authorization code. */ -function withAuthCodeCredential () { +function withAuthCodeCredential() { const credential = new AuthorizationCodeCredential( "", "", @@ -361,7 +361,7 @@ to verify the account has been successfully configured. /** * Authenticate with Azure CLI. */ -function withAzureCliCredential () { +function withAzureCliCredential() { // As you can see in this example, the AzureCliCredential does not take any parameters, // instead relying on the Azure CLI authenticated user to authenticate. const credential = new AzureCliCredential(); @@ -436,7 +436,7 @@ For more information about how to configure your Azure resource for managed iden /** * Authenticate with a system assigned managed identity. */ -function withSystemAssignedManagedIdentityCredential () { +function withSystemAssignedManagedIdentityCredential() { const credential = new ManagedIdentityCredential(); const client = new SecretClient("https://key-vault-name.vault.azure.net", credential); @@ -445,7 +445,7 @@ function withSystemAssignedManagedIdentityCredential () { /** * Authenticate with a user assigned managed identity. */ -function withUserManagedIdentityCredential () { +function withUserManagedIdentityCredential() { const credential = new ManagedIdentityCredential(""); const client = new SecretClient("https://key-vault-name.vault.azure.net", credential); @@ -457,7 +457,7 @@ function withUserManagedIdentityCredential () { The `ChainedTokenCredential` class provides the ability to link together multiple credential instances to be tried sequentially when authenticating. The following example demonstrates creating a credential which will attempt to authenticate a `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] using managed identity, and fall back to certificate authentication if a managed identity is unavailable in the current environment. ```ts -function withChainedTokenCredential () { +function withChainedTokenCredential() { const credential = new ChainedTokenCredential( new ManagedIdentityCredential(""), new ClientSecretCredential("", "", "") @@ -498,7 +498,7 @@ else, if the Identity provider of your Azure Stack is Active Directory Federatio The following example demonstrates authenticating a `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] against an Azure Key Vault hosted in Azure Stack. ```ts -function main () { +function main() { const credential = new ClientSecretCredential( "", "", @@ -534,8 +534,8 @@ In this example, `StaticTokenCredential` implements the `TokenCredential` abstra import { TokenCredential, AccessToken } from "@azure/core-auth"; class StaticTokenCredential implements TokenCredential { - constructor (private accessToken: AccessToken) {} - async getToken (): Promise { + constructor(private accessToken: AccessToken) {} + async getToken(): Promise { return this.accessToken; } } @@ -546,7 +546,7 @@ Once the application has defined this credential, it can be used to authenticate ```ts import { SecretClient } from "@azure/keyvault-secrets"; -async function main () { +async function main() { const token = getTokenForScope("https://vault.azure.net/.default"); const credential = new StaticTokenCredential(token); @@ -575,8 +575,8 @@ import { TokenCredential, AccessToken } from "@azure/core-auth"; import * as msalNode from "@azure/msal-node"; class ConfidentialClientCredential implements TokenCredential { - constructor (private confidentialApp: msalNode.ConfidentialClientApplication) {} - async getToken (scopes: string | string[]): Promise { + constructor(private confidentialApp: msalNode.ConfidentialClientApplication) {} + async getToken(scopes: string | string[]): Promise { const result = await this.confidentialApp.acquireTokenByClientCredential({ scopes: Array.isArray(scopes) ? scopes : [scopes] }); @@ -594,7 +594,7 @@ Users could then use the `ConfidentialClientApplicationCredential` to authentica import { SecretClient } from "@azure/keyvault-secrets"; import * as msalNode from "@azure/msal-node"; -async function main () { +async function main() { const confidentialClient = new msalNode.ConfidentialClientApplication({ // MSAL Configuration }); @@ -637,7 +637,7 @@ class OnBehalfOfCredential implements TokenCredential { } }); } - async getToken (scopes: string | string[]): Promise { + async getToken(scopes: string | string[]): Promise { const result = await this.confidentialApp.acquireTokenOnBehalfOf({ scopes: Array.isArray(scopes) ? scopes : [scopes], oboAssertion: this.userAccessToken @@ -655,7 +655,7 @@ The following example shows an how the `OnBehalfOfCredential` could be used to a ```ts import { SecretClient } from "@azure/keyvault-secrets"; -async function main () { +async function main() { const oboCredential = new OnBehalfOfCredential(clientId, clientSecret, userAccessToken); const client = new SecretClient("https://myvault.vault.azure.net/", oboCredential); @@ -680,7 +680,7 @@ class BrowserCredential implements TokenCredential { private publicApp: msalBrowser.PublicClientApplication; private hasAuthenticated: boolean = false; - constructor (clientId, redirectUri) { + constructor(clientId, redirectUri) { this.publicApp = new msalBrowser.PublicClientApplication({ auth: { clientId, @@ -690,7 +690,7 @@ class BrowserCredential implements TokenCredential { } // Either confirm the account already exists in memory, or tries to parse the redirect URI values. - async prepare (): Promise { + async prepare(): Promise { try { if (await this.publicApp.getActiveAccount()) { this.hasAuthenticated = true; @@ -698,18 +698,18 @@ class BrowserCredential implements TokenCredential { } await this.publicApp.handleRedirectPromise(); this.hasAuthenticated = true; - } catch (e) { + } catch(e) { console.error("BrowserCredential prepare() failed", e); } } // Should be true if prepare() was successful. - isAuthenticated (): boolean { + isAuthenticated(): boolean { return this.hasAuthenticated; } // If called, triggers authentication via redirection. - async loginRedirect (scopes: string | string[]): Promise { + async loginRedirect(scopes: string | string[]): Promise { const loginRequest = { scopes: Array.isArray(scopes) ? scopes : [scopes] }; @@ -717,7 +717,7 @@ class BrowserCredential implements TokenCredential { } // Tries to retrieve the token without triggering a redirection. - async getToken (scopes: string | string[]): Promise { + async getToken(scopes: string | string[]): Promise { if (!this.hasAuthenticated) { throw new Error("Authentication required"); } @@ -741,7 +741,7 @@ The following example shows an how the `BrowserCredential` could be used to auth ```ts import { ServiceBusClient } from "@azure/service-bus"; -async function main () { +async function main() { const browserCredential = new BrowserCredential(clientId, location.origin); await browserCredential.prepare(); @@ -797,17 +797,17 @@ class RotatableCertificateCredential implements TokenCredential { private readonly clientId: string; private credential: ClientCertificateCredential; - constructor (tenantId: string, clientId: string, PEMCertificatePath: string) { + constructor(tenantId: string, clientId: string, PEMCertificatePath: string) { this.tenantId = tenantId; this.clientId = clientId; this.credential = new ClientCertificateCredential(tenantId, clientId, PEMCertificatePath); } - async getToken (scopes: string | string[], options?: GetTokenOptions): Promise { + async getToken(scopes: string | string[], options?: GetTokenOptions): Promise { return this.credential.getToken(scopes, options); } - rotateCertificate (PEMCertificatePath: string) { + rotateCertificate(PEMCertificatePath: string) { this.credential = new ClientCertificateCredential( this.tenantId, this.clientId, @@ -836,7 +836,7 @@ class RotatingCertificateCredential implements TokenCredential { private credential: ClientCertificateCredential; private lastModified: number = 0; - constructor (tenantId: string, clientId: string, certificatePath: string) { + constructor(tenantId: string, clientId: string, certificatePath: string) { this.tenantId = tenantId; this.clientId = clientId; this.certificatePath = certificatePath; @@ -844,13 +844,13 @@ class RotatingCertificateCredential implements TokenCredential { this.refreshCertificate(); } - async getToken (scopes: string | string[], options?: GetTokenOptions): Promise { + async getToken(scopes: string | string[], options?: GetTokenOptions): Promise { await this.refreshCertificate(); return this.credential.getToken(scopes, options); } - refreshCertificate (): Promise { + refreshCertificate(): Promise { if (this.promise) { return this.promise; } From 545995e4808f6f80f0578c631b141e0a5e21ab4f Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Fri, 11 Jun 2021 14:00:47 +0000 Subject: [PATCH 13/22] some improvements --- .../identity/samples/AzureIdentityExamples.md | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index e422553442bd..b6ec10e1e8b0 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -23,7 +23,7 @@ ## Introduction -Authenticating your application, users, and principals is an integral part of working with the Azure Client Libraries. The Azure Identity library provides multiple ways to authenticate, each with a flexible configuration that covers most scenarios. In this document we will go over some of these scenarios and provide small examples that can be used as a starting point for your needs. +Authenticating your application, users, and principals is an integral part of working with the Azure Client Libraries. The Azure Identity library provides multiple ways to gain access to the Azure services, each with a flexible configuration that covers most scenarios. While we have example code in [JavaScript](https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/identity/identity/samples/javascript) and [TypeScript](https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/identity/identity/samples/typescript) that cover the basic authentication scenarios, in this document, we will go over several use cases of Identity that are better explained with more context. ## Authenticating client side browser applications @@ -37,6 +37,10 @@ For client side applications running in the browser, the `InteractiveBrowserCred - In your app registration in the Azure portal, go to `API Permissions` - Click on `Add a permission` - Select the API you want to use. For example, if you are using any of our management/control plane packages i.e. the ones whose name starts with `@azure/arm-`, then you should select ``Azure Service Management`. +- Ensure that your AAD application has enabled public authentication flows: + - Go to Azure Active Directory in Azure portal and find your app registration. + - Navigate to the **Authentication** section. + - Under **Advanced settings**, select `yes` on the option `Allow public client flows`. Copy the client ID and tenant ID from the `Overview` section of your app registration in Azure portal and use it in the below code snippet where we authenticate a `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] using the `InteractiveBrowserCredential`. @@ -51,22 +55,23 @@ function withInteractiveBrowserCredential() { } ``` +If your project is already using MSAL to authenticate on the browser, or if you're looking for more advanced authentication scenarios in the browser, the Azure SDK makes it easy to use MSAL directly to authenticate our clients: [Authenticating with the @azure/msal-browser Public Client](#authenticating-with-the-azure-msal-browser-public-client). + ## Authenticating server side applications -For server side applications we provide options that vary from minimal configuration with sensible defaults using the `DefaultAzureCredential` to more specialized credentials that can support your specific scenario. +For server side applications, we provide options that vary from minimal configuration with sensible defaults using the `DefaultAzureCredential` to more specialized credentials. - To get started, you can always rely on interactive authentication of your user account which requires minimum setup. -- As you develop your application, you may want to first sign in using the developer tools like Azure CLI or Azure PowerShell to avoid signing in interactively every time you run your application. +- As you develop your application, you may want to first sign-in using the developer tools like Azure CLI or Azure PowerShell, to avoid signing in interactively every time you run your application. - As you deploy your application to Azure App Service or run it in a virtual machine, you may want to make use of [Managed Identity](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview). -You can [chain multiple credentials](#chaining-credentials) together so that they are tried sequentially until one of them succeeds. -This is useful to make use of different authentication mechanisms based on your environment without changing your application code. +We also provide a way to chain multiple credentials so that they try to authenticate sequentially until one of them succeeds. This will allow your code to work in multiple environments, including your local development tools. For more information, go to the section: [Chaining credentials](#chaining-credentials). One such chained credential that we provide out of the box is `DefaultAzureCredential`. ### Authenticating User Accounts -Authenticating user accounts is the easiest way to get started with minimal set up. For production scenarios, we recommend authenticating using service principals or managed identity which are listed in the later sections. +Authenticating user accounts is the easiest way to get started with minimal set-up. For production scenarios, we recommend authenticating using service principals or managed identity which are listed in the later sections. | Credential with example | Usage | Setup required | | ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | @@ -270,7 +275,7 @@ To authenticate a user through device code flow, use the following steps: 1. Go to Azure Active Directory in Azure portal and find your app registration. 2. Navigate to the **Authentication** section. -3. Under **Advanced settings**, select `yes` on the option `Enable the following mobile and desktop flows`. +3. Under **Advanced settings**, select `yes` on the option `Allow public client flows`. You also need to be the admin of your tenant to grant consent to your application when you log in for the first time. @@ -280,7 +285,7 @@ If you can't configure the device code flow option on your Active Directory, the This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `UsernamePasswordCredential`. The user must **not** have Multi-factor auth turned on. -Apart from user name and password, this credential requires you to know the tenant Id and client Id. To get the client Id, first [register your application][quickstart-register-app]. +Apart from user name and password, this credential requires you to know the tenant ID and client ID. To get the client ID, first [register your application][quickstart-register-app]. ```ts /** @@ -610,7 +615,7 @@ async function main() { Currently the `@azure/identity` library doesn't provide a credential type for clients which need to authenticate via the [On Behalf of Flow](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-common/docs/request.md#on-behalf-of-flow). While future support for this is planned, users currently requiring this will have to implement their own `TokenCredential` class. -In this example the `OnBehalfOfCredential` accepts a client Id, client secret, and a user's access token. It then creates an instance of `ConfidentialClientApplication` from MSAL to obtain an OBO token which can be used to authenticate client requests. +In this example the `OnBehalfOfCredential` accepts a client ID, client secret, and a user's access token. It then creates an instance of `ConfidentialClientApplication` from MSAL to obtain an OBO token which can be used to authenticate client requests. You'll need to install the [@azure/msal-node][msal_node_npm] and the the [@azure/core-auth][core_auth] package for this sample. From 4572bbb83b9563a23db73deec785623805a06d36 Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Fri, 11 Jun 2021 19:16:00 +0000 Subject: [PATCH 14/22] some improvements --- .../identity/samples/AzureIdentityExamples.md | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index b6ec10e1e8b0..d7f51225f3ed 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -2,8 +2,8 @@ - [Introduction](#introduction) - [Requirements](#requirements) -- [Authenticating client side browser applications](#authenticating-client-side-browser-applications) -- [Authenticating server side applications](#authenticating-server-side-applications) +- [Authenticating client-side browser applications](#authenticating-client-side-browser-applications) +- [Authenticating server-side applications](#authenticating-server-side-applications) - [Authenticating User Accounts](#authenticating-user-accounts) - [Authenticating User Accounts with developer tools](#authenticating-user-accounts-with-developer-tools) - [Authenticating Service Principals](#authenticating-service-principals) @@ -23,26 +23,26 @@ ## Introduction -Authenticating your application, users, and principals is an integral part of working with the Azure Client Libraries. The Azure Identity library provides multiple ways to gain access to the Azure services, each with a flexible configuration that covers most scenarios. While we have example code in [JavaScript](https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/identity/identity/samples/javascript) and [TypeScript](https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/identity/identity/samples/typescript) that cover the basic authentication scenarios, in this document, we will go over several use cases of Identity that are better explained with more context. +Authenticating your application, users, and principals is an integral part of working with the Azure Client Libraries. The Azure Identity library provides multiple ways to gain access to the Azure services, each with a flexible configuration that covers most scenarios. While we have example code in [JavaScript](https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/identity/identity/samples/javascript) and [TypeScript](https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/identity/identity/samples/typescript) that cover the basic authentication scenarios, in this document, we will go over several use cases of Identity with greater context and links to the underlying authentication flows and other available documentation. -## Authenticating client side browser applications +## Authenticating client-side browser applications -For client side applications running in the browser, the `InteractiveBrowserCredential` provides the simplest user authentication experience and is the only credential type that we support in the browser. To get started, you need to register your application in the Microsoft identity platform and set the right permissions. +For client-side applications running in the browser, the `InteractiveBrowserCredential` provides the most direct user authentication experience and is the only credential type that we support in the browser. To get started, you need to register your application in the Microsoft identity platform and set the proper permissions. - [Register a single page application](https://docs.microsoft.com/azure/active-directory/develop/scenario-spa-app-registration) in the Microsoft identity platform - Configure the app registration with a redirect URI to specify where the Microsoft identity platform should redirect the client along with any security tokens. - If using v1 of `@azure/identity` package, follow the instructions at [Redirect URI: MSAL.js 1.0 with implicit flow](https://docs.microsoft.com/azure/active-directory/develop/scenario-spa-app-registration#redirect-uri-msaljs-10-with-implicit-flow) to set the redirect URI. - If using v2 of `@azure/identity` package, follow the instructions at [Redirect URI: MSAL.js 2.0 with auth code flow](https://docs.microsoft.com/azure/active-directory/develop/scenario-spa-app-registration#redirect-uri-msaljs-20-with-auth-code-flow) -- Ensure that your application has the right permission for the APIs it intends to use. +- * Ensure that your application has the correct permission for the APIs it intends to use. - In your app registration in the Azure portal, go to `API Permissions` - Click on `Add a permission` - - Select the API you want to use. For example, if you are using any of our management/control plane packages i.e. the ones whose name starts with `@azure/arm-`, then you should select ``Azure Service Management`. -- Ensure that your AAD application has enabled public authentication flows: - - Go to Azure Active Directory in Azure portal and find your app registration. + - Select the API you want to use. For example, if you are using any of our management/control plane packages, i.e., the ones whose name starts with `@azure/arm-`, then you should select ``Azure Service Management`. +- Ensure that your AAD Application has enabled public authentication flows: + - Go to Azure Active Directory in the Azure portal and find your app registration. - Navigate to the **Authentication** section. - Under **Advanced settings**, select `yes` on the option `Allow public client flows`. -Copy the client ID and tenant ID from the `Overview` section of your app registration in Azure portal and use it in the below code snippet where we authenticate a `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] using the `InteractiveBrowserCredential`. +Copy the client ID and tenant ID from the `Overview` section of your app registration in the Azure portal and use it in the below code snippet where we authenticate a `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] using the `InteractiveBrowserCredential`. ```ts function withInteractiveBrowserCredential() { @@ -57,21 +57,21 @@ function withInteractiveBrowserCredential() { If your project is already using MSAL to authenticate on the browser, or if you're looking for more advanced authentication scenarios in the browser, the Azure SDK makes it easy to use MSAL directly to authenticate our clients: [Authenticating with the @azure/msal-browser Public Client](#authenticating-with-the-azure-msal-browser-public-client). -## Authenticating server side applications +## Authenticating server-side applications -For server side applications, we provide options that vary from minimal configuration with sensible defaults using the `DefaultAzureCredential` to more specialized credentials. +For server-side applications, we provide options that vary from a minimal configuration with sensible defaults using the `DefaultAzureCredential` to more specialized credentials. -- To get started, you can always rely on interactive authentication of your user account which requires minimum setup. -- As you develop your application, you may want to first sign-in using the developer tools like Azure CLI or Azure PowerShell, to avoid signing in interactively every time you run your application. -- As you deploy your application to Azure App Service or run it in a virtual machine, you may want to make use of [Managed Identity](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview). +- To get started, you can always rely on interactive authentication of your user account, which requires minimal setup. +- As you develop your application, you may want to sign in using the developer tools like Azure CLI or Azure PowerShell, to avoid signing in interactively every time you run your application. +- As you deploy your application to Azure App Service or run it in a virtual machine, you may want to use [Managed Identity](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview). -We also provide a way to chain multiple credentials so that they try to authenticate sequentially until one of them succeeds. This will allow your code to work in multiple environments, including your local development tools. For more information, go to the section: [Chaining credentials](#chaining-credentials). +We also provide a way to chain multiple credentials so that they try to authenticate sequentially until one of them succeeds. Chaining credentials will allow your code to work in multiple environments, including your local development tools. For more information, go to the section: [Chaining credentials](#chaining-credentials). One such chained credential that we provide out of the box is `DefaultAzureCredential`. ### Authenticating User Accounts -Authenticating user accounts is the easiest way to get started with minimal set-up. For production scenarios, we recommend authenticating using service principals or managed identity which are listed in the later sections. +Authenticating user accounts is the easiest way to get started with minimal set up. For production scenarios, we recommend authenticating using service principals or managed identities, which are listed in the later sections. | Credential with example | Usage | Setup required | | ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | @@ -90,7 +90,7 @@ Authenticating user accounts is the easiest way to get started with minimal set- ### Authenticating Service Principals -An Azure service principal is an identity created for use with applications, hosted services, and automated tools to access Azure resources. This access is restricted by the roles assigned to the service principal, giving you control over which resources can be accessed and at which level. For security reasons, it's always recommended to use service principals with automated tools rather than allowing them to log in with a user identity. +An Azure service principal is an identity created for use with applications, hosted services, and automated tools to access Azure resources. The roles assigned by the service principal will determine what resources are accessible. For security reasons, we recommended using service principals through automation rather than allowing them to log in with a user identity. To learn more, read [Application and service principal objects in Azure Active Directory][app-register-service-principal] @@ -104,7 +104,7 @@ To learn more, read [Application and service principal objects in Azure Active D | [ClientSecretCredential](#authenticating-a-service-principal-with-a-client-secret) | Authenticates a service principal using a secret. | | [ClientCertificateCredential](#authenticating-a-service-principal-with-a-client-certificate) | Authenticates a service principal using a certificate. | | [EnvironmentCredential](#authenticating-a-service-principal-with-environment-credentials) | Authenticates a service principal or user via credential information specified in environment variables. | -| [DefaultAzureCredential](#authenticating-with-defaultazurecredential) | Tries `EnvironmentCredential`, `AzureCliCredential`, `AzurePowerShellCredential` and other credentials sequentially until one of them succeeds. Use this to have your application authenticate using developer tools, service principals or managed identity based on what is available in the current environment without changing your code. | +| [DefaultAzureCredential](#authenticating-with-defaultazurecredential) | Tries `EnvironmentCredential`, `AzureCliCredential`, `AzurePowerShellCredential`, and other credentials sequentially until one of them succeeds. Use this to have your application authenticate using developer tools, service principals, or managed identity based on what is available in the current environment without changing your code. | ### Authenticating Azure Hosted Applications @@ -158,7 +158,7 @@ For clients that have a default browser available and for client-side applicatio For Node.js, if a `clientId` is provided, the Azure Active Directory application will need to be configured to have a "Mobile and desktop applications" redirect endpoint. Follow our guide on [setting up Redirect URIs for Desktop apps that calls to web APIs](https://docs.microsoft.com/azure/active-directory/develop/scenario-desktop-app-registration#redirect-uris). -For client side applications running in the browser, the `InteractiveBrowserCredential` is the only credential type that is supported. Please see [Authenticating client side browser applications](#authenticating-client-side-browser-applications). +For client-side applications running in the browser, the `InteractiveBrowserCredential` is the only credential type that is supported. Please see [Authenticating client-side browser applications](#authenticating-client-side-browser-applications). ```ts function withInteractiveBrowserCredential() { From 81601e592e0e9907e145c7b66fff5b36c8160f0b Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Fri, 11 Jun 2021 23:25:19 +0000 Subject: [PATCH 15/22] many small tweaks --- .../identity/samples/AzureIdentityExamples.md | 171 +++++++++--------- 1 file changed, 88 insertions(+), 83 deletions(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index d7f51225f3ed..39257c402623 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -112,19 +112,19 @@ If your application is hosted in Azure, you can make use of [Managed Identity](h | Credential with example | Usage | | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [ManagedIdentityCredential](#authenticating-in-azure-with-managed-identity) | Authenticate in a virtual machine, app service, function app, cloud shell, or AKS environment on Azure, with system assigned managed identity, user assigned managed identity, or app registration (when working with AKS pod-identity). | +| [ManagedIdentityCredential](#authenticating-in-azure-with-managed-identity) | Authenticate in a virtual machine, app service, function app, cloud shell, or AKS environment on Azure, with system-assigned managed identity, user-assigned managed identity, or app registration (when working with AKS pod-identity). | | [DefaultAzureCredential](#authenticating-with-defaultazurecredential) | Tries `EnvironmentCredential`, `ManagedIdentityCredential`, `AzureCliCredential`, `AzurePowerShellCredential`, and other credentials sequentially until one of them succeeds. Use this to have your application authenticate using developer tools, service principals or managed identity based on what is available in the current environment without changing your code. | ### Examples #### Authenticating with `DefaultAzureCredential` -This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `DefaultAzureCredential`. There's also [a runnable sample](https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/identity/identity/samples/typescript/src/defaultAzureCredential.ts) to create a Key Vault key client you can copy-paste. The `DefaultAzureCredential` makes for a terrific starting point as it provides sane defaults with minimal configuration and chains multiple credentials together. While you may outgrow it eventually, it is a sensible first choice for most scenarios where the application is intended to ultimately be run in the Azure Cloud. +This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `DefaultAzureCredential`. There's also [a runnable sample](https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/identity/identity/samples/typescript/src/defaultAzureCredential.ts) to create a Key Vault key client you can copy-paste. The `DefaultAzureCredential` makes for a simple starting point as it provides sane defaults with minimal configuration and chains multiple credentials together. While your project may eventually need only a specific set of credentials, it is a sensible first choice for most scenarios where a project in active development will be running in the Azure Cloud. ```ts /** * The default credential first checks environment variables for configuration. - * If environment configuration is incomplete, it will try managed identity. + * If the environment configuration is incomplete, it will try managed identity. */ function withDefaultAzureCredential() { const credential = new DefaultAzureCredential(); @@ -132,15 +132,15 @@ function withDefaultAzureCredential() { } ``` -#### Authenticating a user assigned managed identity with `DefaultAzureCredential` +#### Authenticating a user-assigned managed identity with `DefaultAzureCredential` -This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `DefaultAzureCredential`, deployed to an Azure resource with a user assigned managed identity configured. +This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `DefaultAzureCredential`, deployed to an Azure resource with a user-assigned managed identity configured. -For more information about how to configure a user assigned managed identity for an Azure resource please refer to [What are managed identities for Azure resources][azure_managed_identities]. +For more information about configuring a user-assigned managed identity for an Azure resource, please refer to [What are managed identities for Azure resources][azure_managed_identities]. ```ts /** - * The default credential will use the user assigned managed identity with the specified client ID. + * The default credential will use the user-assigned managed identity with the specified client ID. */ function withDefaultAzureCredential() { // Alternatively, you may set the environment variable AZURE_CLIENT_ID="" and omit the `managedIdentityClientId` @@ -154,7 +154,7 @@ function withDefaultAzureCredential() { #### Authenticating a user account interactively in the browser -For clients that have a default browser available and for client-side applications running in the browser, the `InteractiveBrowserCredential` provides the simplest user authentication experience. In the sample below an application authenticates a `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] using the `InteractiveBrowserCredential`. +For clients with a default browser available and client-side applications running in the browser, the `InteractiveBrowserCredential` provides the most direct user authentication experience. In the sample below, an application authenticates a `SecretClient` from the [@azure/service-bus][service_bus_client_library] using the `InteractiveBrowserCredential`. For Node.js, if a `clientId` is provided, the Azure Active Directory application will need to be configured to have a "Mobile and desktop applications" redirect endpoint. Follow our guide on [setting up Redirect URIs for Desktop apps that calls to web APIs](https://docs.microsoft.com/azure/active-directory/develop/scenario-desktop-app-registration#redirect-uris). @@ -166,8 +166,7 @@ function withInteractiveBrowserCredential() { tenantId: "", clientId: "" }); - - const client = new SecretClient("https://key-vault-name.vault.azure.net", credential); + const client = new ServiceBusClient("", credential); } ``` @@ -175,14 +174,14 @@ function withInteractiveBrowserCredential() { This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `ClientSecretCredential`. There's also [a runnable sample](https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/identity/identity/samples/typescript/src/clientSecretCredential.ts) to create a Key Vault key client you can copy-paste. -An Azure service principal is an identity created for use with applications, hosted services, and automated tools to access Azure resources. This access is restricted by the roles assigned to the service principal, giving you control over which resources can be accessed and at which level. For security reasons, it's always recommended to use service principals with automated tools rather than allowing them to log in with a user identity. +You'll need to: -To learn more, read [Application and service principal objects in Azure Active Directory][app-register-service-principal] +- [Create an application registration][quickstart-register-app] +- [Create a Service Principal with the Azure CLI][service_principal_azure_cli] or [Create an Azure service principal with Azure PowerShell][service_principal_azure_powershell] -Set up: +To learn more about service principals, read [Application and service principal objects in Azure Active Directory][app-register-service-principal] -- [Application registration][quickstart-register-app] -- [Create a Service Principal with the Azure CLI][service_principal_azure_cli] or [Create an Azure service principal with Azure PowerShell][service_principal_azure_powershell] +In the sample below, an application authenticates a `SecretClient` from the [@azure/service-bus][service_bus_client_library] using the `ClientSecretCredential`. ```ts /** @@ -194,26 +193,28 @@ function withClientSecretCredential() { "", "" ); - const client = new SecretClient("https://key-vault-name.vault.azure.net", credential); + const client = new ServiceBusClient("", credential); } ``` #### Authenticating a service principal with environment credentials -This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `EnvironmentCredential`. The `EnvironmentCredential` looks for well-known environment variable names to determine how it should authenticate. It effectively acts as a wrapper for the `ClientSecretCredential`, `ClientCertificateCredential` or `UsernamePasswordCredential` depending on which environment variables are present. - -An Azure service principal is an identity created for use with applications, hosted services, and automated tools to access Azure resources. This access is restricted by the roles assigned to the service principal, giving you control over which resources can be accessed and at which level. For security reasons, it's always recommended to use service principals with automated tools rather than allowing them to log in with a user identity. - -To learn more, read [Application and service principal objects in Azure Active Directory][app-register-service-principal] +This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `EnvironmentCredential`. The `EnvironmentCredential` looks for well-known environment variable names to determine how it should authenticate. It effectively acts as a wrapper for the `ClientSecretCredential`, `ClientCertificateCredential`, or `UsernamePasswordCredential`, depending on which environment variables are present. -Set up: +You'll need to: -- [Application registration][quickstart-register-app] +- [Create an application registration][quickstart-register-app] - [Create a Service Principal with the Azure CLI][service_principal_azure_cli] or [Create an Azure service principal with Azure PowerShell][service_principal_azure_powershell] +- Provide the environment variables: + - `AZURE_TENANT_ID`, containing the AD tenant ID or name. + - `AZURE_CLIENT_ID`, containing the ID of the user/service principal to authenticate as. + - `AZURE_CLIENT_SECRET`, containing a client secret created belonging to the same user/service principal. + +To learn more about service principals, read [Application and service principal objects in Azure Active Directory][app-register-service-principal] ```ts /** - * Authenticate with a client certificate. + * Authenticate using the AZURE_TENANT_ID, AZURE_CLIENT_ID and AZURE_CLIENT_SECRET environment variables. */ function withEnvironmentCredential() { let credential = new EnvironmentCredential(); @@ -225,15 +226,13 @@ function withEnvironmentCredential() { This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `ClientCertificateCredential`. -An Azure service principal is an identity created for use with applications, hosted services, and automated tools to access Azure resources. This access is restricted by the roles assigned to the service principal, giving you control over which resources can be accessed and at which level. For security reasons, it's always recommended to use service principals with automated tools rather than allowing them to log in with a user identity. - -To learn more, read [Application and service principal objects in Azure Active Directory][app-register-service-principal] - -Set up: +You'll need to: -- [Application registration][quickstart-register-app] +- [Create an application registration][quickstart-register-app] - [Create a Service Principal with the Azure CLI][service_principal_azure_cli] or [Create an Azure service principal with Azure PowerShell][service_principal_azure_powershell] +To learn more about service principals, read [Application and service principal objects in Azure Active Directory][app-register-service-principal] + ```ts /** * Authenticate with a client certificate. @@ -250,9 +249,17 @@ function withClientCertificateCredential() { #### Authenticating a user account with device code flow -This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `DeviceCodeCredential`. +This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `DeviceCodeCredential`. The `DeviceCodeCredential` offers a credential that can be used with little to no setup - the user is free to use whatever browser they choose to complete the authentication process. + +To authenticate a user through device code flow, use the following steps: + +1. Go to Azure Active Directory in Azure portal and find your app registration. +2. Navigate to the **Authentication** section. +3. Under **Advanced settings**, select `yes` on the option `Allow public client flows`. + +You also need to be the admin of your tenant to grant consent to your application when you log in for the first time. -> The `DeviceCodeCredential` offers a credential that can be used with little to no setup - the user is free to use whatever browser they choose to complete the authentication process. +If you can't configure the device code flow option on your Active Directory, then it may require your app to be multi-tenant. To make your app multi-tenant, navigate to the **Authentication** panel, then select **Accounts in any organizational directory**. Then, select _yes_ for Treat application as Public Client. ```ts /** @@ -271,16 +278,6 @@ function withDeviceCodeCredential() { } ``` -To authenticate a user through device code flow, use the following steps: - -1. Go to Azure Active Directory in Azure portal and find your app registration. -2. Navigate to the **Authentication** section. -3. Under **Advanced settings**, select `yes` on the option `Allow public client flows`. - -You also need to be the admin of your tenant to grant consent to your application when you log in for the first time. - -If you can't configure the device code flow option on your Active Directory, then it may require your app to be multi-tenant. To make your app multi-tenant, navigate to the **Authentication** panel, then select **Accounts in any organizational directory**. Then, select _yes_ for Treat application as Public Client. - #### Authenticating a user account with username and password This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `UsernamePasswordCredential`. The user must **not** have Multi-factor auth turned on. @@ -304,11 +301,11 @@ function withClientCertificateCredential() { #### Authenticating a user account with auth code flow -This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `AuthorizationCodeCredential` on a web application. This can be useful when you want complete control over the authentication flow or when the `InteractiveBrowserCredential` does not fit your use-case. +This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `AuthorizationCodeCredential` on a Node.js service intended as the back-end for a web application. This can be useful when you want complete control over the authentication flow or when the `InteractiveBrowserCredential` does not fit your use-case. -First, [register your application][quickstart-register-app] and get your client id, tenant id and redirect URL. +First, [register your application][quickstart-register-app] and get your client ID, tenant ID and redirect URL. -Next, prompt the user to login at the URL documented at [Microsoft identity platform and OAuth 2.0 authorization code flow](https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-auth-code-flow#request-an-authorization-code). You will need the client id, tenant id, redirect URL, and the scopes your application plans to access. +Next, prompt the user to login at the URL documented at [Microsoft identity platform and OAuth 2.0 authorization code flow](https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-auth-code-flow#request-an-authorization-code). You will need the client ID, tenant ID, redirect URL, and the scopes your application plans to access. Then create an API at the redirect URL with the following code to access the Key Vault service. @@ -334,7 +331,7 @@ function withAuthCodeCredential() { This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `AzureCliCredential` on a workstation with Azure CLI installed and signed in. -#### Configure the Azure CLI +##### Configure the Azure CLI Sign in using the [Azure CLI][azure_cli] @@ -379,7 +376,7 @@ function withAzureCliCredential() { This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `AzurePowerShellCredential` on a workstation with Azure PowerShell installed and authenticated. -#### Configure Azure PowerShell +##### Configure Azure PowerShell Sign in using [Azure PowerShell][azure_powershell]: @@ -387,7 +384,7 @@ Sign in using [Azure PowerShell][azure_powershell]: PS> Connect-AzAccount ``` -If the account / service principal has access to multiple tenants (subscriptions), ensure that the `Get-AzContext` cmdlet returns the correct subscription: +If the account/service principal has access to multiple tenants (subscriptions), ensure that the `Get-AzContext` cmdlet returns the correct subscription: ```powershell PS> Get-AzContext @@ -433,13 +430,13 @@ function withAzurePowerShellCredential() { #### Authenticating in Azure with managed identity -This examples demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `ManagedIdentityCredential` in a virtual machine, app service, function app, cloud shell, or AKS environment on Azure, with system assigned, or user assigned managed identity enabled. +This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] using the `ManagedIdentityCredential` in a virtual machine, app service, function app, cloud shell, or AKS environment on Azure, with system-assigned or user-assigned managed identity enabled. -For more information about how to configure your Azure resource for managed identity please refer to [Configure managed identities for Azure resources](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/qs-configure-cli-windows-vm). +For more information about configuring your Azure resource for managed identity, please refer to [Configure managed identities for Azure resources](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/qs-configure-cli-windows-vm). ```ts /** - * Authenticate with a system assigned managed identity. + * Authenticate with a system-assigned managed identity. */ function withSystemAssignedManagedIdentityCredential() { const credential = new ManagedIdentityCredential(); @@ -448,7 +445,7 @@ function withSystemAssignedManagedIdentityCredential() { } /** - * Authenticate with a user assigned managed identity. + * Authenticate with a user-assigned managed identity. */ function withUserManagedIdentityCredential() { const credential = new ManagedIdentityCredential(""); @@ -459,7 +456,7 @@ function withUserManagedIdentityCredential() { ## Chaining credentials -The `ChainedTokenCredential` class provides the ability to link together multiple credential instances to be tried sequentially when authenticating. The following example demonstrates creating a credential which will attempt to authenticate a `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] using managed identity, and fall back to certificate authentication if a managed identity is unavailable in the current environment. +The `ChainedTokenCredential` class provides the ability to link together multiple credential instances to be tried sequentially when authenticating. The following example demonstrates creating a credential that will attempt to authenticate a `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] using managed identity and fall back to certificate authentication if a managed identity is unavailable in the current environment. ```ts function withChainedTokenCredential() { @@ -475,7 +472,7 @@ function withChainedTokenCredential() { ### Determine the Azure Authority Host for Azure Stack -In powershell run this command or have your Azure Stack Administrator run this command: +In PowerShell, run this command or have your Azure Stack Administrator run this command: ```powershell Get-AzEnvironment -Name @@ -493,8 +490,7 @@ The ActiveDirectory Authority in the output will be your Azure Authority Host ### Determine the Tenant ID for Azure Stack -If the Identity provider of your Azure Stack is Azure Active Directory (Azure AD) then contact your Azure Stack Administrator to find out your tenant ID. -else, if the Identity provider of your Azure Stack is Active Directory Federation Services (AD FS) then your tenant id is `adfs`. +If the Identity provider of your Azure Stack is Azure Active Directory (Azure AD), then contact your Azure Stack Administrator to find out your tenant ID. Otherwise, if the Identity provider of your Azure Stack is Active Directory Federation Services (AD FS), then your tenant id is `adfs`. ### Authentication example @@ -521,17 +517,15 @@ function main() { ### Custom Credentials -The `@azure/identity` library covers a broad range of Azure Active Directory authentication scenarios. However, it's possible the credential implementations provided might not meet the specific needs your application, or an application might want to avoid taking a dependency on the `@azure/identity` library. In such cases, you may want to write your own credential. +The `@azure/identity` library covers a broad range of Azure Active Directory authentication scenarios. However, we understand there are cases in which the credentials provided might not meet the specific needs of your application. Some applications might want to avoid taking a dependency on the `@azure/identity` package. In such cases, you may want to write your custom credential. -In this section we'll examine some such scenarios. +In this section, we'll examine some such scenarios. ### Authenticating with a pre-fetched access token -Our package `@azure/core-auth` exports a `TokenCredential` interface which is used by the `@azure/identity` package to define a common public API for all of the Identity credentials that we offer. - -The `@azure/identity` library does not contain a `TokenCredential` implementation which can be constructed directly with an `AccessToken`. This is intentionally omitted as a main line scenario as access tokens expire frequently and have constrained usage. However, we understand there may be some scenarios where authenticating a service client with a pre-fetched token is necessary. +Our package `@azure/core-auth` exports a `TokenCredential` interface used by the `@azure/identity` package to define a standard public API for all of the Identity credentials we offer. We understand there are cases in which it will be convenient to create custom credentials. One example is when a token is pre-fetched, a custom `TokenCredential` can return that token as an `AccessToken` to the Azure SDK clients. -In this example, `StaticTokenCredential` implements the `TokenCredential` abstraction. It takes a pre-fetched access token in its constructor as an [AccessToken](https://docs.microsoft.com/javascript/api/@azure/core-auth/accesstoken), and simply returns that from its implementation of `getToken()`. +In this example, `StaticTokenCredential` implements the `TokenCredential` abstraction. It takes a pre-fetched access token in its constructor as an [AccessToken](https://docs.microsoft.com/javascript/api/@azure/core-auth/accesstoken), and returns that from its implementation of `getToken()`. > You'll need to install the [@azure/core-auth][core_auth] package for this sample. @@ -539,6 +533,9 @@ In this example, `StaticTokenCredential` implements the `TokenCredential` abstra import { TokenCredential, AccessToken } from "@azure/core-auth"; class StaticTokenCredential implements TokenCredential { + // AccessToken is an object with two properties: + // - A "token" property with a string value. + // - And an "expiresOnTimestamp" property with a numeric unix timestamp as its value. constructor(private accessToken: AccessToken) {} async getToken(): Promise { return this.accessToken; @@ -546,25 +543,31 @@ class StaticTokenCredential implements TokenCredential { } ``` -Once the application has defined this credential, it can be used to authenticate Azure SDK clients. The following example shows how an application already using some other mechanism for acquiring tokens (in this case the hypothetical method `getTokenForScope()`) could use the `StaticTokenCredential` to authenticate a `SecretClient` from `@azure/keyvault-secrets`. +Once the application has defined this credential, it can authenticate Azure SDK clients with a pre-fetched `AccessToken`. The following example shows how an application already using some other mechanism for acquiring tokens (the hypothetical method `getTokenForScope()`) could use the `StaticTokenCredential` to authenticate a `SecretClient` from `@azure/keyvault-secrets`. ```ts import { SecretClient } from "@azure/keyvault-secrets"; +// StaticTokenCredential would be defined before the main() function... + async function main() { - const token = getTokenForScope("https://vault.azure.net/.default"); + const accessToken = getTokenForScope("https://vault.azure.net/.default"); + + // In this case, `accessToken` has to contain two properties: + // - A "token" property with a string value. + // - And an "expiresOnTimestamp" property with a numeric unix timestamp as its value. - const credential = new StaticTokenCredential(token); + const credential = new StaticTokenCredential(accessToken); const client = new SecretClient("https://myvault.vault.azure.net/", credential); } ``` -It should be noted when using this custom credential type, it is the responsibility of the caller to ensure that the token is valid, and contains the correct claims needed to authenticate calls from the particular service client. For instance in the above case the token must have the scope "https://vault.azure.net/.default" to authorize calls to Azure Blob Storage. +When using this custom credential type, it is the caller's responsibility to ensure that the token is valid and contains the correct claims needed to authenticate calls from the particular service client. For instance in the above case the token must have the scope "https://vault.azure.net/.default" to authorize calls to Azure Blob Storage. ### Authenticating with MSAL Directly -Some applications already use the `@azure/msal-node` or `@azure/msal-browser` to authenticate portions of their application. In these cases, the application might want to use the same to authenticate Azure SDK clients, to take advantage of the token caching the MSAL client application is doing, and to prevent unnecessary authentication calls. +Some applications already use the `@azure/msal-node` or `@azure/msal-browser` to authenticate portions of their application. In these cases, the application might want to use the same to authenticate Azure SDK clients, to take advantage of the token caching the MSAL client application is doing, and preventing unnecessary authentication calls. #### Authenticating with the @azure/msal-node Confidential Client @@ -573,7 +576,7 @@ In this example the [ConfidentialClientApplicationCredential](https://github.com You'll need to install the [@azure/msal-node][msal_node_npm] and the the [@azure/core-auth][core_auth] package for this sample. > For more information about MSAL for Node.js, please refer to [the README of the `@azure/msal-node` package][msal_node_readme]. -> For more information about working with the Confidential Client of MSAL, please refer to: [Initialization of MSAL (Node.js)](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md). +> For more information about working with the Confidential Client of MSAL, please refer to [Initialization of MSAL (Node.js)](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md). ```ts import { TokenCredential, AccessToken } from "@azure/core-auth"; @@ -613,15 +616,15 @@ async function main() { #### Authenticating with the @azure/msal-node On Behalf Of Flow -Currently the `@azure/identity` library doesn't provide a credential type for clients which need to authenticate via the [On Behalf of Flow](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-common/docs/request.md#on-behalf-of-flow). While future support for this is planned, users currently requiring this will have to implement their own `TokenCredential` class. +Currently, the `@azure/identity` library doesn't provide a credential type for clients which need to authenticate via the [On Behalf of Flow](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-common/docs/request.md#on-behalf-of-flow). While we may add support for this feature in the future, users currently requiring this will have to implement their own `TokenCredential` class. -In this example the `OnBehalfOfCredential` accepts a client ID, client secret, and a user's access token. It then creates an instance of `ConfidentialClientApplication` from MSAL to obtain an OBO token which can be used to authenticate client requests. +In this example, the `OnBehalfOfCredential` accepts a client ID, client secret, and a user's access token. It then creates an instance of `ConfidentialClientApplication` from MSAL to obtain an OBO token that can authenticate client requests. You'll need to install the [@azure/msal-node][msal_node_npm] and the the [@azure/core-auth][core_auth] package for this sample. > For more information about MSAL for Node.js, please refer to [the README of the `@azure/msal-node` package][msal_node_readme]. -> For more information about working with the Confidential Client of MSAL, please refer to: [Initialization of MSAL (Node.js)](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md). -> For more information about working with the On Behalf Flow with MSAL, please refer to: [On Behalf of Flow](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-common/docs/request.md#on-behalf-of-flow). +> For more information about working with the Confidential Client of MSAL, please refer to [Initialization of MSAL (Node.js)](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md). +> For more information about working with the On Behalf Flow with MSAL, please refer to [On Behalf of Flow](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-common/docs/request.md#on-behalf-of-flow). ```ts import { TokenCredential, AccessToken } from "@azure/core-auth"; @@ -669,7 +672,7 @@ async function main() { #### Authenticating with the @azure/msal-browser Public Client -While `@azure/identity` provides some browser support, for users that need the full set of features provided by `@azure/msal-browser`, it is possible to implement a `TokenCredential` on top of MSAL's public API for the browsers. +While `@azure/identity` provides some browser support, for users that need the complete set of features offered by `@azure/msal-browser`, it is possible to implement a `TokenCredential` on top of MSAL's public API for the browsers. You'll need to install the [@azure/msal-browser][msal_browser_npm] and the the [@azure/core-auth][core_auth] package for this sample. @@ -741,7 +744,7 @@ class BrowserCredential implements TokenCredential { } ``` -The following example shows an how the `BrowserCredential` could be used to authenticate a `ServiceBusClient`. Keep in mind that for this example to work, the redirect URI configured in the AAD application should point to the same page that runs this code originally (for example, `http://localhost:80`): +The following example shows how the `BrowserCredential` could be used to authenticate a `ServiceBusClient`. Keep in mind that for this example to work, the redirect URI configured in the AAD application should point to the same page that runs this code originally (for example, `http://localhost:80`): ```ts import { ServiceBusClient } from "@azure/service-bus"; @@ -761,11 +764,11 @@ async function main() { ### Authenticating with Key Vault Certificates -Azure Key Vault allows users to create certificates that can be used to authenticate Azure SDK clients. +Azure Key Vault supports creating secure certificates that can be used to authenticate Azure SDK clients. -Key Vault Certificates can be created through different means. For example, using the Azure CLI: [Quickstart: Set and retrieve a certificate from Azure Key Vault using Azure CLI](https://docs.microsoft.com/azure/key-vault/certificates/quick-create-cli). +There are different ways to create Key Vault Certificates. For example, through the Azure CLI: [Quickstart: Set and retrieve a certificate from Azure Key Vault using Azure CLI](https://docs.microsoft.com/azure/key-vault/certificates/quick-create-cli). -Once you have a certificate, you may export the certificate with the Azure CLI following the steps at: [Export certificates from Azure Key Vault](https://docs.microsoft.com/azure/key-vault/certificates/how-to-export-certificate?tabs=azure-cli). +Once you have a certificate, you may export the certificate with the Azure CLI following the steps at [Export certificates from Azure Key Vault](https://docs.microsoft.com/azure/key-vault/certificates/how-to-export-certificate?tabs=azure-cli). You can also export your certificate through the portal by going to your Key Vault, going to a specific certificate, then downloading the certificate in PFX/PEM format. @@ -783,13 +786,13 @@ const credential = new ClientCertificateCredential( ### Rolling Certificates -Long running applications may have the need to roll certificates during process execution. Certificate rotation is not currently supported by the `ClientCertificateCredential` which treats the certificate used to construct the credential as immutable. This means that any clients constructed with an `ClientCertificateCredential` using a particular cert would fail to authenticate requests after that cert has been rolled and the original is no longer valid. +Long-running applications may need to roll certificates during process execution. At the moment, the `ClientCertificateCredential` does not support certificate rotation (the credential treats the certificate provided as immutable). Therefore, clients constructed with a `ClientCertificateCredential` using a particular cert would fail to authenticate requests after that certificate rolls and the original is no longer valid. -However, if an application wants to roll this certificate without creating new service clients, it can accomplish this by creating its own `TokenCredential` implementation which wraps the `ClientCertificateCredential`. The implementation of this custom credential `TokenCredential` would somewhat depend on how the application handles certificate rotation. +However, if an application wants to roll this certificate without creating new service clients, it can accomplish this by creating its own `TokenCredential` implementation, which wraps the `ClientCertificateCredential`. Implementing this custom `TokenCredential` would somewhat depend on how the application handles certificate rotation. #### Explicit rotation -If the application gets notified of certificate rotations and it can directly respond, it might choose to wrap the `ClientCertificateCredential` in a custom credential which provides a means for rotating the certificate. +If the application gets notified of certificate rotations and can directly respond, it might choose to wrap the `ClientCertificateCredential` in a custom credential which provides a means for rotating the certificate. > You'll need to install the [@azure/core-auth][core_auth] package for this sample. @@ -822,11 +825,11 @@ class RotatableCertificateCredential implements TokenCredential { } ``` -The above example shows a custom credential type `RotatableCertificateCredential` which provides a `rotateCertificate`. The implementation internally relies on an instance of `ClientCertificateCredential`, and `rotateCertificate` simply replaces this instance with a new one using the new certificate path. +The above example shows a custom credential type `RotatableCertificateCredential`, which provides a `rotateCertificate`. The implementation internally relies on an instance of `ClientCertificateCredential`, and `rotateCertificate` replaces this instance with a new one using the new certificate path. #### Implicit rotation -Some applications might want to respond to certificate rotations which are external to the application, for instance a separate process rotates the certificate by updating it on disk. Here the application create a custom credential which checks for certificate updates when tokens are requested. +Some applications might want to respond to certificate rotations that are external to the application. For instance, a separate process rotates the certificate by updating it on disk. Here the application creates a custom credential that checks for certificate updates when tokens are requested. ```ts import { TokenCredential, GetTokenOptions, AccessToken } from "@azure/core-auth"; @@ -873,6 +876,7 @@ class RotatingCertificateCredential implements TokenCredential { ); this.promise = null; } + resolve(); } }); }); @@ -880,12 +884,13 @@ class RotatingCertificateCredential implements TokenCredential { } ``` -In this example the custom credential type `RotatingCertificateCredential` again uses a `ClientCertificateCredential` instance to retrieve tokens. However, in this case it will attempt to refresh the certificate prior to obtaining the token. The method `RefreshCertificate` will query to see if the certificate has changed, and if so it will replace `this.credential` with a new instance of the certificate credential using the same certificate path. +In this example, the custom credential type `RotatingCertificateCredential` again uses a `ClientCertificateCredential` instance to retrieve tokens. However, in this case, it will attempt to refresh the certificate before obtaining the token. The method `RefreshCertificate` will query to see if the certificate has changed. If so, it will replace `this.credential` with a new instance of the certificate credential using the same certificate path. [azure_cli]: https://docs.microsoft.com/cli/azure [secrets_client_library]: https://www.npmjs.com/package/@azure/keyvault-secrets +[service_bus_client_library]: https://www.npmjs.com/package/@azure/service-bus [azure_managed_identities]: https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview [service_principal_azure_cli]: https://docs.microsoft.com/cli/azure/create-an-azure-service-principal-azure-cli [device_code_flow]: https://github.com/Azure/azure-sdk-for-java/wiki/Set-up-Your-Environment-for-Authentication#enable-applications-for-device-code-flow From c5b21fe66b232ea363ebb7efb114c6bf878f9bad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodr=C3=ADguez?= Date: Tue, 15 Jun 2021 20:20:12 -0400 Subject: [PATCH 16/22] Apply suggestions from code review Co-authored-by: Scott Addie <10702007+scottaddie@users.noreply.github.com> --- .../identity/samples/AzureIdentityExamples.md | 98 +++++++++++-------- 1 file changed, 55 insertions(+), 43 deletions(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index 39257c402623..eafe654aaaa3 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -23,11 +23,11 @@ ## Introduction -Authenticating your application, users, and principals is an integral part of working with the Azure Client Libraries. The Azure Identity library provides multiple ways to gain access to the Azure services, each with a flexible configuration that covers most scenarios. While we have example code in [JavaScript](https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/identity/identity/samples/javascript) and [TypeScript](https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/identity/identity/samples/typescript) that cover the basic authentication scenarios, in this document, we will go over several use cases of Identity with greater context and links to the underlying authentication flows and other available documentation. +Authenticating your application, users, and principals is an integral part of working with the Azure client libraries. The Azure Identity library provides multiple ways to gain access to the Azure services, each with a flexible configuration that covers most scenarios. There is sample code in [JavaScript](https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/identity/identity/samples/javascript) and [TypeScript](https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/identity/identity/samples/typescript) to cover the basic authentication scenarios. This document covers several use cases of Identity with greater context and links to the underlying authentication flows and other available documentation. ## Authenticating client-side browser applications -For client-side applications running in the browser, the `InteractiveBrowserCredential` provides the most direct user authentication experience and is the only credential type that we support in the browser. To get started, you need to register your application in the Microsoft identity platform and set the proper permissions. +For client-side applications running in the browser, the `InteractiveBrowserCredential` provides the most direct user authentication experience. It's the only credential type that we support in the browser. To get started, register your application in the Microsoft Identity platform and set the proper permissions. - [Register a single page application](https://docs.microsoft.com/azure/active-directory/develop/scenario-spa-app-registration) in the Microsoft identity platform - Configure the app registration with a redirect URI to specify where the Microsoft identity platform should redirect the client along with any security tokens. @@ -36,7 +36,7 @@ For client-side applications running in the browser, the `InteractiveBrowserCred - * Ensure that your application has the correct permission for the APIs it intends to use. - In your app registration in the Azure portal, go to `API Permissions` - Click on `Add a permission` - - Select the API you want to use. For example, if you are using any of our management/control plane packages, i.e., the ones whose name starts with `@azure/arm-`, then you should select ``Azure Service Management`. + - Select the API you want to use. For example, if you're using any of our management/control plane packages, i.e., the ones whose name starts with `@azure/arm-`, you should select `Azure Service Management`. - Ensure that your AAD Application has enabled public authentication flows: - Go to Azure Active Directory in the Azure portal and find your app registration. - Navigate to the **Authentication** section. @@ -104,7 +104,7 @@ To learn more, read [Application and service principal objects in Azure Active D | [ClientSecretCredential](#authenticating-a-service-principal-with-a-client-secret) | Authenticates a service principal using a secret. | | [ClientCertificateCredential](#authenticating-a-service-principal-with-a-client-certificate) | Authenticates a service principal using a certificate. | | [EnvironmentCredential](#authenticating-a-service-principal-with-environment-credentials) | Authenticates a service principal or user via credential information specified in environment variables. | -| [DefaultAzureCredential](#authenticating-with-defaultazurecredential) | Tries `EnvironmentCredential`, `AzureCliCredential`, `AzurePowerShellCredential`, and other credentials sequentially until one of them succeeds. Use this to have your application authenticate using developer tools, service principals, or managed identity based on what is available in the current environment without changing your code. | +| [DefaultAzureCredential](#authenticating-with-defaultazurecredential) | Tries `EnvironmentCredential`, `AzureCliCredential`, `AzurePowerShellCredential`, and other credentials sequentially until one of them succeeds. Use this to have your application authenticate using developer tools, service principals, or managed identity based on what's available in the current environment without changing your code. | ### Authenticating Azure Hosted Applications @@ -119,7 +119,7 @@ If your application is hosted in Azure, you can make use of [Managed Identity](h #### Authenticating with `DefaultAzureCredential` -This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `DefaultAzureCredential`. There's also [a runnable sample](https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/identity/identity/samples/typescript/src/defaultAzureCredential.ts) to create a Key Vault key client you can copy-paste. The `DefaultAzureCredential` makes for a simple starting point as it provides sane defaults with minimal configuration and chains multiple credentials together. While your project may eventually need only a specific set of credentials, it is a sensible first choice for most scenarios where a project in active development will be running in the Azure Cloud. +This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `DefaultAzureCredential`. There's also [a runnable sample](https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/identity/identity/samples/typescript/src/defaultAzureCredential.ts) to create a Key Vault key client you can copy-paste. The `DefaultAzureCredential` provides sane defaults with minimal configuration and chains multiple credentials together. While your project may eventually need only a specific set of credentials, it's a sensible first choice for most scenarios in which a project in active development will be running in the Azure Cloud. ```ts /** @@ -136,7 +136,7 @@ function withDefaultAzureCredential() { This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `DefaultAzureCredential`, deployed to an Azure resource with a user-assigned managed identity configured. -For more information about configuring a user-assigned managed identity for an Azure resource, please refer to [What are managed identities for Azure resources][azure_managed_identities]. +For more information about configuring a user-assigned managed identity for an Azure resource, refer to [What are managed identities for Azure resources][azure_managed_identities]. ```ts /** @@ -158,7 +158,7 @@ For clients with a default browser available and client-side applications runnin For Node.js, if a `clientId` is provided, the Azure Active Directory application will need to be configured to have a "Mobile and desktop applications" redirect endpoint. Follow our guide on [setting up Redirect URIs for Desktop apps that calls to web APIs](https://docs.microsoft.com/azure/active-directory/develop/scenario-desktop-app-registration#redirect-uris). -For client-side applications running in the browser, the `InteractiveBrowserCredential` is the only credential type that is supported. Please see [Authenticating client-side browser applications](#authenticating-client-side-browser-applications). +For client-side applications running in the browser, the `InteractiveBrowserCredential` is the only credential type that is supported. For more information, see [Authenticating client-side browser applications](#authenticating-client-side-browser-applications). ```ts function withInteractiveBrowserCredential() { @@ -179,9 +179,9 @@ You'll need to: - [Create an application registration][quickstart-register-app] - [Create a Service Principal with the Azure CLI][service_principal_azure_cli] or [Create an Azure service principal with Azure PowerShell][service_principal_azure_powershell] -To learn more about service principals, read [Application and service principal objects in Azure Active Directory][app-register-service-principal] +To learn more about service principals, see [Application and service principal objects in Azure Active Directory][app-register-service-principal]. -In the sample below, an application authenticates a `SecretClient` from the [@azure/service-bus][service_bus_client_library] using the `ClientSecretCredential`. +In the following sample, an application authenticates a `SecretClient` from the [@azure/service-bus][service_bus_client_library] using the `ClientSecretCredential`: ```ts /** @@ -199,7 +199,10 @@ function withClientSecretCredential() { #### Authenticating a service principal with environment credentials -This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `EnvironmentCredential`. The `EnvironmentCredential` looks for well-known environment variable names to determine how it should authenticate. It effectively acts as a wrapper for the `ClientSecretCredential`, `ClientCertificateCredential`, or `UsernamePasswordCredential`, depending on which environment variables are present. +This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `EnvironmentCredential`. The `EnvironmentCredential`: + +- Looks for well-known environment variable names to determine how it should authenticate. +- Acts as a wrapper for the `ClientSecretCredential`, `ClientCertificateCredential`, or `UsernamePasswordCredential`, depending on which environment variables are present. You'll need to: @@ -210,7 +213,7 @@ You'll need to: - `AZURE_CLIENT_ID`, containing the ID of the user/service principal to authenticate as. - `AZURE_CLIENT_SECRET`, containing a client secret created belonging to the same user/service principal. -To learn more about service principals, read [Application and service principal objects in Azure Active Directory][app-register-service-principal] +To learn more about service principals, see [Application and service principal objects in Azure Active Directory][app-register-service-principal]. ```ts /** @@ -231,7 +234,7 @@ You'll need to: - [Create an application registration][quickstart-register-app] - [Create a Service Principal with the Azure CLI][service_principal_azure_cli] or [Create an Azure service principal with Azure PowerShell][service_principal_azure_powershell] -To learn more about service principals, read [Application and service principal objects in Azure Active Directory][app-register-service-principal] +To learn more about service principals, see [Application and service principal objects in Azure Active Directory][app-register-service-principal]. ```ts /** @@ -249,17 +252,21 @@ function withClientCertificateCredential() { #### Authenticating a user account with device code flow -This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `DeviceCodeCredential`. The `DeviceCodeCredential` offers a credential that can be used with little to no setup - the user is free to use whatever browser they choose to complete the authentication process. +This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `DeviceCodeCredential`. The `DeviceCodeCredential` offers a credential that can be used with little to no setup. The user can use the browser of their choice to complete the authentication process. -To authenticate a user through device code flow, use the following steps: +To authenticate a user through device code flow, complete the following steps: 1. Go to Azure Active Directory in Azure portal and find your app registration. 2. Navigate to the **Authentication** section. 3. Under **Advanced settings**, select `yes` on the option `Allow public client flows`. -You also need to be the admin of your tenant to grant consent to your application when you log in for the first time. +You also need to be the administrator of your tenant to grant consent to your application when you log in for the first time. + +If you can't configure the device code flow option on your Active Directory, it may require your app to be multi-tenant. To make your app multi-tenant: -If you can't configure the device code flow option on your Active Directory, then it may require your app to be multi-tenant. To make your app multi-tenant, navigate to the **Authentication** panel, then select **Accounts in any organizational directory**. Then, select _yes_ for Treat application as Public Client. +1. Navigate to the **Authentication** panel. +2. Select **Accounts in any organizational directory**. +3. Then, select _yes_ for Treat application as Public Client. ```ts /** @@ -301,15 +308,15 @@ function withClientCertificateCredential() { #### Authenticating a user account with auth code flow -This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `AuthorizationCodeCredential` on a Node.js service intended as the back-end for a web application. This can be useful when you want complete control over the authentication flow or when the `InteractiveBrowserCredential` does not fit your use-case. +This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `AuthorizationCodeCredential` on a Node.js service intended as the back-end for a web application. This can be useful when you want complete control over the authentication flow or when the `InteractiveBrowserCredential` doesn't fit your use case. First, [register your application][quickstart-register-app] and get your client ID, tenant ID and redirect URL. -Next, prompt the user to login at the URL documented at [Microsoft identity platform and OAuth 2.0 authorization code flow](https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-auth-code-flow#request-an-authorization-code). You will need the client ID, tenant ID, redirect URL, and the scopes your application plans to access. +Next, prompt the user to login at the URL documented at [Microsoft identity platform and OAuth 2.0 authorization code flow](https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-auth-code-flow#request-an-authorization-code). You'll need the client ID, tenant ID, redirect URL, and the scopes your application plans to access. Then create an API at the redirect URL with the following code to access the Key Vault service. -For a complete example using the authorization code flow in Electron please refer to [our electron sample](https://github.com/Azure/azure-sdk-for-js/blob/master/samples/frameworks/electron/ts/src/authProvider.ts). +For a complete example using the authorization code flow in Electron, see [our electron sample](https://github.com/Azure/azure-sdk-for-js/blob/master/samples/frameworks/electron/ts/src/authProvider.ts). ```ts /** @@ -430,9 +437,9 @@ function withAzurePowerShellCredential() { #### Authenticating in Azure with managed identity -This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] using the `ManagedIdentityCredential` in a virtual machine, app service, function app, cloud shell, or AKS environment on Azure, with system-assigned or user-assigned managed identity enabled. +This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] using the `ManagedIdentityCredential` in a virtual machine, App Service, Functions app, Cloud Shell, or AKS environment on Azure, with system-assigned or user-assigned managed identity enabled. -For more information about configuring your Azure resource for managed identity, please refer to [Configure managed identities for Azure resources](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/qs-configure-cli-windows-vm). +For more information about configuring your Azure resource for managed identity, see [Configure managed identities for Azure resources](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/qs-configure-cli-windows-vm). ```ts /** @@ -490,7 +497,7 @@ The ActiveDirectory Authority in the output will be your Azure Authority Host ### Determine the Tenant ID for Azure Stack -If the Identity provider of your Azure Stack is Azure Active Directory (Azure AD), then contact your Azure Stack Administrator to find out your tenant ID. Otherwise, if the Identity provider of your Azure Stack is Active Directory Federation Services (AD FS), then your tenant id is `adfs`. +If the Identity provider of your Azure Stack is Azure Active Directory (Azure AD), contact your Azure Stack Administrator to find your tenant ID. Otherwise, if the Identity provider of your Azure Stack is Active Directory Federation Services (ADFS), your tenant ID is `adfs`. ### Authentication example @@ -517,15 +524,15 @@ function main() { ### Custom Credentials -The `@azure/identity` library covers a broad range of Azure Active Directory authentication scenarios. However, we understand there are cases in which the credentials provided might not meet the specific needs of your application. Some applications might want to avoid taking a dependency on the `@azure/identity` package. In such cases, you may want to write your custom credential. +The `@azure/identity` library covers a broad range of Azure Active Directory authentication scenarios. However, we understand there are cases in which the credentials provided might not meet the specific needs of your application. Some applications might avoid taking a dependency on the `@azure/identity` package. In such cases, you may want to write your custom credential. In this section, we'll examine some such scenarios. ### Authenticating with a pre-fetched access token -Our package `@azure/core-auth` exports a `TokenCredential` interface used by the `@azure/identity` package to define a standard public API for all of the Identity credentials we offer. We understand there are cases in which it will be convenient to create custom credentials. One example is when a token is pre-fetched, a custom `TokenCredential` can return that token as an `AccessToken` to the Azure SDK clients. +The [@azure/core-auth][core_auth] package exports a `TokenCredential` interface. The interface is used by the `@azure/identity` package to define a standard public API for all of the Identity credentials we offer. There are cases in which it's convenient to create custom credentials. For example, when a token is pre-fetched, a custom `TokenCredential` can return that token as an `AccessToken` to the Azure SDK clients. -In this example, `StaticTokenCredential` implements the `TokenCredential` abstraction. It takes a pre-fetched access token in its constructor as an [AccessToken](https://docs.microsoft.com/javascript/api/@azure/core-auth/accesstoken), and returns that from its implementation of `getToken()`. +In this example, `StaticTokenCredential` implements the `TokenCredential` abstraction. It takes a pre-fetched access token in its constructor as an [AccessToken](https://docs.microsoft.com/javascript/api/@azure/core-auth/accesstoken) and returns that from its implementation of `getToken()`. > You'll need to install the [@azure/core-auth][core_auth] package for this sample. @@ -563,20 +570,20 @@ async function main() { } ``` -When using this custom credential type, it is the caller's responsibility to ensure that the token is valid and contains the correct claims needed to authenticate calls from the particular service client. For instance in the above case the token must have the scope "https://vault.azure.net/.default" to authorize calls to Azure Blob Storage. +When using this custom credential type, it's the caller's responsibility to ensure the token is valid and contains the correct claims needed to authenticate calls from the particular service client. In the preceding case, the token must have the scope `https://vault.azure.net/.default` to authorize calls to Azure Blob Storage. ### Authenticating with MSAL Directly -Some applications already use the `@azure/msal-node` or `@azure/msal-browser` to authenticate portions of their application. In these cases, the application might want to use the same to authenticate Azure SDK clients, to take advantage of the token caching the MSAL client application is doing, and preventing unnecessary authentication calls. +Some applications already use the [@azure/msal-node][msal_node_npm] or [@azure/msal-browser][msal_browser_npm] package to authenticate portions of their application. In these cases, the application might want to use the same to authenticate Azure SDK clients, to take advantage of the token caching the MSAL client application is doing, and preventing unnecessary authentication calls. #### Authenticating with the @azure/msal-node Confidential Client -In this example the [ConfidentialClientApplicationCredential](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md) is constructed with an instance of `ConfidentialClientApplication` it then implements `getToken()` using the `acquireTokenByClientCredential()` method to acquire a token. +In this example, the [ConfidentialClientApplicationCredential](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md) is constructed with an instance of `ConfidentialClientApplication` it then implements `getToken()` using the `acquireTokenByClientCredential()` method to acquire a token. You'll need to install the [@azure/msal-node][msal_node_npm] and the the [@azure/core-auth][core_auth] package for this sample. -> For more information about MSAL for Node.js, please refer to [the README of the `@azure/msal-node` package][msal_node_readme]. -> For more information about working with the Confidential Client of MSAL, please refer to [Initialization of MSAL (Node.js)](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md). +> For more information about MSAL for Node.js, see [the README of the `@azure/msal-node` package][msal_node_readme]. +> For more information about working with the Confidential Client of MSAL, see [Initialization of MSAL (Node.js)](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md). ```ts import { TokenCredential, AccessToken } from "@azure/core-auth"; @@ -622,9 +629,9 @@ In this example, the `OnBehalfOfCredential` accepts a client ID, client secret, You'll need to install the [@azure/msal-node][msal_node_npm] and the the [@azure/core-auth][core_auth] package for this sample. -> For more information about MSAL for Node.js, please refer to [the README of the `@azure/msal-node` package][msal_node_readme]. -> For more information about working with the Confidential Client of MSAL, please refer to [Initialization of MSAL (Node.js)](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md). -> For more information about working with the On Behalf Flow with MSAL, please refer to [On Behalf of Flow](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-common/docs/request.md#on-behalf-of-flow). +> For more information about MSAL for Node.js, see [the README of the `@azure/msal-node` package][msal_node_readme]. +> For more information about working with the Confidential Client of MSAL, see [Initialization of MSAL (Node.js)](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md). +> For more information about working with the On Behalf Flow with MSAL, see [On Behalf of Flow](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-common/docs/request.md#on-behalf-of-flow). ```ts import { TokenCredential, AccessToken } from "@azure/core-auth"; @@ -658,7 +665,7 @@ class OnBehalfOfCredential implements TokenCredential { } ``` -The following example shows an how the `OnBehalfOfCredential` could be used to authenticate a `SecretClient`. +The following example shows an how the `OnBehalfOfCredential` could be used to authenticate a `SecretClient`: ```ts import { SecretClient } from "@azure/keyvault-secrets"; @@ -672,13 +679,18 @@ async function main() { #### Authenticating with the @azure/msal-browser Public Client -While `@azure/identity` provides some browser support, for users that need the complete set of features offered by `@azure/msal-browser`, it is possible to implement a `TokenCredential` on top of MSAL's public API for the browsers. +While `@azure/identity` provides some browser support, for users that need the complete feature set offered by `@azure/msal-browser`, it's possible to implement a `TokenCredential` on top of MSAL's public API for the browsers. You'll need to install the [@azure/msal-browser][msal_browser_npm] and the the [@azure/core-auth][core_auth] package for this sample. -> For more information about MSAL for browsers, please refer to [the README of the `@azure/msal-browser` package][msal_browser_readme]. +> For more information about MSAL for browsers, see [the README of the `@azure/msal-browser` package][msal_browser_readme]. + +For this example, you'll define a `BrowserCredential` class with the following methods: -For this example, we will define a `BrowserCredential` class that has a `getToken` method (which will use the Silent Authentication flow, retrieving the account from memory, as we want to prevent unnecessary redirections), and also a `prepare()` method that will try either to check if the account has previously authenticated, or to parse the redirection URI values if present, also a `hasAuthenticated` method which can be used to know if the authentication has taken place, and finally a `loginRedirect` method, which if called will trigger the authentication via redirection. +- `getToken` — Will use the Silent Authentication flow, retrieving the account from memory to prevent unnecessary redirections. +- `prepare` — Will try either to check if the account has previously authenticated or to parse the redirection URI values if present. +- `hasAuthenticated` — Can be used to determine if the authentication has taken place. +- `loginRedirect` — If called, this method triggers the authentication via redirection. ```ts import { TokenCredential, AccessToken } from "@azure/core-auth"; @@ -744,7 +756,7 @@ class BrowserCredential implements TokenCredential { } ``` -The following example shows how the `BrowserCredential` could be used to authenticate a `ServiceBusClient`. Keep in mind that for this example to work, the redirect URI configured in the AAD application should point to the same page that runs this code originally (for example, `http://localhost:80`): +The following example shows how the `BrowserCredential` could be used to authenticate a `ServiceBusClient`. For this example to work, the redirect URI configured in the AAD application should point to the same page that runs this code originally. For example, `http://localhost:80`. ```ts import { ServiceBusClient } from "@azure/service-bus"; @@ -766,15 +778,15 @@ async function main() { Azure Key Vault supports creating secure certificates that can be used to authenticate Azure SDK clients. -There are different ways to create Key Vault Certificates. For example, through the Azure CLI: [Quickstart: Set and retrieve a certificate from Azure Key Vault using Azure CLI](https://docs.microsoft.com/azure/key-vault/certificates/quick-create-cli). +There are different ways to create Key Vault certificates. For example, through the Azure CLI: [Quickstart: Set and retrieve a certificate from Azure Key Vault using Azure CLI](https://docs.microsoft.com/azure/key-vault/certificates/quick-create-cli). Once you have a certificate, you may export the certificate with the Azure CLI following the steps at [Export certificates from Azure Key Vault](https://docs.microsoft.com/azure/key-vault/certificates/how-to-export-certificate?tabs=azure-cli). You can also export your certificate through the portal by going to your Key Vault, going to a specific certificate, then downloading the certificate in PFX/PEM format. -Once you have a Key Vault certificate downloaded, go to Azure Active Directory, find the Enterprise app you want to authenticate with, go to `Certificates & secrets` and then upload the certificate. +Once you have a Key Vault certificate downloaded, go to Azure Active Directory. Find the Enterprise app you want to authenticate with, go to `Certificates & secrets`, and upload the certificate. -After that, you'll be able to authenticate by pointing the `@azure/identity`'s `ClientCertificateCredential` to the path where your PEM certificate is, as follows: +After that, you can authenticate by pointing the `@azure/identity`'s `ClientCertificateCredential` to the PEM certificate's path, as follows: ```ts const credential = new ClientCertificateCredential( @@ -786,7 +798,7 @@ const credential = new ClientCertificateCredential( ### Rolling Certificates -Long-running applications may need to roll certificates during process execution. At the moment, the `ClientCertificateCredential` does not support certificate rotation (the credential treats the certificate provided as immutable). Therefore, clients constructed with a `ClientCertificateCredential` using a particular cert would fail to authenticate requests after that certificate rolls and the original is no longer valid. +Long-running applications may need to roll certificates during process execution. At the moment, the `ClientCertificateCredential` doesn't support certificate rotation. The credential treats the certificate provided as immutable. Therefore, clients constructed with a `ClientCertificateCredential` using a particular certificate would fail to authenticate requests after that certificate rolls and the original is no longer valid. However, if an application wants to roll this certificate without creating new service clients, it can accomplish this by creating its own `TokenCredential` implementation, which wraps the `ClientCertificateCredential`. Implementing this custom `TokenCredential` would somewhat depend on how the application handles certificate rotation. @@ -825,7 +837,7 @@ class RotatableCertificateCredential implements TokenCredential { } ``` -The above example shows a custom credential type `RotatableCertificateCredential`, which provides a `rotateCertificate`. The implementation internally relies on an instance of `ClientCertificateCredential`, and `rotateCertificate` replaces this instance with a new one using the new certificate path. +The preceding example shows a custom credential type `RotatableCertificateCredential`, which provides a `rotateCertificate`. The implementation internally relies on an instance of `ClientCertificateCredential`. `rotateCertificate` replaces this instance with a new one using the new certificate path. #### Implicit rotation From 371a5daa583c89627708ae9787c1f5619b6a79e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodr=C3=ADguez?= Date: Fri, 18 Jun 2021 12:59:41 -0400 Subject: [PATCH 17/22] Apply suggestions from code review Co-authored-by: Scott Addie <10702007+scottaddie@users.noreply.github.com> --- sdk/identity/identity/samples/AzureIdentityExamples.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index eafe654aaaa3..3094c887dea2 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -33,7 +33,7 @@ For client-side applications running in the browser, the `InteractiveBrowserCred - Configure the app registration with a redirect URI to specify where the Microsoft identity platform should redirect the client along with any security tokens. - If using v1 of `@azure/identity` package, follow the instructions at [Redirect URI: MSAL.js 1.0 with implicit flow](https://docs.microsoft.com/azure/active-directory/develop/scenario-spa-app-registration#redirect-uri-msaljs-10-with-implicit-flow) to set the redirect URI. - If using v2 of `@azure/identity` package, follow the instructions at [Redirect URI: MSAL.js 2.0 with auth code flow](https://docs.microsoft.com/azure/active-directory/develop/scenario-spa-app-registration#redirect-uri-msaljs-20-with-auth-code-flow) -- * Ensure that your application has the correct permission for the APIs it intends to use. +- Ensure that your application has the correct permission for the APIs it intends to use. - In your app registration in the Azure portal, go to `API Permissions` - Click on `Add a permission` - Select the API you want to use. For example, if you're using any of our management/control plane packages, i.e., the ones whose name starts with `@azure/arm-`, you should select `Azure Service Management`. @@ -316,7 +316,7 @@ Next, prompt the user to login at the URL documented at [Microsoft identity plat Then create an API at the redirect URL with the following code to access the Key Vault service. -For a complete example using the authorization code flow in Electron, see [our electron sample](https://github.com/Azure/azure-sdk-for-js/blob/master/samples/frameworks/electron/ts/src/authProvider.ts). +For a complete example using the authorization code flow in Electron, see [our Electron sample](https://github.com/Azure/azure-sdk-for-js/blob/master/samples/frameworks/electron/ts/src/authProvider.ts). ```ts /** @@ -479,7 +479,7 @@ function withChainedTokenCredential() { ### Determine the Azure Authority Host for Azure Stack -In PowerShell, run this command or have your Azure Stack Administrator run this command: +In PowerShell, run this command or have your Azure Stack administrator run this command: ```powershell Get-AzEnvironment -Name @@ -497,7 +497,7 @@ The ActiveDirectory Authority in the output will be your Azure Authority Host ### Determine the Tenant ID for Azure Stack -If the Identity provider of your Azure Stack is Azure Active Directory (Azure AD), contact your Azure Stack Administrator to find your tenant ID. Otherwise, if the Identity provider of your Azure Stack is Active Directory Federation Services (ADFS), your tenant ID is `adfs`. +If the Identity provider of your Azure Stack is Azure Active Directory (Azure AD), contact your Azure Stack administrator to find your tenant ID. Otherwise, if the Identity provider of your Azure Stack is Active Directory Federation Services (ADFS), your tenant ID is `adfs`. ### Authentication example @@ -782,7 +782,7 @@ There are different ways to create Key Vault certificates. For example, through Once you have a certificate, you may export the certificate with the Azure CLI following the steps at [Export certificates from Azure Key Vault](https://docs.microsoft.com/azure/key-vault/certificates/how-to-export-certificate?tabs=azure-cli). -You can also export your certificate through the portal by going to your Key Vault, going to a specific certificate, then downloading the certificate in PFX/PEM format. +You can also export your certificate through the Azure portal. Navigate to your Key Vault resource, go to a specific certificate, then download the certificate in PFX/PEM format. Once you have a Key Vault certificate downloaded, go to Azure Active Directory. Find the Enterprise app you want to authenticate with, go to `Certificates & secrets`, and upload the certificate. From 69c56abbb5909fbd31d211b26ed9325d2ac54066 Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Fri, 18 Jun 2021 19:10:47 +0000 Subject: [PATCH 18/22] prerequisites sections --- .../identity/samples/AzureIdentityExamples.md | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index 3094c887dea2..a942c3358edf 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -534,7 +534,9 @@ The [@azure/core-auth][core_auth] package exports a `TokenCredential` interface. In this example, `StaticTokenCredential` implements the `TokenCredential` abstraction. It takes a pre-fetched access token in its constructor as an [AccessToken](https://docs.microsoft.com/javascript/api/@azure/core-auth/accesstoken) and returns that from its implementation of `getToken()`. -> You'll need to install the [@azure/core-auth][core_auth] package for this sample. +**Prerequisites** + +Install the [@azure/core-auth][core_auth] package. ```ts import { TokenCredential, AccessToken } from "@azure/core-auth"; @@ -580,7 +582,9 @@ Some applications already use the [@azure/msal-node][msal_node_npm] or [@azure/m In this example, the [ConfidentialClientApplicationCredential](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md) is constructed with an instance of `ConfidentialClientApplication` it then implements `getToken()` using the `acquireTokenByClientCredential()` method to acquire a token. -You'll need to install the [@azure/msal-node][msal_node_npm] and the the [@azure/core-auth][core_auth] package for this sample. +**Prerequisites** + +Install the [@azure/msal-node][msal_node_npm] and [@azure/core-auth][core_auth]. > For more information about MSAL for Node.js, see [the README of the `@azure/msal-node` package][msal_node_readme]. > For more information about working with the Confidential Client of MSAL, see [Initialization of MSAL (Node.js)](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md). @@ -627,7 +631,9 @@ Currently, the `@azure/identity` library doesn't provide a credential type for c In this example, the `OnBehalfOfCredential` accepts a client ID, client secret, and a user's access token. It then creates an instance of `ConfidentialClientApplication` from MSAL to obtain an OBO token that can authenticate client requests. -You'll need to install the [@azure/msal-node][msal_node_npm] and the the [@azure/core-auth][core_auth] package for this sample. +**Prerequisites** + +Install the [@azure/msal-node][msal_node_npm] and [@azure/core-auth][core_auth]. > For more information about MSAL for Node.js, see [the README of the `@azure/msal-node` package][msal_node_readme]. > For more information about working with the Confidential Client of MSAL, see [Initialization of MSAL (Node.js)](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md). @@ -681,10 +687,6 @@ async function main() { While `@azure/identity` provides some browser support, for users that need the complete feature set offered by `@azure/msal-browser`, it's possible to implement a `TokenCredential` on top of MSAL's public API for the browsers. -You'll need to install the [@azure/msal-browser][msal_browser_npm] and the the [@azure/core-auth][core_auth] package for this sample. - -> For more information about MSAL for browsers, see [the README of the `@azure/msal-browser` package][msal_browser_readme]. - For this example, you'll define a `BrowserCredential` class with the following methods: - `getToken` — Will use the Silent Authentication flow, retrieving the account from memory to prevent unnecessary redirections. @@ -692,6 +694,12 @@ For this example, you'll define a `BrowserCredential` class with the following m - `hasAuthenticated` — Can be used to determine if the authentication has taken place. - `loginRedirect` — If called, this method triggers the authentication via redirection. +**Prerequisites** + +Install the [@azure/msal-browser][msal_browser_npm] and [@azure/core-auth][core_auth]. + +> For more information about MSAL for browsers, see [the README of the `@azure/msal-browser` package][msal_browser_readme]. + ```ts import { TokenCredential, AccessToken } from "@azure/core-auth"; import * as msalBrowser from "@azure/msal-browser"; @@ -806,7 +814,9 @@ However, if an application wants to roll this certificate without creating new s If the application gets notified of certificate rotations and can directly respond, it might choose to wrap the `ClientCertificateCredential` in a custom credential which provides a means for rotating the certificate. -> You'll need to install the [@azure/core-auth][core_auth] package for this sample. +**Prerequisites** + +Install the [@azure/core-auth][core_auth] package. ```ts import { TokenCredential, GetTokenOptions, AccessToken } from "@azure/core-auth"; From 0f2543a1db0a6b91a7ef81b9c50c85e6e0d68f0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodr=C3=ADguez?= Date: Mon, 21 Jun 2021 15:36:24 -0400 Subject: [PATCH 19/22] Apply suggestions from code review Co-authored-by: Scott Addie <10702007+scottaddie@users.noreply.github.com> --- .../identity/samples/AzureIdentityExamples.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index a942c3358edf..cce957af41dd 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -36,13 +36,13 @@ For client-side applications running in the browser, the `InteractiveBrowserCred - Ensure that your application has the correct permission for the APIs it intends to use. - In your app registration in the Azure portal, go to `API Permissions` - Click on `Add a permission` - - Select the API you want to use. For example, if you're using any of our management/control plane packages, i.e., the ones whose name starts with `@azure/arm-`, you should select `Azure Service Management`. + - Select the API you want to use. For example, if you're using any of our management/control plane packages (the ones whose name starts with `@azure/arm-`), you should select **Azure Service Management**. - Ensure that your AAD Application has enabled public authentication flows: - Go to Azure Active Directory in the Azure portal and find your app registration. - Navigate to the **Authentication** section. - - Under **Advanced settings**, select `yes` on the option `Allow public client flows`. + - Under **Advanced settings**, select **yes** on the option **Allow public client flows**. -Copy the client ID and tenant ID from the `Overview` section of your app registration in the Azure portal and use it in the below code snippet where we authenticate a `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] using the `InteractiveBrowserCredential`. +Copy the client ID and tenant ID from the **Overview** section of your app registration in the Azure portal and use it in the below code snippet where we authenticate a `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] using the `InteractiveBrowserCredential`. ```ts function withInteractiveBrowserCredential() { @@ -112,14 +112,14 @@ If your application is hosted in Azure, you can make use of [Managed Identity](h | Credential with example | Usage | | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [ManagedIdentityCredential](#authenticating-in-azure-with-managed-identity) | Authenticate in a virtual machine, app service, function app, cloud shell, or AKS environment on Azure, with system-assigned managed identity, user-assigned managed identity, or app registration (when working with AKS pod-identity). | +| [ManagedIdentityCredential](#authenticating-in-azure-with-managed-identity) | Authenticate in a virtual machine, App Service, Functions app, Cloud Shell, or AKS environment on Azure, with system-assigned managed identity, user-assigned managed identity, or app registration (when working with AKS pod identity). | | [DefaultAzureCredential](#authenticating-with-defaultazurecredential) | Tries `EnvironmentCredential`, `ManagedIdentityCredential`, `AzureCliCredential`, `AzurePowerShellCredential`, and other credentials sequentially until one of them succeeds. Use this to have your application authenticate using developer tools, service principals or managed identity based on what is available in the current environment without changing your code. | ### Examples #### Authenticating with `DefaultAzureCredential` -This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `DefaultAzureCredential`. There's also [a runnable sample](https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/identity/identity/samples/typescript/src/defaultAzureCredential.ts) to create a Key Vault key client you can copy-paste. The `DefaultAzureCredential` provides sane defaults with minimal configuration and chains multiple credentials together. While your project may eventually need only a specific set of credentials, it's a sensible first choice for most scenarios in which a project in active development will be running in the Azure Cloud. +This example demonstrates authenticating the `SecretClient` from the [@azure/keyvault-secrets][secrets_client_library] client library using the `DefaultAzureCredential`. There's also [a runnable sample](https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/identity/identity/samples/typescript/src/defaultAzureCredential.ts) to create a Key Vault key client you can copy-paste. The `DefaultAzureCredential` provides sane defaults with minimal configuration and chains multiple credentials together. While your project may eventually need only a specific set of credentials, it's a sensible first choice for most scenarios in which a project in active development will be running in the Azure cloud. ```ts /** @@ -217,7 +217,7 @@ To learn more about service principals, see [Application and service principal o ```ts /** - * Authenticate using the AZURE_TENANT_ID, AZURE_CLIENT_ID and AZURE_CLIENT_SECRET environment variables. + * Authenticate using the AZURE_TENANT_ID, AZURE_CLIENT_ID, and AZURE_CLIENT_SECRET environment variables. */ function withEnvironmentCredential() { let credential = new EnvironmentCredential(); @@ -266,7 +266,7 @@ If you can't configure the device code flow option on your Active Directory, it 1. Navigate to the **Authentication** panel. 2. Select **Accounts in any organizational directory**. -3. Then, select _yes_ for Treat application as Public Client. +3. Select **yes** for **Treat application as Public Client**. ```ts /** @@ -792,7 +792,7 @@ Once you have a certificate, you may export the certificate with the Azure CLI f You can also export your certificate through the Azure portal. Navigate to your Key Vault resource, go to a specific certificate, then download the certificate in PFX/PEM format. -Once you have a Key Vault certificate downloaded, go to Azure Active Directory. Find the Enterprise app you want to authenticate with, go to `Certificates & secrets`, and upload the certificate. +Once you have a Key Vault certificate downloaded, go to Azure Active Directory. Find the Enterprise app you want to authenticate with, go to **Certificates & secrets**, and upload the certificate. After that, you can authenticate by pointing the `@azure/identity`'s `ClientCertificateCredential` to the PEM certificate's path, as follows: From 69db4a29337523c8cdc1dd3de1639a84c5aad7d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodr=C3=ADguez?= Date: Wed, 23 Jun 2021 14:45:06 -0400 Subject: [PATCH 20/22] Update sdk/identity/identity/samples/AzureIdentityExamples.md Co-authored-by: Scott Addie <10702007+scottaddie@users.noreply.github.com> --- sdk/identity/identity/samples/AzureIdentityExamples.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index cce957af41dd..119c2dc5b3cb 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -90,7 +90,7 @@ Authenticating user accounts is the easiest way to get started with minimal set ### Authenticating Service Principals -An Azure service principal is an identity created for use with applications, hosted services, and automated tools to access Azure resources. The roles assigned by the service principal will determine what resources are accessible. For security reasons, we recommended using service principals through automation rather than allowing them to log in with a user identity. +An Azure service principal is an identity created for use with applications, hosted services, and automated tools to access Azure resources. The roles assigned by the service principal will determine what resources are accessible. For security reasons, use service principals through automation rather than allowing them to log in with a user identity. To learn more, read [Application and service principal objects in Azure Active Directory][app-register-service-principal] From 99ba628ff26ff08ba2e16c66da43a94f36c1e8f8 Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Thu, 24 Jun 2021 18:28:54 +0000 Subject: [PATCH 21/22] master -> main --- .../identity/samples/AzureIdentityExamples.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index 179ce57c7dff..ad0bbec2c61c 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -23,7 +23,7 @@ ## Introduction -Authenticating your application, users, and principals is an integral part of working with the Azure client libraries. The Azure Identity library provides multiple ways to gain access to the Azure services, each with a flexible configuration that covers most scenarios. There is sample code in [JavaScript](https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/identity/identity/samples/javascript) and [TypeScript](https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/identity/identity/samples/typescript) to cover the basic authentication scenarios. This document covers several use cases of Identity with greater context and links to the underlying authentication flows and other available documentation. +Authenticating your application, users, and principals is an integral part of working with the Azure client libraries. The Azure Identity library provides multiple ways to gain access to the Azure services, each with a flexible configuration that covers most scenarios. There is sample code in [JavaScript](https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/identity/identity/samples/javascript) and [TypeScript](https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/identity/identity/samples/typescript) to cover the basic authentication scenarios. This document covers several use cases of Identity with greater context and links to the underlying authentication flows and other available documentation. ## Authenticating client-side browser applications @@ -580,14 +580,14 @@ Some applications already use the [@azure/msal-node][msal_node_npm] or [@azure/m #### Authenticating with the @azure/msal-node Confidential Client -In this example, the [ConfidentialClientApplicationCredential](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md) is constructed with an instance of `ConfidentialClientApplication` it then implements `getToken()` using the `acquireTokenByClientCredential()` method to acquire a token. +In this example, the [ConfidentialClientApplicationCredential](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/main/lib/msal-node/docs/initialize-confidential-client-application.md) is constructed with an instance of `ConfidentialClientApplication` it then implements `getToken()` using the `acquireTokenByClientCredential()` method to acquire a token. **Prerequisites** Install the [@azure/msal-node][msal_node_npm] and [@azure/core-auth][core_auth]. > For more information about MSAL for Node.js, see [the README of the `@azure/msal-node` package][msal_node_readme]. -> For more information about working with the Confidential Client of MSAL, see [Initialization of MSAL (Node.js)](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md). +> For more information about working with the Confidential Client of MSAL, see [Initialization of MSAL (Node.js)](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/main/lib/msal-node/docs/initialize-confidential-client-application.md). ```ts import { TokenCredential, AccessToken } from "@azure/core-auth"; @@ -627,7 +627,7 @@ async function main() { #### Authenticating with the @azure/msal-node On Behalf Of Flow -Currently, the `@azure/identity` library doesn't provide a credential type for clients which need to authenticate via the [On Behalf of Flow](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-common/docs/request.md#on-behalf-of-flow). While we may add support for this feature in the future, users currently requiring this will have to implement their own `TokenCredential` class. +Currently, the `@azure/identity` library doesn't provide a credential type for clients which need to authenticate via the [On Behalf of Flow](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/main/lib/msal-common/docs/request.md#on-behalf-of-flow). While we may add support for this feature in the future, users currently requiring this will have to implement their own `TokenCredential` class. In this example, the `OnBehalfOfCredential` accepts a client ID, client secret, and a user's access token. It then creates an instance of `ConfidentialClientApplication` from MSAL to obtain an OBO token that can authenticate client requests. @@ -636,8 +636,8 @@ In this example, the `OnBehalfOfCredential` accepts a client ID, client secret, Install the [@azure/msal-node][msal_node_npm] and [@azure/core-auth][core_auth]. > For more information about MSAL for Node.js, see [the README of the `@azure/msal-node` package][msal_node_readme]. -> For more information about working with the Confidential Client of MSAL, see [Initialization of MSAL (Node.js)](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md). -> For more information about working with the On Behalf Flow with MSAL, see [On Behalf of Flow](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-common/docs/request.md#on-behalf-of-flow). +> For more information about working with the Confidential Client of MSAL, see [Initialization of MSAL (Node.js)](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/main/lib/msal-node/docs/initialize-confidential-client-application.md). +> For more information about working with the On Behalf Flow with MSAL, see [On Behalf of Flow](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/main/lib/msal-common/docs/request.md#on-behalf-of-flow). ```ts import { TokenCredential, AccessToken } from "@azure/core-auth"; @@ -919,8 +919,8 @@ In this example, the custom credential type `RotatingCertificateCredential` agai [quickstart-register-app]: https://docs.microsoft.com/azure/active-directory/develop/quickstart-register-app [app-register-service-principal]: https://docs.microsoft.com/azure/active-directory/develop/app-objects-and-service-principals [service_principal_azure_powershell]: https://docs.microsoft.com/powershell/azure/create-azure-service-principal-azureps -[msal_node_readme]: https://github.com/sadasant/microsoft-authentication-library-for-js/tree/master/lib/msal-node +[msal_node_readme]: https://github.com/sadasant/microsoft-authentication-library-for-js/tree/main/lib/msal-node [msal_node_npm]: https://www.npmjs.com/package/@azure/msal-node -[msal_browser_readme]: https://github.com/sadasant/microsoft-authentication-library-for-js/tree/master/lib/msal-browser +[msal_browser_readme]: https://github.com/sadasant/microsoft-authentication-library-for-js/tree/main/lib/msal-browser [msal_browser_npm]: https://www.npmjs.com/package/@azure/msal-browser [core_auth]: https://www.npmjs.com/package/@azure/core-auth From 0927bd8637eebb9e9d54254ffe9a396f052efe7c Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Thu, 24 Jun 2021 20:47:08 +0000 Subject: [PATCH 22/22] MSAL doesnt have main yet --- .../identity/samples/AzureIdentityExamples.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sdk/identity/identity/samples/AzureIdentityExamples.md b/sdk/identity/identity/samples/AzureIdentityExamples.md index ad0bbec2c61c..9fde9177df7f 100644 --- a/sdk/identity/identity/samples/AzureIdentityExamples.md +++ b/sdk/identity/identity/samples/AzureIdentityExamples.md @@ -580,14 +580,14 @@ Some applications already use the [@azure/msal-node][msal_node_npm] or [@azure/m #### Authenticating with the @azure/msal-node Confidential Client -In this example, the [ConfidentialClientApplicationCredential](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/main/lib/msal-node/docs/initialize-confidential-client-application.md) is constructed with an instance of `ConfidentialClientApplication` it then implements `getToken()` using the `acquireTokenByClientCredential()` method to acquire a token. +In this example, the [ConfidentialClientApplicationCredential](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md) is constructed with an instance of `ConfidentialClientApplication` it then implements `getToken()` using the `acquireTokenByClientCredential()` method to acquire a token. **Prerequisites** Install the [@azure/msal-node][msal_node_npm] and [@azure/core-auth][core_auth]. > For more information about MSAL for Node.js, see [the README of the `@azure/msal-node` package][msal_node_readme]. -> For more information about working with the Confidential Client of MSAL, see [Initialization of MSAL (Node.js)](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/main/lib/msal-node/docs/initialize-confidential-client-application.md). +> For more information about working with the Confidential Client of MSAL, see [Initialization of MSAL (Node.js)](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md). ```ts import { TokenCredential, AccessToken } from "@azure/core-auth"; @@ -627,7 +627,7 @@ async function main() { #### Authenticating with the @azure/msal-node On Behalf Of Flow -Currently, the `@azure/identity` library doesn't provide a credential type for clients which need to authenticate via the [On Behalf of Flow](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/main/lib/msal-common/docs/request.md#on-behalf-of-flow). While we may add support for this feature in the future, users currently requiring this will have to implement their own `TokenCredential` class. +Currently, the `@azure/identity` library doesn't provide a credential type for clients which need to authenticate via the [On Behalf of Flow](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-common/docs/request.md#on-behalf-of-flow). While we may add support for this feature in the future, users currently requiring this will have to implement their own `TokenCredential` class. In this example, the `OnBehalfOfCredential` accepts a client ID, client secret, and a user's access token. It then creates an instance of `ConfidentialClientApplication` from MSAL to obtain an OBO token that can authenticate client requests. @@ -636,8 +636,8 @@ In this example, the `OnBehalfOfCredential` accepts a client ID, client secret, Install the [@azure/msal-node][msal_node_npm] and [@azure/core-auth][core_auth]. > For more information about MSAL for Node.js, see [the README of the `@azure/msal-node` package][msal_node_readme]. -> For more information about working with the Confidential Client of MSAL, see [Initialization of MSAL (Node.js)](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/main/lib/msal-node/docs/initialize-confidential-client-application.md). -> For more information about working with the On Behalf Flow with MSAL, see [On Behalf of Flow](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/main/lib/msal-common/docs/request.md#on-behalf-of-flow). +> For more information about working with the Confidential Client of MSAL, see [Initialization of MSAL (Node.js)](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-node/docs/initialize-confidential-client-application.md). +> For more information about working with the On Behalf Flow with MSAL, see [On Behalf of Flow](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-common/docs/request.md#on-behalf-of-flow). ```ts import { TokenCredential, AccessToken } from "@azure/core-auth"; @@ -919,8 +919,8 @@ In this example, the custom credential type `RotatingCertificateCredential` agai [quickstart-register-app]: https://docs.microsoft.com/azure/active-directory/develop/quickstart-register-app [app-register-service-principal]: https://docs.microsoft.com/azure/active-directory/develop/app-objects-and-service-principals [service_principal_azure_powershell]: https://docs.microsoft.com/powershell/azure/create-azure-service-principal-azureps -[msal_node_readme]: https://github.com/sadasant/microsoft-authentication-library-for-js/tree/main/lib/msal-node +[msal_node_readme]: https://github.com/sadasant/microsoft-authentication-library-for-js/tree/master/lib/msal-node [msal_node_npm]: https://www.npmjs.com/package/@azure/msal-node -[msal_browser_readme]: https://github.com/sadasant/microsoft-authentication-library-for-js/tree/main/lib/msal-browser +[msal_browser_readme]: https://github.com/sadasant/microsoft-authentication-library-for-js/tree/master/lib/msal-browser [msal_browser_npm]: https://www.npmjs.com/package/@azure/msal-browser [core_auth]: https://www.npmjs.com/package/@azure/core-auth