diff --git a/sdk/identity/identity/CHANGELOG.md b/sdk/identity/identity/CHANGELOG.md index 5b19ea9cc580..dbce12deb454 100644 --- a/sdk/identity/identity/CHANGELOG.md +++ b/sdk/identity/identity/CHANGELOG.md @@ -105,6 +105,12 @@ Azure Service Fabric support hasn't been added on the initial version 2 of Ident - Removed the `allowMultiTenantAuthentication` option from all of the credentials. Multi-tenant authentication is now enabled by default. On Node.js, it can be disabled with the `AZURE_IDENTITY_DISABLE_MULTITENANTAUTH` environment variable. - Removed support for specific Azure regions on `ClientSecretCredential` and `ClientCertificateCredential. This feature will be added back on the next beta. +#### Breaking Changes from 2.0.0-beta.6 + +- 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. + ### Bugs Fixed - `ClientSecretCredential`, `ClientCertificateCredential`, and `UsernamePasswordCredential` throw if the required parameters aren't provided (even in JavaScript). diff --git a/sdk/identity/identity/package.json b/sdk/identity/identity/package.json index c09e1d19eacf..b5482935cb8d 100644 --- a/sdk/identity/identity/package.json +++ b/sdk/identity/identity/package.json @@ -21,7 +21,7 @@ "./dist-esm/src/credentials/visualStudioCodeCredential.js": "./dist-esm/src/credentials/visualStudioCodeCredential.browser.js", "./dist-esm/src/credentials/usernamePasswordCredential.js": "./dist-esm/src/credentials/usernamePasswordCredential.browser.js", "./dist-esm/src/credentials/azurePowerShellCredential.js": "./dist-esm/src/credentials/azurePowerShellCredential.browser.js", - "./dist-esm/src/credentials/applicationCredential.js": "./dist-esm/src/credentials/applicationCredential.browser.js", + "./dist-esm/src/credentials/azureApplicationCredential.js": "./dist-esm/src/credentials/azureApplicationCredential.browser.js", "./dist-esm/src/credentials/onBehalfOfCredential.js": "./dist-esm/src/credentials/onBehalfOfCredential.browser.js", "./dist-esm/src/util/authHostEnv.js": "./dist-esm/src/util/authHostEnv.browser.js", "./dist-esm/src/util/validateMultiTenant.js": "./dist-esm/src/util/validateMultiTenant.browser.js", diff --git a/sdk/identity/identity/review/identity.api.md b/sdk/identity/identity/review/identity.api.md index abbf46dd158b..23dc2f505f72 100644 --- a/sdk/identity/identity/review/identity.api.md +++ b/sdk/identity/identity/review/identity.api.md @@ -64,7 +64,7 @@ export class AuthorizationCodeCredential implements TokenCredential { constructor(tenantId: string | "common", clientId: string, clientSecret: string, authorizationCode: string, redirectUri: string, options?: TokenCredentialOptions); constructor(tenantId: string | "common", clientId: string, authorizationCode: string, redirectUri: string, options?: TokenCredentialOptions); getToken(scopes: string | string[], options?: GetTokenOptions): Promise; - } +} // @public export enum AzureAuthorityHosts { @@ -78,7 +78,7 @@ export enum AzureAuthorityHosts { export class AzureCliCredential implements TokenCredential { constructor(options?: AzureCliCredentialOptions); getToken(scopes: string | string[], options?: GetTokenOptions): Promise; - } +} // @public export interface AzureCliCredentialOptions extends TokenCredentialOptions { @@ -89,7 +89,7 @@ export interface AzureCliCredentialOptions extends TokenCredentialOptions { export class AzurePowerShellCredential implements TokenCredential { constructor(options?: AzurePowerShellCredentialOptions); getToken(scopes: string | string[], options?: GetTokenOptions): Promise; - } +} // @public export interface AzurePowerShellCredentialOptions extends TokenCredentialOptions { @@ -110,7 +110,7 @@ export class ChainedTokenCredential implements TokenCredential { export class ClientCertificateCredential implements TokenCredential { constructor(tenantId: string, clientId: string, certificatePath: string, options?: ClientCertificateCredentialOptions); getToken(scopes: string | string[], options?: GetTokenOptions): Promise; - } +} // @public export interface ClientCertificateCredentialOptions extends TokenCredentialOptions, CredentialPersistenceOptions { @@ -121,7 +121,7 @@ export interface ClientCertificateCredentialOptions extends TokenCredentialOptio export class ClientSecretCredential implements TokenCredential { constructor(tenantId: string, clientId: string, clientSecret: string, options?: ClientSecretCredentialOptions); getToken(scopes: string | string[], options?: GetTokenOptions): Promise; - } +} // @public export interface ClientSecretCredentialOptions extends TokenCredentialOptions, CredentialPersistenceOptions { @@ -146,7 +146,7 @@ export class DefaultAzureCredential extends ChainedTokenCredential { } // @public -export interface DefaultAzureCredentialOptions extends TokenCredentialOptions, CredentialPersistenceOptions { +export interface DefaultAzureCredentialOptions extends TokenCredentialOptions { managedIdentityClientId?: string; tenantId?: string; } @@ -159,7 +159,7 @@ export class DeviceCodeCredential implements TokenCredential { constructor(options?: DeviceCodeCredentialOptions); authenticate(scopes: string | string[], options?: GetTokenOptions): Promise; getToken(scopes: string | string[], options?: GetTokenOptions): Promise; - } +} // @public export interface DeviceCodeCredentialOptions extends InteractiveCredentialOptions, CredentialPersistenceOptions { @@ -185,7 +185,7 @@ export class EnvironmentCredential implements TokenCredential { } // @public -export interface EnvironmentCredentialOptions extends TokenCredentialOptions, CredentialPersistenceOptions { +export interface EnvironmentCredentialOptions extends TokenCredentialOptions { } // @public @@ -211,7 +211,7 @@ export class InteractiveBrowserCredential implements TokenCredential { constructor(options?: InteractiveBrowserCredentialOptions | InteractiveBrowserCredentialBrowserOptions); authenticate(scopes: string | string[], options?: GetTokenOptions): Promise; getToken(scopes: string | string[], options?: GetTokenOptions): Promise; - } +} // @public export interface InteractiveBrowserCredentialBrowserOptions extends InteractiveCredentialOptions { @@ -244,31 +244,33 @@ export class ManagedIdentityCredential implements TokenCredential { constructor(clientId: string, options?: TokenCredentialOptions); constructor(options?: TokenCredentialOptions); getToken(scopes: string | string[], options?: GetTokenOptions): Promise; - } +} // @public export class OnBehalfOfCredential implements TokenCredential { - constructor(configuration: OnBehalfOfCredentialSecretConfiguration | OnBehalfOfCredentialCertificateConfiguration, options?: OnBehalfOfCredentialOptions); + constructor(options: OnBehalfOfCredentialOptions); getToken(scopes: string | string[], options?: GetTokenOptions): Promise; - } +} // @public -export interface OnBehalfOfCredentialCertificateConfiguration { +export interface OnBehalfOfCredentialCertificateOptions { certificatePath: string; clientId: string; + clientSecret?: never; sendCertificateChain?: boolean; tenantId: string; userAssertionToken: string; } // @public -export interface OnBehalfOfCredentialOptions extends TokenCredentialOptions, CredentialPersistenceOptions { -} +export type OnBehalfOfCredentialOptions = (OnBehalfOfCredentialSecretOptions | OnBehalfOfCredentialCertificateOptions) & TokenCredentialOptions & CredentialPersistenceOptions; // @public -export interface OnBehalfOfCredentialSecretConfiguration { +export interface OnBehalfOfCredentialSecretOptions { + certificatePath?: never; clientId: string; clientSecret: string; + sendCertificateChain?: never; tenantId: string; userAssertionToken: string; } @@ -297,7 +299,7 @@ export function useIdentityPlugin(plugin: IdentityPlugin): void; export class UsernamePasswordCredential implements TokenCredential { constructor(tenantId: string, clientId: string, username: string, password: string, options?: UsernamePasswordCredentialOptions); getToken(scopes: string | string[], options?: GetTokenOptions): Promise; - } +} // @public export interface UsernamePasswordCredentialOptions extends TokenCredentialOptions, CredentialPersistenceOptions { @@ -307,14 +309,13 @@ export interface UsernamePasswordCredentialOptions extends TokenCredentialOption export class VisualStudioCodeCredential implements TokenCredential { constructor(options?: VisualStudioCodeCredentialOptions); getToken(scopes: string | string[], options?: GetTokenOptions): Promise; - } +} // @public export interface VisualStudioCodeCredentialOptions extends TokenCredentialOptions { tenantId?: string; } - // (No @packageDocumentation comment for this package) ``` diff --git a/sdk/identity/identity/src/credentials/applicationCredential.browser.ts b/sdk/identity/identity/src/credentials/azureApplicationCredential.browser.ts similarity index 83% rename from sdk/identity/identity/src/credentials/applicationCredential.browser.ts rename to sdk/identity/identity/src/credentials/azureApplicationCredential.browser.ts index f716c1d44ea5..a2c85b71f9be 100644 --- a/sdk/identity/identity/src/credentials/applicationCredential.browser.ts +++ b/sdk/identity/identity/src/credentials/azureApplicationCredential.browser.ts @@ -18,11 +18,11 @@ const logger = credentialLogger("ApplicationCredential"); * * Only available in Node.js */ -export class ApplicationCredential extends ChainedTokenCredential { +export class AzureApplicationCredential extends ChainedTokenCredential { /** - * Creates an instance of the ApplicationCredential class. + * Creates an instance of the AzureApplicationCredential class. * - * The ApplicationCredential provides a default {@link ChainedTokenCredential} configuration for + * The AzureApplicationCredential provides a default {@link ChainedTokenCredential} configuration for * applications that will be deployed to Azure. * * Only available in Node.js diff --git a/sdk/identity/identity/src/credentials/applicationCredential.ts b/sdk/identity/identity/src/credentials/azureApplicationCredential.ts similarity index 67% rename from sdk/identity/identity/src/credentials/applicationCredential.ts rename to sdk/identity/identity/src/credentials/azureApplicationCredential.ts index d199fc811c8f..a0343af27538 100644 --- a/sdk/identity/identity/src/credentials/applicationCredential.ts +++ b/sdk/identity/identity/src/credentials/azureApplicationCredential.ts @@ -12,9 +12,9 @@ import { CredentialPersistenceOptions } from "./credentialPersistenceOptions"; import { DefaultManagedIdentityCredential } from "./defaultAzureCredential"; /** - * Provides options to configure the {@link ApplicationCredential} class. + * Provides options to configure the {@link AzureApplicationCredential} class. */ -export interface ApplicationCredentialOptions +export interface AzureApplicationCredentialOptions extends TokenCredentialOptions, CredentialPersistenceOptions { /** @@ -28,11 +28,11 @@ export interface ApplicationCredentialOptions * The type of a class that implements TokenCredential and accepts * `ApplicationCredentialOptions`. */ -interface ApplicationCredentialConstructor { - new (options?: ApplicationCredentialOptions): TokenCredential; +interface AzureApplicationCredentialConstructor { + new (options?: AzureApplicationCredentialOptions): TokenCredential; } -export const ApplicationCredentials: ApplicationCredentialConstructor[] = [ +export const AzureApplicationCredentials: AzureApplicationCredentialConstructor[] = [ EnvironmentCredential, DefaultManagedIdentityCredential ]; @@ -41,11 +41,11 @@ export const ApplicationCredentials: ApplicationCredentialConstructor[] = [ * Provides a default {@link ChainedTokenCredential} configuration that should * work for most applications that use the Azure SDK. */ -export class ApplicationCredential extends ChainedTokenCredential { +export class AzureApplicationCredential extends ChainedTokenCredential { /** - * Creates an instance of the ApplicationCredential class. + * Creates an instance of the AzureApplicationCredential class. * - * The ApplicationCredential provides a default {@link ChainedTokenCredential} configuration that should + * The AzureApplicationCredential provides a default {@link ChainedTokenCredential} configuration that should * work for most applications that use the Azure SDK. The following credential * types will be tried, in order: * @@ -55,10 +55,10 @@ export class ApplicationCredential extends ChainedTokenCredential { * Consult the documentation of these credential types for more information * on how they attempt authentication. * - * @param options - Optional parameters. See {@link ApplicationCredentialOptions}. + * @param options - Optional parameters. See {@link AzureApplicationCredentialOptions}. */ - constructor(options?: ApplicationCredentialOptions) { - super(...ApplicationCredentials.map((ctor) => new ctor(options))); + constructor(options?: AzureApplicationCredentialOptions) { + super(...AzureApplicationCredentials.map((ctor) => new ctor(options))); this.UnavailableMessage = "ApplicationCredential => failed to retrieve a token from the included credentials"; } diff --git a/sdk/identity/identity/src/credentials/defaultAzureCredential.ts b/sdk/identity/identity/src/credentials/defaultAzureCredential.ts index f63dfeac0451..5a17348d154d 100644 --- a/sdk/identity/identity/src/credentials/defaultAzureCredential.ts +++ b/sdk/identity/identity/src/credentials/defaultAzureCredential.ts @@ -11,15 +11,12 @@ import { AzureCliCredential } from "./azureCliCredential"; import { AzurePowerShellCredential } from "./azurePowerShellCredential"; import { EnvironmentCredential } from "./environmentCredential"; import { ManagedIdentityCredential } from "./managedIdentityCredential"; -import { CredentialPersistenceOptions } from "./credentialPersistenceOptions"; import { VisualStudioCodeCredential } from "./visualStudioCodeCredential"; /** * Provides options to configure the {@link DefaultAzureCredential} class. */ -export interface DefaultAzureCredentialOptions - extends TokenCredentialOptions, - CredentialPersistenceOptions { +export interface DefaultAzureCredentialOptions extends TokenCredentialOptions { /** * Optionally pass in a Tenant ID to be used as part of the credential. * By default it may use a generic tenant ID depending on the underlying credential. diff --git a/sdk/identity/identity/src/credentials/environmentCredential.ts b/sdk/identity/identity/src/credentials/environmentCredential.ts index 605121126e68..5b1ca011585b 100644 --- a/sdk/identity/identity/src/credentials/environmentCredential.ts +++ b/sdk/identity/identity/src/credentials/environmentCredential.ts @@ -11,7 +11,6 @@ import { checkTenantId } from "../util/checkTenantId"; import { trace } from "../util/tracing"; import { ClientCertificateCredential } from "./clientCertificateCredential"; import { UsernamePasswordCredential } from "./usernamePasswordCredential"; -import { CredentialPersistenceOptions } from "./credentialPersistenceOptions"; /** * Contains the list of all supported environment variable names so that an @@ -35,9 +34,7 @@ const logger = credentialLogger("EnvironmentCredential"); * Enables authentication to Azure Active Directory depending on the available environment variables. * Defines options for the EnvironmentCredential class. */ -export interface EnvironmentCredentialOptions - extends TokenCredentialOptions, - CredentialPersistenceOptions {} +export interface EnvironmentCredentialOptions extends TokenCredentialOptions {} /** * Enables authentication to Azure Active Directory using client secret diff --git a/sdk/identity/identity/src/credentials/onBehalfOfCredential.ts b/sdk/identity/identity/src/credentials/onBehalfOfCredential.ts index 1c67df5da7bc..5b658b0723a4 100644 --- a/sdk/identity/identity/src/credentials/onBehalfOfCredential.ts +++ b/sdk/identity/identity/src/credentials/onBehalfOfCredential.ts @@ -7,60 +7,15 @@ import { MsalOnBehalfOf } from "../msal/nodeFlows/msalOnBehalfOf"; import { credentialLogger } from "../util/logging"; import { trace } from "../util/tracing"; import { MsalFlow } from "../msal/flows"; -import { OnBehalfOfCredentialOptions } from "./onBehalfOfCredentialOptions"; +import { + OnBehalfOfCredentialCertificateOptions, + OnBehalfOfCredentialOptions, + OnBehalfOfCredentialSecretOptions +} from "./onBehalfOfCredentialOptions"; const credentialName = "OnBehalfOfCredential"; const logger = credentialLogger(credentialName); -/** - * Defines the configuration parameters to authenticate the {@link OnBehalfOfCredential} with a secret. - */ -export interface OnBehalfOfCredentialSecretConfiguration { - /** - * The Azure Active Directory tenant (directory) ID. - */ - tenantId: string; - /** - * The client (application) ID of an App Registration in the tenant. - */ - clientId: string; - /** - * A client secret that was generated for the App Registration. - */ - clientSecret: string; - /** - * The user assertion for the On-Behalf-Of flow. - */ - userAssertionToken: string; -} - -/** - * Defines the configuration parameters to authenticate the {@link OnBehalfOfCredential} with a certificate. - */ -export interface OnBehalfOfCredentialCertificateConfiguration { - /** - * The Azure Active Directory tenant (directory) ID. - */ - tenantId: string; - /** - * The client (application) ID of an App Registration in the tenant. - */ - clientId: string; - /** - * The path to a PEM-encoded public/private key certificate on the filesystem. - */ - certificatePath: string; - /** - * Option to include x5c header for SubjectName and Issuer name authorization. - * Set this option to send base64 encoded public certificate in the client assertion header as an x5c claim - */ - sendCertificateChain?: boolean; - /** - * The user assertion for the On-Behalf-Of flow. - */ - userAssertionToken: string; -} - /** * Enables authentication to Azure Active Directory using the [On Behalf Of flow](https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow). */ @@ -86,31 +41,19 @@ export class OnBehalfOfCredential implements TokenCredential { * await client.getKey("key-name"); * ``` * - * @param configuration - Configuration specific to this credential. * @param options - Optional parameters, generally common across credentials. */ - constructor( - private configuration: - | OnBehalfOfCredentialSecretConfiguration - | OnBehalfOfCredentialCertificateConfiguration, - private options: OnBehalfOfCredentialOptions = {} - ) { - const { tenantId, clientId, userAssertionToken } = configuration; - const secretConfiguration = configuration as OnBehalfOfCredentialSecretConfiguration; - const certificateConfiguration = configuration as OnBehalfOfCredentialCertificateConfiguration; - if ( - !tenantId || - !clientId || - !(secretConfiguration.clientSecret || certificateConfiguration.certificatePath) || - !userAssertionToken - ) { + constructor(private options: OnBehalfOfCredentialOptions) { + const { clientSecret } = options as OnBehalfOfCredentialSecretOptions; + const { certificatePath } = options as OnBehalfOfCredentialCertificateOptions; + const { tenantId, clientId, userAssertionToken } = options; + if (!tenantId || !clientId || !(clientSecret || certificatePath) || !userAssertionToken) { throw new Error( `${credentialName}: tenantId, clientId, clientSecret (or certificatePath) and userAssertionToken are required parameters.` ); } this.msalFlow = new MsalOnBehalfOf({ ...this.options, - ...this.configuration, logger, tokenCredentialOptions: this.options }); diff --git a/sdk/identity/identity/src/credentials/onBehalfOfCredentialOptions.ts b/sdk/identity/identity/src/credentials/onBehalfOfCredentialOptions.ts index 089b888242c5..7c374e1c86ad 100644 --- a/sdk/identity/identity/src/credentials/onBehalfOfCredentialOptions.ts +++ b/sdk/identity/identity/src/credentials/onBehalfOfCredentialOptions.ts @@ -4,9 +4,73 @@ import { TokenCredentialOptions } from "../client/identityClient"; import { CredentialPersistenceOptions } from "./credentialPersistenceOptions"; +/** + * Defines the parameters to authenticate the {@link OnBehalfOfCredential} with a secret. + */ +export interface OnBehalfOfCredentialSecretOptions { + /** + * The Azure Active Directory tenant (directory) ID. + */ + tenantId: string; + /** + * The client (application) ID of an App Registration in the tenant. + */ + clientId: string; + /** + * A client secret that was generated for the App Registration. + */ + clientSecret: string; + /** + * The user assertion for the On-Behalf-Of flow. + */ + userAssertionToken: string; + /** + * The path to a PEM-encoded certificate should not be provided when the secret options are provided. + */ + certificatePath?: never; + /** + * Option to include x5c header should not be provided when the secret options are provided. + */ + sendCertificateChain?: never; +} + +/** + * Defines the parameters to authenticate the {@link OnBehalfOfCredential} with a certificate. + */ +export interface OnBehalfOfCredentialCertificateOptions { + /** + * The Azure Active Directory tenant (directory) ID. + */ + tenantId: string; + /** + * The client (application) ID of an App Registration in the tenant. + */ + clientId: string; + /** + * The path to a PEM-encoded public/private key certificate on the filesystem. + */ + certificatePath: string; + /** + * Option to include x5c header for SubjectName and Issuer name authorization. + * Set this option to send base64 encoded public certificate in the client assertion header as an x5c claim + */ + sendCertificateChain?: boolean; + /** + * The user assertion for the On-Behalf-Of flow. + */ + userAssertionToken: string; + /** + * Client secret should not be provided when certificate options are provided. + */ + clientSecret?: never; +} + /** * Optional parameters for the {@link OnBehalfOfCredential} class. */ -export interface OnBehalfOfCredentialOptions - extends TokenCredentialOptions, - CredentialPersistenceOptions {} +export type OnBehalfOfCredentialOptions = ( + | OnBehalfOfCredentialSecretOptions + | OnBehalfOfCredentialCertificateOptions +) & + TokenCredentialOptions & + CredentialPersistenceOptions; diff --git a/sdk/identity/identity/src/index.ts b/sdk/identity/identity/src/index.ts index d824ede795d9..74fe2bd333fa 100644 --- a/sdk/identity/identity/src/index.ts +++ b/sdk/identity/identity/src/index.ts @@ -53,21 +53,21 @@ export { AuthorizationCodeCredential } from "./credentials/authorizationCodeCred export { AzurePowerShellCredential } from "./credentials/azurePowerShellCredential"; export { AzurePowerShellCredentialOptions } from "./credentials/azurePowerShellCredentialOptions"; export { - ApplicationCredential, - ApplicationCredentialOptions -} from "./credentials/applicationCredential"; + AzureApplicationCredential as ApplicationCredential, + AzureApplicationCredentialOptions as ApplicationCredentialOptions +} from "./credentials/azureApplicationCredential"; export { VisualStudioCodeCredential, VisualStudioCodeCredentialOptions } from "./credentials/visualStudioCodeCredential"; +export { OnBehalfOfCredential } from "./credentials/onBehalfOfCredential"; export { - OnBehalfOfCredential, - OnBehalfOfCredentialSecretConfiguration, - OnBehalfOfCredentialCertificateConfiguration -} from "./credentials/onBehalfOfCredential"; -export { OnBehalfOfCredentialOptions } from "./credentials/onBehalfOfCredentialOptions"; + OnBehalfOfCredentialOptions, + OnBehalfOfCredentialSecretOptions, + OnBehalfOfCredentialCertificateOptions +} from "./credentials/onBehalfOfCredentialOptions"; export { TokenCachePersistenceOptions } from "./msal/nodeFlows/tokenCachePersistenceOptions"; diff --git a/sdk/identity/identity/test/public/node/extensions.spec.ts b/sdk/identity/identity/test/public/node/extensions.spec.ts index 4f57e80bc5fd..73d07c18ace3 100644 --- a/sdk/identity/identity/test/public/node/extensions.spec.ts +++ b/sdk/identity/identity/test/public/node/extensions.spec.ts @@ -2,7 +2,7 @@ // Licensed under the MIT license. import { assert, AssertionError } from "chai"; -import { DefaultAzureCredential } from "../../../src"; +import { DeviceCodeCredential } from "../../../src"; import { VisualStudioCodeCredential } from "../../../src"; /** @@ -25,7 +25,7 @@ async function assertRejects(p: Promise, regexp: RegExp): Promise describe("Plugin API", function(this: Mocha.Suite) { it("Setting persistence options throws if not initialized", function() { assert.throws(() => { - new DefaultAzureCredential({ + new DeviceCodeCredential({ tokenCachePersistenceOptions: { enabled: true }