From 597031d9b8fcb59bf49efbcdaedefde63f642450 Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Fri, 1 Oct 2021 13:42:02 +0000 Subject: [PATCH 1/7] [Identity] AuthenticationRequiredError options --- sdk/identity/identity/review/identity.api.md | 7 +++-- .../identity/src/client/identityClient.ts | 2 +- .../src/credentials/azureCliCredential.ts | 2 +- .../credentials/azurePowerShellCredential.ts | 2 +- .../src/credentials/chainedTokenCredential.ts | 2 +- .../src/credentials/environmentCredential.ts | 2 +- .../managedIdentityCredential/arcMsi.ts | 2 +- .../managedIdentityCredential/imdsMsi.ts | 2 +- .../managedIdentityCredential/index.ts | 2 +- .../credentials/visualStudioCodeCredential.ts | 2 +- .../identity/src/{client => }/errors.ts | 30 +++++++++++++++++++ sdk/identity/identity/src/index.ts | 22 +++++++------- .../src/msal/browserFlows/browserCommon.ts | 15 +++++----- .../src/msal/browserFlows/msalAuthCode.ts | 16 +++++++--- sdk/identity/identity/src/msal/errors.ts | 24 --------------- .../src/msal/nodeFlows/msalOpenBrowser.ts | 2 +- .../identity/src/msal/nodeFlows/nodeCommon.ts | 18 ++++++----- sdk/identity/identity/src/msal/utils.ts | 10 +++---- .../public/chainedTokenCredential.spec.ts | 8 ++--- 19 files changed, 93 insertions(+), 77 deletions(-) rename sdk/identity/identity/src/{client => }/errors.ts (86%) delete mode 100644 sdk/identity/identity/src/msal/errors.ts diff --git a/sdk/identity/identity/review/identity.api.md b/sdk/identity/identity/review/identity.api.md index 23dc2f505f72..ec33ba0b8288 100644 --- a/sdk/identity/identity/review/identity.api.md +++ b/sdk/identity/identity/review/identity.api.md @@ -54,8 +54,11 @@ export interface AuthenticationRecord { export class AuthenticationRequiredError extends Error { constructor( scopes: string[], - getTokenOptions?: GetTokenOptions, message?: string); - getTokenOptions: GetTokenOptions; + options: { + getTokenOptions?: GetTokenOptions; + message?: string; + }); + getTokenOptions?: GetTokenOptions; scopes: string[]; } diff --git a/sdk/identity/identity/src/client/identityClient.ts b/sdk/identity/identity/src/client/identityClient.ts index b71070ff5cc2..9d6428949445 100644 --- a/sdk/identity/identity/src/client/identityClient.ts +++ b/sdk/identity/identity/src/client/identityClient.ts @@ -12,7 +12,7 @@ import { PipelineRequest } from "@azure/core-rest-pipeline"; import { AbortController, AbortSignalLike } from "@azure/abort-controller"; -import { AuthenticationError, AuthenticationErrorName } from "./errors"; +import { AuthenticationError, AuthenticationErrorName } from "../errors"; import { getIdentityTokenEndpointSuffix } from "../util/identityTokenEndpoint"; import { DefaultAuthorityHost } from "../constants"; import { createSpan } from "../util/tracing"; diff --git a/sdk/identity/identity/src/credentials/azureCliCredential.ts b/sdk/identity/identity/src/credentials/azureCliCredential.ts index e0dd2f6a84f6..cf743d0d1332 100644 --- a/sdk/identity/identity/src/credentials/azureCliCredential.ts +++ b/sdk/identity/identity/src/credentials/azureCliCredential.ts @@ -4,7 +4,7 @@ import { TokenCredential, GetTokenOptions, AccessToken } from "@azure/core-auth"; import { createSpan } from "../util/tracing"; -import { CredentialUnavailableError } from "../client/errors"; +import { CredentialUnavailableError } from "../errors"; import { SpanStatusCode } from "@azure/core-tracing"; import { credentialLogger, formatSuccess, formatError } from "../util/logging"; import child_process from "child_process"; diff --git a/sdk/identity/identity/src/credentials/azurePowerShellCredential.ts b/sdk/identity/identity/src/credentials/azurePowerShellCredential.ts index 2e2a5000a184..47eecd8036a0 100644 --- a/sdk/identity/identity/src/credentials/azurePowerShellCredential.ts +++ b/sdk/identity/identity/src/credentials/azurePowerShellCredential.ts @@ -3,7 +3,7 @@ import { TokenCredential, GetTokenOptions, AccessToken } from "@azure/core-auth"; -import { CredentialUnavailableError } from "../client/errors"; +import { CredentialUnavailableError } from "../errors"; import { credentialLogger, formatSuccess, formatError } from "../util/logging"; import { trace } from "../util/tracing"; import { ensureValidScope, getScopeResource } from "../util/scopeUtils"; diff --git a/sdk/identity/identity/src/credentials/chainedTokenCredential.ts b/sdk/identity/identity/src/credentials/chainedTokenCredential.ts index 40cb82058e07..1276318648bd 100644 --- a/sdk/identity/identity/src/credentials/chainedTokenCredential.ts +++ b/sdk/identity/identity/src/credentials/chainedTokenCredential.ts @@ -3,7 +3,7 @@ import { AccessToken, TokenCredential, GetTokenOptions } from "@azure/core-auth"; -import { AggregateAuthenticationError, CredentialUnavailableError } from "../client/errors"; +import { AggregateAuthenticationError, CredentialUnavailableError } from "../errors"; import { createSpan } from "../util/tracing"; import { SpanStatusCode } from "@azure/core-tracing"; import { credentialLogger, formatSuccess, formatError } from "../util/logging"; diff --git a/sdk/identity/identity/src/credentials/environmentCredential.ts b/sdk/identity/identity/src/credentials/environmentCredential.ts index 5b1ca011585b..d5a1c378a64c 100644 --- a/sdk/identity/identity/src/credentials/environmentCredential.ts +++ b/sdk/identity/identity/src/credentials/environmentCredential.ts @@ -6,7 +6,7 @@ import { AccessToken, TokenCredential, GetTokenOptions } from "@azure/core-auth" import { credentialLogger, processEnvVars, formatSuccess, formatError } from "../util/logging"; import { TokenCredentialOptions } from "../client/identityClient"; import { ClientSecretCredential } from "./clientSecretCredential"; -import { AuthenticationError, CredentialUnavailableError } from "../client/errors"; +import { AuthenticationError, CredentialUnavailableError } from "../errors"; import { checkTenantId } from "../util/checkTenantId"; import { trace } from "../util/tracing"; import { ClientCertificateCredential } from "./clientCertificateCredential"; diff --git a/sdk/identity/identity/src/credentials/managedIdentityCredential/arcMsi.ts b/sdk/identity/identity/src/credentials/managedIdentityCredential/arcMsi.ts index 589107ab4cb5..8523e6938fe2 100644 --- a/sdk/identity/identity/src/credentials/managedIdentityCredential/arcMsi.ts +++ b/sdk/identity/identity/src/credentials/managedIdentityCredential/arcMsi.ts @@ -13,7 +13,7 @@ import { credentialLogger } from "../../util/logging"; import { IdentityClient } from "../../client/identityClient"; import { mapScopesToResource, msiGenericGetToken } from "./utils"; import { azureArcAPIVersion } from "./constants"; -import { AuthenticationError } from "../../client/errors"; +import { AuthenticationError } from "../../errors"; const msiName = "ManagedIdentityCredential - Azure Arc MSI"; const logger = credentialLogger(msiName); diff --git a/sdk/identity/identity/src/credentials/managedIdentityCredential/imdsMsi.ts b/sdk/identity/identity/src/credentials/managedIdentityCredential/imdsMsi.ts index cd94e98dfacb..e25fbf3c60d5 100644 --- a/sdk/identity/identity/src/credentials/managedIdentityCredential/imdsMsi.ts +++ b/sdk/identity/identity/src/credentials/managedIdentityCredential/imdsMsi.ts @@ -16,7 +16,7 @@ import { createSpan } from "../../util/tracing"; import { imdsApiVersion, imdsEndpointPath, imdsHost } from "./constants"; import { MSI, MSIConfiguration } from "./models"; import { mapScopesToResource, msiGenericGetToken } from "./utils"; -import { AuthenticationError } from "../../client/errors"; +import { AuthenticationError } from "../../errors"; const msiName = "ManagedIdentityCredential - IMDS"; const logger = credentialLogger(msiName); diff --git a/sdk/identity/identity/src/credentials/managedIdentityCredential/index.ts b/sdk/identity/identity/src/credentials/managedIdentityCredential/index.ts index e5623df773ce..503627090ba8 100644 --- a/sdk/identity/identity/src/credentials/managedIdentityCredential/index.ts +++ b/sdk/identity/identity/src/credentials/managedIdentityCredential/index.ts @@ -5,7 +5,7 @@ import { SpanStatusCode } from "@azure/core-tracing"; import { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core-auth"; import { IdentityClient, TokenCredentialOptions } from "../../client/identityClient"; -import { AuthenticationError, CredentialUnavailableError } from "../../client/errors"; +import { AuthenticationError, CredentialUnavailableError } from "../../errors"; import { credentialLogger, formatSuccess, formatError } from "../../util/logging"; import { appServiceMsi2017 } from "./appServiceMsi2017"; import { createSpan } from "../../util/tracing"; diff --git a/sdk/identity/identity/src/credentials/visualStudioCodeCredential.ts b/sdk/identity/identity/src/credentials/visualStudioCodeCredential.ts index 48f33dfaee76..970f01bb318f 100644 --- a/sdk/identity/identity/src/credentials/visualStudioCodeCredential.ts +++ b/sdk/identity/identity/src/credentials/visualStudioCodeCredential.ts @@ -7,7 +7,7 @@ import fs from "fs"; import os from "os"; import path from "path"; -import { CredentialUnavailableError } from "../client/errors"; +import { CredentialUnavailableError } from "../errors"; import { IdentityClient, TokenCredentialOptions } from "../client/identityClient"; import { AzureAuthorityHosts } from "../constants"; import { checkTenantId } from "../util/checkTenantId"; diff --git a/sdk/identity/identity/src/client/errors.ts b/sdk/identity/identity/src/errors.ts similarity index 86% rename from sdk/identity/identity/src/client/errors.ts rename to sdk/identity/identity/src/errors.ts index dfe225f5b2ef..ba768f51189f 100644 --- a/sdk/identity/identity/src/client/errors.ts +++ b/sdk/identity/identity/src/errors.ts @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +import { GetTokenOptions } from "@azure/core-auth"; + /** * See the official documentation for more details: * @@ -182,3 +184,31 @@ function convertOAuthErrorResponseToErrorResponse(errorBody: OAuthErrorResponse) traceId: errorBody.trace_id }; } + +/** + * Error used to enforce authentication after trying to retrieve a token silently. + */ +export class AuthenticationRequiredError extends Error { + /** + * The options used to configure the getToken request. + */ + public getTokenOptions?: GetTokenOptions; + + constructor( + /** + * The list of scopes for which the token will have access. + */ + public scopes: string[], + /** + * Optional parameters. A message can be specified. The {@link GetTokenOptions} of the request can also be specified to more easily associate the error with the received parameters. + */ + options: { + getTokenOptions?: GetTokenOptions; + message?: string; + } + ) { + super(options?.message); + this.getTokenOptions = options?.getTokenOptions; + this.name = "AuthenticationRequiredError"; + } +} diff --git a/sdk/identity/identity/src/index.ts b/sdk/identity/identity/src/index.ts index 74fe2bd333fa..5fd735cbb658 100644 --- a/sdk/identity/identity/src/index.ts +++ b/sdk/identity/identity/src/index.ts @@ -8,8 +8,18 @@ export { IdentityPlugin } from "./plugins/provider"; import { TokenCredential } from "@azure/core-auth"; import { DefaultAzureCredential } from "./credentials/defaultAzureCredential"; +export { + AuthenticationError, + ErrorResponse, + AggregateAuthenticationError, + AuthenticationErrorName, + AggregateAuthenticationErrorName, + CredentialUnavailableError, + CredentialUnavailableErrorName, + AuthenticationRequiredError +} from "./errors"; + export { AuthenticationRecord } from "./msal/types"; -export { AuthenticationRequiredError } from "./msal/errors"; export { serializeAuthenticationRecord, deserializeAuthenticationRecord } from "./msal/utils"; export { TokenCredentialOptions } from "./client/identityClient"; @@ -71,16 +81,6 @@ export { export { TokenCachePersistenceOptions } from "./msal/nodeFlows/tokenCachePersistenceOptions"; -export { - AuthenticationError, - ErrorResponse, - AggregateAuthenticationError, - AuthenticationErrorName, - AggregateAuthenticationErrorName, - CredentialUnavailableError, - CredentialUnavailableErrorName -} from "./client/errors"; - export { TokenCredential, GetTokenOptions, AccessToken } from "@azure/core-auth"; export { logger } from "./util/logging"; diff --git a/sdk/identity/identity/src/msal/browserFlows/browserCommon.ts b/sdk/identity/identity/src/msal/browserFlows/browserCommon.ts index 3a362dc266af..4398d4aae5a6 100644 --- a/sdk/identity/identity/src/msal/browserFlows/browserCommon.ts +++ b/sdk/identity/identity/src/msal/browserFlows/browserCommon.ts @@ -7,14 +7,13 @@ import { AccessToken } from "@azure/core-auth"; import { DefaultTenantId } from "../../constants"; import { resolveTenantId } from "../../util/resolveTenantId"; +import { processMultiTenantRequest } from "../../util/validateMultiTenant"; import { BrowserLoginStyle } from "../../credentials/interactiveBrowserCredentialOptions"; +import { AuthenticationRequiredError, CredentialUnavailableError } from "../../errors"; import { getAuthority, getKnownAuthorities, MsalBaseUtilities } from "../utils"; import { MsalFlow, MsalFlowOptions } from "../flows"; import { AuthenticationRecord } from "../types"; import { CredentialFlowGetTokenOptions } from "../credentials"; -import { AuthenticationRequiredError } from "../errors"; -import { CredentialUnavailableError } from "../../client/errors"; -import { processMultiTenantRequest } from "../../util/validateMultiTenant"; /** * Union of the constructor parameters that all MSAL flow types take. @@ -160,11 +159,11 @@ export abstract class MsalBrowser extends MsalBaseUtilities implements MsalBrows throw err; } if (options?.disableAutomaticAuthentication) { - throw new AuthenticationRequiredError( - scopes, - options, - "Automatic authentication has been disabled. You may call the authentication() method." - ); + throw new AuthenticationRequiredError(scopes, { + getTokenOptions: options, + message: + "Automatic authentication has been disabled. You may call the authentication() method." + }); } this.logger.info( `Silent authentication failed, falling back to interactive method ${this.loginStyle}` diff --git a/sdk/identity/identity/src/msal/browserFlows/msalAuthCode.ts b/sdk/identity/identity/src/msal/browserFlows/msalAuthCode.ts index a81004fba11e..32a17bf05ece 100644 --- a/sdk/identity/identity/src/msal/browserFlows/msalAuthCode.ts +++ b/sdk/identity/identity/src/msal/browserFlows/msalAuthCode.ts @@ -5,11 +5,11 @@ import * as msalBrowser from "@azure/msal-browser"; import { AccessToken } from "@azure/core-auth"; -import { MsalBrowserFlowOptions, MsalBrowser } from "./browserCommon"; +import { AuthenticationRequiredError } from "../../errors"; import { defaultLoggerCallback, msalToPublic, publicToMsal } from "../utils"; import { AuthenticationRecord } from "../types"; -import { AuthenticationRequiredError } from "../errors"; import { CredentialFlowGetTokenOptions } from "../credentials"; +import { MsalBrowserFlowOptions, MsalBrowser } from "./browserCommon"; // We keep a copy of the redirect hash. const redirectHash = self.location.hash; @@ -158,7 +158,11 @@ To work with multiple accounts for the same Client ID and Tenant ID, please prov ): Promise { const account = await this.getActiveAccount(); if (!account) { - throw new AuthenticationRequiredError(scopes, options); + throw new AuthenticationRequiredError(scopes, { + getTokenOptions: options, + message: + "Silent authentication failed. We couldn't retrieve an active account from the cache." + }); } const parameters: msalBrowser.SilentRequest = { @@ -187,7 +191,11 @@ To work with multiple accounts for the same Client ID and Tenant ID, please prov ): Promise { const account = await this.getActiveAccount(); if (!account) { - throw new AuthenticationRequiredError(scopes, options); + throw new AuthenticationRequiredError(scopes, { + getTokenOptions: options, + message: + "Silent authentication failed. We couldn't retrieve an active account from the cache." + }); } const parameters: msalBrowser.RedirectRequest = { diff --git a/sdk/identity/identity/src/msal/errors.ts b/sdk/identity/identity/src/msal/errors.ts deleted file mode 100644 index 71ee673d5fb1..000000000000 --- a/sdk/identity/identity/src/msal/errors.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -import { GetTokenOptions } from "@azure/core-auth"; - -/** - * Error used to enforce authentication after trying to retrieve a token silently. - */ -export class AuthenticationRequiredError extends Error { - constructor( - /** - * The list of scopes for which the token will have access. - */ - public scopes: string[], - /** - * The options used to configure the getToken request. - */ - public getTokenOptions: GetTokenOptions = {}, - message?: string - ) { - super(message); - this.name = "AuthenticationRequiredError"; - } -} diff --git a/sdk/identity/identity/src/msal/nodeFlows/msalOpenBrowser.ts b/sdk/identity/identity/src/msal/nodeFlows/msalOpenBrowser.ts index ed1eb4c602aa..4009d447807d 100644 --- a/sdk/identity/identity/src/msal/nodeFlows/msalOpenBrowser.ts +++ b/sdk/identity/identity/src/msal/nodeFlows/msalOpenBrowser.ts @@ -11,9 +11,9 @@ import open from "open"; import stoppable from "stoppable"; import { credentialLogger, formatError, formatSuccess } from "../../util/logging"; +import { CredentialUnavailableError } from "../../errors"; import { MsalNodeOptions, MsalNode } from "./nodeCommon"; import { msalToPublic } from "../utils"; -import { CredentialUnavailableError } from "../../client/errors"; import { CredentialFlowGetTokenOptions } from "../credentials"; /** diff --git a/sdk/identity/identity/src/msal/nodeFlows/nodeCommon.ts b/sdk/identity/identity/src/msal/nodeFlows/nodeCommon.ts index 340063d483c1..b3ea5643e07a 100644 --- a/sdk/identity/identity/src/msal/nodeFlows/nodeCommon.ts +++ b/sdk/identity/identity/src/msal/nodeFlows/nodeCommon.ts @@ -10,9 +10,9 @@ import { AbortSignalLike } from "@azure/abort-controller"; import { DeveloperSignOnClientId } from "../../constants"; import { IdentityClient, TokenCredentialOptions } from "../../client/identityClient"; import { resolveTenantId } from "../../util/resolveTenantId"; +import { AuthenticationRequiredError } from "../../errors"; import { CredentialFlowGetTokenOptions } from "../credentials"; import { MsalFlow, MsalFlowOptions } from "../flows"; -import { AuthenticationRequiredError } from "../errors"; import { AuthenticationRecord } from "../types"; import { defaultLoggerCallback, @@ -242,7 +242,11 @@ To work with multiple accounts for the same Client ID and Tenant ID, please prov ): Promise { await this.getActiveAccount(); if (!this.account) { - throw new AuthenticationRequiredError(scopes, options); + throw new AuthenticationRequiredError(scopes, { + getTokenOptions: options, + message: + "Silent authentication failed. We couldn't retrieve an active account from the cache." + }); } const silentRequest: msalNode.SilentFlowRequest = { @@ -291,11 +295,11 @@ To work with multiple accounts for the same Client ID and Tenant ID, please prov throw err; } if (options?.disableAutomaticAuthentication) { - throw new AuthenticationRequiredError( - scopes, - options, - "Automatic authentication has been disabled. You may call the authentication() method." - ); + throw new AuthenticationRequiredError(scopes, { + getTokenOptions: options, + message: + "Automatic authentication has been disabled. You may call the authentication() method." + }); } this.logger.info(`Silent authentication failed, falling back to interactive method.`); return this.doGetToken(scopes, options); diff --git a/sdk/identity/identity/src/msal/utils.ts b/sdk/identity/identity/src/msal/utils.ts index eafb02ab3597..25026a4d199f 100644 --- a/sdk/identity/identity/src/msal/utils.ts +++ b/sdk/identity/identity/src/msal/utils.ts @@ -8,10 +8,9 @@ import { AbortError } from "@azure/abort-controller"; import { v4 as uuidv4 } from "uuid"; import { CredentialLogger, formatError, formatSuccess } from "../util/logging"; -import { CredentialUnavailableError } from "../client/errors"; +import { CredentialUnavailableError, AuthenticationRequiredError } from "../errors"; import { DefaultAuthorityHost, DefaultTenantId } from "../constants"; import { AuthenticationRecord, MsalAccountInfo, MsalResult, MsalToken } from "./types"; -import { AuthenticationRequiredError } from "./errors"; import { MsalFlowOptions } from "./flows"; /** @@ -32,11 +31,10 @@ export function ensureValidMsalToken( ): void { const error = (message: string): Error => { logger.getToken.info(message); - return new AuthenticationRequiredError( - Array.isArray(scopes) ? scopes : [scopes], + return new AuthenticationRequiredError(Array.isArray(scopes) ? scopes : [scopes], { getTokenOptions, message - ); + }); }; if (!msalToken) { throw error("No response"); @@ -190,7 +188,7 @@ export class MsalBaseUtilities { ) { return error; } - return new AuthenticationRequiredError(scopes, getTokenOptions, error.message); + return new AuthenticationRequiredError(scopes, { getTokenOptions, message: error.message }); } } diff --git a/sdk/identity/identity/test/public/chainedTokenCredential.spec.ts b/sdk/identity/identity/test/public/chainedTokenCredential.spec.ts index f4c90a9dc390..4750c7d0f951 100644 --- a/sdk/identity/identity/test/public/chainedTokenCredential.spec.ts +++ b/sdk/identity/identity/test/public/chainedTokenCredential.spec.ts @@ -24,11 +24,9 @@ describe("ChainedTokenCredential", function() { mockCredential(Promise.reject(new CredentialUnavailableError("unavailable."))), mockCredential( Promise.reject( - new AuthenticationRequiredError( - ["https://vault.azure.net/.default"], - {}, - "authentication-required." - ) + new AuthenticationRequiredError(["https://vault.azure.net/.default"], { + message: "authentication-required." + }) ) ), mockCredential(Promise.resolve({ token: "firstToken", expiresOnTimestamp: 0 })), From 0d740db93b60b8f95526285fb4d8dd8206b25b81 Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Fri, 1 Oct 2021 13:46:16 +0000 Subject: [PATCH 2/7] changelog entry --- sdk/identity/identity/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/identity/identity/CHANGELOG.md b/sdk/identity/identity/CHANGELOG.md index dbce12deb454..3bc122a57ac1 100644 --- a/sdk/identity/identity/CHANGELOG.md +++ b/sdk/identity/identity/CHANGELOG.md @@ -110,6 +110,7 @@ Azure Service Fabric support hasn't been added on the initial version 2 of Ident - Renamed the `ApplicationCredential` to `AzureApplicationCredential`. - Removed the `CredentialPersistenceOptions` from `DefaultAzureCredential` and `EnvironmentCredential`. - Merged the configuration and the options bag on the `OnBehalfOfCredential` into a single options bag. +- `AuthenticationRequiredError` (introduced in 2.0.0-beta.1) now has its parameters into a single options bag. ### Bugs Fixed From ef1a95a35205cc298bf31b79b18d20d873b0746c Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Fri, 1 Oct 2021 17:03:02 +0000 Subject: [PATCH 3/7] AuthenticationRequiredErrorOptions --- sdk/identity/identity/CHANGELOG.md | 1 + sdk/identity/identity/review/identity.api.md | 13 +++++++++---- sdk/identity/identity/src/errors.ts | 13 +++++++++---- sdk/identity/identity/src/index.ts | 3 ++- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/sdk/identity/identity/CHANGELOG.md b/sdk/identity/identity/CHANGELOG.md index 3bc122a57ac1..70a53dad3b38 100644 --- a/sdk/identity/identity/CHANGELOG.md +++ b/sdk/identity/identity/CHANGELOG.md @@ -111,6 +111,7 @@ Azure Service Fabric support hasn't been added on the initial version 2 of Ident - Removed the `CredentialPersistenceOptions` from `DefaultAzureCredential` and `EnvironmentCredential`. - Merged the configuration and the options bag on the `OnBehalfOfCredential` into a single options bag. - `AuthenticationRequiredError` (introduced in 2.0.0-beta.1) now has its parameters into a single options bag. +- `AuthenticationRequiredError` (introduced in 2.0.0-beta.1) now has its parameters in a single options bag, `AuthenticationRequiredErrorOptions`. ### Bugs Fixed diff --git a/sdk/identity/identity/review/identity.api.md b/sdk/identity/identity/review/identity.api.md index ec33ba0b8288..0808cbbd937f 100644 --- a/sdk/identity/identity/review/identity.api.md +++ b/sdk/identity/identity/review/identity.api.md @@ -54,14 +54,19 @@ export interface AuthenticationRecord { export class AuthenticationRequiredError extends Error { constructor( scopes: string[], - options: { - getTokenOptions?: GetTokenOptions; - message?: string; - }); + options?: AuthenticationRequiredErrorOptions); getTokenOptions?: GetTokenOptions; scopes: string[]; } +// @public +export interface AuthenticationRequiredErrorOptions { + // (undocumented) + getTokenOptions?: GetTokenOptions; + // (undocumented) + message?: string; +} + // @public export class AuthorizationCodeCredential implements TokenCredential { constructor(tenantId: string | "common", clientId: string, clientSecret: string, authorizationCode: string, redirectUri: string, options?: TokenCredentialOptions); diff --git a/sdk/identity/identity/src/errors.ts b/sdk/identity/identity/src/errors.ts index ba768f51189f..715466e8e9b5 100644 --- a/sdk/identity/identity/src/errors.ts +++ b/sdk/identity/identity/src/errors.ts @@ -185,6 +185,14 @@ function convertOAuthErrorResponseToErrorResponse(errorBody: OAuthErrorResponse) }; } +/** + * Optional parameters to the {@link AuthenticationRequiredError} + */ +export interface AuthenticationRequiredErrorOptions { + getTokenOptions?: GetTokenOptions; + message?: string; +} + /** * Error used to enforce authentication after trying to retrieve a token silently. */ @@ -202,10 +210,7 @@ export class AuthenticationRequiredError extends Error { /** * Optional parameters. A message can be specified. The {@link GetTokenOptions} of the request can also be specified to more easily associate the error with the received parameters. */ - options: { - getTokenOptions?: GetTokenOptions; - message?: string; - } + options?: AuthenticationRequiredErrorOptions ) { super(options?.message); this.getTokenOptions = options?.getTokenOptions; diff --git a/sdk/identity/identity/src/index.ts b/sdk/identity/identity/src/index.ts index 5fd735cbb658..80efc99901b1 100644 --- a/sdk/identity/identity/src/index.ts +++ b/sdk/identity/identity/src/index.ts @@ -16,7 +16,8 @@ export { AggregateAuthenticationErrorName, CredentialUnavailableError, CredentialUnavailableErrorName, - AuthenticationRequiredError + AuthenticationRequiredError, + AuthenticationRequiredErrorOptions } from "./errors"; export { AuthenticationRecord } from "./msal/types"; From efd02e3d339bc5e8fd3e6d900568e2e4d29d0f5b Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Fri, 1 Oct 2021 17:04:28 +0000 Subject: [PATCH 4/7] small improvement --- sdk/identity/identity/src/errors.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/identity/identity/src/errors.ts b/sdk/identity/identity/src/errors.ts index 715466e8e9b5..6b0d2cbe4119 100644 --- a/sdk/identity/identity/src/errors.ts +++ b/sdk/identity/identity/src/errors.ts @@ -210,10 +210,10 @@ export class AuthenticationRequiredError extends Error { /** * Optional parameters. A message can be specified. The {@link GetTokenOptions} of the request can also be specified to more easily associate the error with the received parameters. */ - options?: AuthenticationRequiredErrorOptions + options: AuthenticationRequiredErrorOptions = {} ) { - super(options?.message); - this.getTokenOptions = options?.getTokenOptions; + super(options.message); + this.getTokenOptions = options.getTokenOptions; this.name = "AuthenticationRequiredError"; } } From be0e66c8668ecaa97a94e037263c75de4b8a38c4 Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Wed, 6 Oct 2021 23:49:29 +0000 Subject: [PATCH 5/7] comments on the public API --- sdk/identity/identity/review/identity.api.md | 2 -- sdk/identity/identity/src/errors.ts | 8 +++++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/sdk/identity/identity/review/identity.api.md b/sdk/identity/identity/review/identity.api.md index 0808cbbd937f..bf4ff8603dbe 100644 --- a/sdk/identity/identity/review/identity.api.md +++ b/sdk/identity/identity/review/identity.api.md @@ -61,9 +61,7 @@ export class AuthenticationRequiredError extends Error { // @public export interface AuthenticationRequiredErrorOptions { - // (undocumented) getTokenOptions?: GetTokenOptions; - // (undocumented) message?: string; } diff --git a/sdk/identity/identity/src/errors.ts b/sdk/identity/identity/src/errors.ts index 6b0d2cbe4119..d716352d6b32 100644 --- a/sdk/identity/identity/src/errors.ts +++ b/sdk/identity/identity/src/errors.ts @@ -189,7 +189,13 @@ function convertOAuthErrorResponseToErrorResponse(errorBody: OAuthErrorResponse) * Optional parameters to the {@link AuthenticationRequiredError} */ export interface AuthenticationRequiredErrorOptions { + /** + * The options passed to the getToken request. + */ getTokenOptions?: GetTokenOptions; + /** + * The message of the error. + */ message?: string; } @@ -198,7 +204,7 @@ export interface AuthenticationRequiredErrorOptions { */ export class AuthenticationRequiredError extends Error { /** - * The options used to configure the getToken request. + * The options passed to the getToken request. */ public getTokenOptions?: GetTokenOptions; From 3d6c5eda216a3ddde822166e3d58ce1cfc4e43ac Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Sat, 9 Oct 2021 01:53:33 +0000 Subject: [PATCH 6/7] merged AuthenticationRequiredErrror parameters --- sdk/identity/identity/review/identity.api.md | 4 ++-- sdk/identity/identity/src/errors.ts | 15 ++++++++++----- .../src/msal/browserFlows/browserCommon.ts | 3 ++- .../src/msal/browserFlows/msalAuthCode.ts | 6 ++++-- .../identity/src/msal/nodeFlows/nodeCommon.ts | 6 ++++-- sdk/identity/identity/src/msal/utils.ts | 5 +++-- .../test/public/chainedTokenCredential.spec.ts | 5 +++-- 7 files changed, 28 insertions(+), 16 deletions(-) diff --git a/sdk/identity/identity/review/identity.api.md b/sdk/identity/identity/review/identity.api.md index bf4ff8603dbe..a76f97b57b15 100644 --- a/sdk/identity/identity/review/identity.api.md +++ b/sdk/identity/identity/review/identity.api.md @@ -53,8 +53,7 @@ export interface AuthenticationRecord { // @public export class AuthenticationRequiredError extends Error { constructor( - scopes: string[], - options?: AuthenticationRequiredErrorOptions); + options: AuthenticationRequiredErrorOptions); getTokenOptions?: GetTokenOptions; scopes: string[]; } @@ -63,6 +62,7 @@ export class AuthenticationRequiredError extends Error { export interface AuthenticationRequiredErrorOptions { getTokenOptions?: GetTokenOptions; message?: string; + scopes: string[]; } // @public diff --git a/sdk/identity/identity/src/errors.ts b/sdk/identity/identity/src/errors.ts index d716352d6b32..6e238ce397b8 100644 --- a/sdk/identity/identity/src/errors.ts +++ b/sdk/identity/identity/src/errors.ts @@ -189,6 +189,10 @@ function convertOAuthErrorResponseToErrorResponse(errorBody: OAuthErrorResponse) * Optional parameters to the {@link AuthenticationRequiredError} */ export interface AuthenticationRequiredErrorOptions { + /** + * The list of scopes for which the token will have access. + */ + scopes: string[], /** * The options passed to the getToken request. */ @@ -203,22 +207,23 @@ export interface AuthenticationRequiredErrorOptions { * Error used to enforce authentication after trying to retrieve a token silently. */ export class AuthenticationRequiredError extends Error { + /** + * The list of scopes for which the token will have access. + */ + public scopes: string[]; /** * The options passed to the getToken request. */ public getTokenOptions?: GetTokenOptions; constructor( - /** - * The list of scopes for which the token will have access. - */ - public scopes: string[], /** * Optional parameters. A message can be specified. The {@link GetTokenOptions} of the request can also be specified to more easily associate the error with the received parameters. */ - options: AuthenticationRequiredErrorOptions = {} + options: AuthenticationRequiredErrorOptions ) { super(options.message); + this.scopes = options.scopes; this.getTokenOptions = options.getTokenOptions; this.name = "AuthenticationRequiredError"; } diff --git a/sdk/identity/identity/src/msal/browserFlows/browserCommon.ts b/sdk/identity/identity/src/msal/browserFlows/browserCommon.ts index 4398d4aae5a6..e5c9fa89eedc 100644 --- a/sdk/identity/identity/src/msal/browserFlows/browserCommon.ts +++ b/sdk/identity/identity/src/msal/browserFlows/browserCommon.ts @@ -159,7 +159,8 @@ export abstract class MsalBrowser extends MsalBaseUtilities implements MsalBrows throw err; } if (options?.disableAutomaticAuthentication) { - throw new AuthenticationRequiredError(scopes, { + throw new AuthenticationRequiredError({ + scopes, getTokenOptions: options, message: "Automatic authentication has been disabled. You may call the authentication() method." diff --git a/sdk/identity/identity/src/msal/browserFlows/msalAuthCode.ts b/sdk/identity/identity/src/msal/browserFlows/msalAuthCode.ts index 32a17bf05ece..0bc7bbb2e32d 100644 --- a/sdk/identity/identity/src/msal/browserFlows/msalAuthCode.ts +++ b/sdk/identity/identity/src/msal/browserFlows/msalAuthCode.ts @@ -158,7 +158,8 @@ To work with multiple accounts for the same Client ID and Tenant ID, please prov ): Promise { const account = await this.getActiveAccount(); if (!account) { - throw new AuthenticationRequiredError(scopes, { + throw new AuthenticationRequiredError({ + scopes, getTokenOptions: options, message: "Silent authentication failed. We couldn't retrieve an active account from the cache." @@ -191,7 +192,8 @@ To work with multiple accounts for the same Client ID and Tenant ID, please prov ): Promise { const account = await this.getActiveAccount(); if (!account) { - throw new AuthenticationRequiredError(scopes, { + throw new AuthenticationRequiredError({ + scopes, getTokenOptions: options, message: "Silent authentication failed. We couldn't retrieve an active account from the cache." diff --git a/sdk/identity/identity/src/msal/nodeFlows/nodeCommon.ts b/sdk/identity/identity/src/msal/nodeFlows/nodeCommon.ts index b3ea5643e07a..9b5a1b31c4fb 100644 --- a/sdk/identity/identity/src/msal/nodeFlows/nodeCommon.ts +++ b/sdk/identity/identity/src/msal/nodeFlows/nodeCommon.ts @@ -242,7 +242,8 @@ To work with multiple accounts for the same Client ID and Tenant ID, please prov ): Promise { await this.getActiveAccount(); if (!this.account) { - throw new AuthenticationRequiredError(scopes, { + throw new AuthenticationRequiredError({ + scopes, getTokenOptions: options, message: "Silent authentication failed. We couldn't retrieve an active account from the cache." @@ -295,7 +296,8 @@ To work with multiple accounts for the same Client ID and Tenant ID, please prov throw err; } if (options?.disableAutomaticAuthentication) { - throw new AuthenticationRequiredError(scopes, { + throw new AuthenticationRequiredError({ + scopes, getTokenOptions: options, message: "Automatic authentication has been disabled. You may call the authentication() method." diff --git a/sdk/identity/identity/src/msal/utils.ts b/sdk/identity/identity/src/msal/utils.ts index 25026a4d199f..61b8f982651d 100644 --- a/sdk/identity/identity/src/msal/utils.ts +++ b/sdk/identity/identity/src/msal/utils.ts @@ -31,7 +31,8 @@ export function ensureValidMsalToken( ): void { const error = (message: string): Error => { logger.getToken.info(message); - return new AuthenticationRequiredError(Array.isArray(scopes) ? scopes : [scopes], { + return new AuthenticationRequiredError({ + scopes: Array.isArray(scopes) ? scopes : [scopes], getTokenOptions, message }); @@ -188,7 +189,7 @@ export class MsalBaseUtilities { ) { return error; } - return new AuthenticationRequiredError(scopes, { getTokenOptions, message: error.message }); + return new AuthenticationRequiredError({ scopes, getTokenOptions, message: error.message }); } } diff --git a/sdk/identity/identity/test/public/chainedTokenCredential.spec.ts b/sdk/identity/identity/test/public/chainedTokenCredential.spec.ts index 4750c7d0f951..3583f5270e72 100644 --- a/sdk/identity/identity/test/public/chainedTokenCredential.spec.ts +++ b/sdk/identity/identity/test/public/chainedTokenCredential.spec.ts @@ -18,13 +18,14 @@ function mockCredential(returnPromise: Promise): TokenCreden }; } -describe("ChainedTokenCredential", function() { +describe("ChainedTokenCredential", function () { it("returns the first token received from a credential", async () => { const chainedTokenCredential = new ChainedTokenCredential( mockCredential(Promise.reject(new CredentialUnavailableError("unavailable."))), mockCredential( Promise.reject( - new AuthenticationRequiredError(["https://vault.azure.net/.default"], { + new AuthenticationRequiredError({ + scopes: ["https://vault.azure.net/.default"], message: "authentication-required." }) ) From 0c63b741703b5ae903e711e6f6b48d2b94f9999d Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Mon, 11 Oct 2021 17:43:14 +0000 Subject: [PATCH 7/7] formatting --- sdk/identity/identity/src/errors.ts | 2 +- .../identity/test/public/chainedTokenCredential.spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/identity/identity/src/errors.ts b/sdk/identity/identity/src/errors.ts index 6e238ce397b8..48931ebeece1 100644 --- a/sdk/identity/identity/src/errors.ts +++ b/sdk/identity/identity/src/errors.ts @@ -192,7 +192,7 @@ export interface AuthenticationRequiredErrorOptions { /** * The list of scopes for which the token will have access. */ - scopes: string[], + scopes: string[]; /** * The options passed to the getToken request. */ diff --git a/sdk/identity/identity/test/public/chainedTokenCredential.spec.ts b/sdk/identity/identity/test/public/chainedTokenCredential.spec.ts index 3583f5270e72..cc17697b5c5c 100644 --- a/sdk/identity/identity/test/public/chainedTokenCredential.spec.ts +++ b/sdk/identity/identity/test/public/chainedTokenCredential.spec.ts @@ -18,7 +18,7 @@ function mockCredential(returnPromise: Promise): TokenCreden }; } -describe("ChainedTokenCredential", function () { +describe("ChainedTokenCredential", function() { it("returns the first token received from a credential", async () => { const chainedTokenCredential = new ChainedTokenCredential( mockCredential(Promise.reject(new CredentialUnavailableError("unavailable."))),