diff --git a/sdk/identity/Azure.Identity/CHANGELOG.md b/sdk/identity/Azure.Identity/CHANGELOG.md index c9773f83c0cdc..aae2c1d089215 100644 --- a/sdk/identity/Azure.Identity/CHANGELOG.md +++ b/sdk/identity/Azure.Identity/CHANGELOG.md @@ -6,6 +6,10 @@ - The `IDisposable` interface has been removed from `TokenCache`. +### New Features + +- All credentials added support to handle the `Claims` property on `TokenRequestContext` + ## 1.4.0-beta.2 (2021-01-29) ### Fixes and improvements diff --git a/sdk/identity/Azure.Identity/src/Azure.Identity.csproj b/sdk/identity/Azure.Identity/src/Azure.Identity.csproj index 686a890d8691d..87499d5bd4695 100644 --- a/sdk/identity/Azure.Identity/src/Azure.Identity.csproj +++ b/sdk/identity/Azure.Identity/src/Azure.Identity.csproj @@ -10,6 +10,7 @@ true + @@ -30,5 +31,6 @@ - - \ No newline at end of file + + + diff --git a/sdk/identity/Azure.Identity/src/DeviceCodeCredential.cs b/sdk/identity/Azure.Identity/src/DeviceCodeCredential.cs index 8b52275e29725..611e9ae9b72fd 100644 --- a/sdk/identity/Azure.Identity/src/DeviceCodeCredential.cs +++ b/sdk/identity/Azure.Identity/src/DeviceCodeCredential.cs @@ -172,7 +172,7 @@ private async Task AuthenticateImplAsync(bool async, Token try { - AccessToken token = await GetTokenViaDeviceCodeAsync(requestContext.Scopes, async, cancellationToken).ConfigureAwait(false); + AccessToken token = await GetTokenViaDeviceCodeAsync(requestContext, async, cancellationToken).ConfigureAwait(false); scope.Succeeded(token); @@ -196,7 +196,7 @@ private async ValueTask GetTokenImplAsync(bool async, TokenRequestC { try { - AuthenticationResult result = await Client.AcquireTokenSilentAsync(requestContext.Scopes, Record, async, cancellationToken).ConfigureAwait(false); + AuthenticationResult result = await Client.AcquireTokenSilentAsync(requestContext.Scopes, requestContext.Claims, Record, async, cancellationToken).ConfigureAwait(false); return scope.Succeeded(new AccessToken(result.AccessToken, result.ExpiresOn)); } @@ -211,7 +211,7 @@ private async ValueTask GetTokenImplAsync(bool async, TokenRequestC throw new AuthenticationRequiredException(AuthenticationRequiredMessage, requestContext, inner); } - return scope.Succeeded(await GetTokenViaDeviceCodeAsync(requestContext.Scopes, async, cancellationToken).ConfigureAwait(false)); + return scope.Succeeded(await GetTokenViaDeviceCodeAsync(requestContext, async, cancellationToken).ConfigureAwait(false)); } catch (Exception e) { @@ -219,9 +219,9 @@ private async ValueTask GetTokenImplAsync(bool async, TokenRequestC } } - private async Task GetTokenViaDeviceCodeAsync(string[] scopes, bool async, CancellationToken cancellationToken) + private async Task GetTokenViaDeviceCodeAsync(TokenRequestContext context, bool async, CancellationToken cancellationToken) { - AuthenticationResult result = await Client.AcquireTokenWithDeviceCodeAsync(scopes, code => DeviceCodeCallbackImpl(code, cancellationToken), async, cancellationToken).ConfigureAwait(false); + AuthenticationResult result = await Client.AcquireTokenWithDeviceCodeAsync(context.Scopes, context.Claims, code => DeviceCodeCallbackImpl(code, cancellationToken), async, cancellationToken).ConfigureAwait(false); Record = new AuthenticationRecord(result, ClientId); diff --git a/sdk/identity/Azure.Identity/src/InteractiveBrowserCredential.cs b/sdk/identity/Azure.Identity/src/InteractiveBrowserCredential.cs index 7d263d2549e64..b6bc5bee16831 100644 --- a/sdk/identity/Azure.Identity/src/InteractiveBrowserCredential.cs +++ b/sdk/identity/Azure.Identity/src/InteractiveBrowserCredential.cs @@ -160,7 +160,7 @@ private async Task AuthenticateImplAsync(bool async, Token try { - scope.Succeeded(await GetTokenViaBrowserLoginAsync(requestContext.Scopes, async, cancellationToken).ConfigureAwait(false)); + scope.Succeeded(await GetTokenViaBrowserLoginAsync(requestContext, async, cancellationToken).ConfigureAwait(false)); return Record; } @@ -182,7 +182,7 @@ private async ValueTask GetTokenImplAsync(bool async, TokenRequestC { try { - AuthenticationResult result = await Client.AcquireTokenSilentAsync(requestContext.Scopes, Record, async, cancellationToken).ConfigureAwait(false); + AuthenticationResult result = await Client.AcquireTokenSilentAsync(requestContext.Scopes, requestContext.Claims, Record, async, cancellationToken).ConfigureAwait(false); return scope.Succeeded(new AccessToken(result.AccessToken, result.ExpiresOn)); } @@ -197,7 +197,7 @@ private async ValueTask GetTokenImplAsync(bool async, TokenRequestC throw new AuthenticationRequiredException(AuthenticationRequiredMessage, requestContext, inner); } - return scope.Succeeded(await GetTokenViaBrowserLoginAsync(requestContext.Scopes, async, cancellationToken).ConfigureAwait(false)); + return scope.Succeeded(await GetTokenViaBrowserLoginAsync(requestContext, async, cancellationToken).ConfigureAwait(false)); } catch (Exception e) { @@ -205,9 +205,9 @@ private async ValueTask GetTokenImplAsync(bool async, TokenRequestC } } - private async Task GetTokenViaBrowserLoginAsync(string[] scopes, bool async, CancellationToken cancellationToken) + private async Task GetTokenViaBrowserLoginAsync(TokenRequestContext context, bool async, CancellationToken cancellationToken) { - AuthenticationResult result = await Client.AcquireTokenInteractiveAsync(scopes, Prompt.SelectAccount, async, cancellationToken).ConfigureAwait(false); + AuthenticationResult result = await Client.AcquireTokenInteractiveAsync(context.Scopes, context.Claims, Prompt.SelectAccount, async, cancellationToken).ConfigureAwait(false); Record = new AuthenticationRecord(result, ClientId); diff --git a/sdk/identity/Azure.Identity/src/MsalPublicClient.cs b/sdk/identity/Azure.Identity/src/MsalPublicClient.cs index ded0a54505730..948b22fd5b30a 100644 --- a/sdk/identity/Azure.Identity/src/MsalPublicClient.cs +++ b/sdk/identity/Azure.Identity/src/MsalPublicClient.cs @@ -38,6 +38,8 @@ protected override ValueTask CreateClientAsync(bool as pubAppBuilder = pubAppBuilder.WithRedirectUri(RedirectUrl); } + pubAppBuilder.WithClientCapabilities(new string[] { "CP1" }); + return new ValueTask(pubAppBuilder.Build()); } @@ -47,12 +49,15 @@ public virtual async ValueTask> GetAccountsAsync(bool async, Canc return await GetAccountsAsync(client, async).ConfigureAwait(false); } - public virtual async ValueTask AcquireTokenSilentAsync(string[] scopes, IAccount account, bool async, CancellationToken cancellationToken) + public virtual async ValueTask AcquireTokenSilentAsync(string[] scopes, string claims, IAccount account, bool async, CancellationToken cancellationToken) { IPublicClientApplication client = await GetClientAsync(async, cancellationToken).ConfigureAwait(false); - return await client.AcquireTokenSilent(scopes, account).ExecuteAsync(async, cancellationToken).ConfigureAwait(false); + return await client.AcquireTokenSilent(scopes, account) + .WithClaims(claims) + .ExecuteAsync(async, cancellationToken) + .ConfigureAwait(false); } - public virtual async ValueTask AcquireTokenSilentAsync(string[] scopes, AuthenticationRecord record, bool async, CancellationToken cancellationToken) + public virtual async ValueTask AcquireTokenSilentAsync(string[] scopes, string claims, AuthenticationRecord record, bool async, CancellationToken cancellationToken) { IPublicClientApplication client = await GetClientAsync(async, cancellationToken).ConfigureAwait(false); @@ -61,31 +66,47 @@ public virtual async ValueTask AcquireTokenSilentAsync(str // user authenticated to originally. return await client.AcquireTokenSilent(scopes, (AuthenticationAccount)record) .WithAuthority(Pipeline.AuthorityHost.AbsoluteUri, TenantId ?? record.TenantId) - .ExecuteAsync(async, cancellationToken).ConfigureAwait(false); + .WithClaims(claims) + .ExecuteAsync(async, cancellationToken) + .ConfigureAwait(false); } - public virtual async ValueTask AcquireTokenInteractiveAsync(string[] scopes, Prompt prompt, bool async, CancellationToken cancellationToken) + public virtual async ValueTask AcquireTokenInteractiveAsync(string[] scopes, string claims, Prompt prompt, bool async, CancellationToken cancellationToken) { IPublicClientApplication client = await GetClientAsync(async, cancellationToken).ConfigureAwait(false); - return await client.AcquireTokenInteractive(scopes).WithPrompt(prompt).ExecuteAsync(async, cancellationToken).ConfigureAwait(false); + return await client.AcquireTokenInteractive(scopes) + .WithPrompt(prompt) + .WithClaims(claims) + .ExecuteAsync(async, cancellationToken) + .ConfigureAwait(false); } - public virtual async ValueTask AcquireTokenByUsernamePasswordAsync(string[] scopes, string username, SecureString password, bool async, CancellationToken cancellationToken) + public virtual async ValueTask AcquireTokenByUsernamePasswordAsync(string[] scopes, string claims, string username, SecureString password, bool async, CancellationToken cancellationToken) { IPublicClientApplication client = await GetClientAsync(async, cancellationToken).ConfigureAwait(false); - return await client.AcquireTokenByUsernamePassword(scopes, username, password).ExecuteAsync(async, cancellationToken).ConfigureAwait(false); + return await client.AcquireTokenByUsernamePassword(scopes, username, password) + .WithClaims(claims) + .ExecuteAsync(async, cancellationToken) + .ConfigureAwait(false); } - public virtual async ValueTask AcquireTokenWithDeviceCodeAsync(string[] scopes, Func deviceCodeCallback, bool async, CancellationToken cancellationToken) + public virtual async ValueTask AcquireTokenWithDeviceCodeAsync(string[] scopes, string claims, Func deviceCodeCallback, bool async, CancellationToken cancellationToken) { IPublicClientApplication client = await GetClientAsync(async, cancellationToken).ConfigureAwait(false); - return await client.AcquireTokenWithDeviceCode(scopes, deviceCodeCallback).ExecuteAsync(async, cancellationToken).ConfigureAwait(false); + return await client.AcquireTokenWithDeviceCode(scopes, deviceCodeCallback) + .WithClaims(claims) + .ExecuteAsync(async, cancellationToken) + .ConfigureAwait(false); } - public virtual async ValueTask AcquireTokenByRefreshToken(string[] scopes, string refreshToken, AzureCloudInstance azureCloudInstance, string tenant, bool async, CancellationToken cancellationToken) + public virtual async ValueTask AcquireTokenByRefreshToken(string[] scopes, string claims, string refreshToken, AzureCloudInstance azureCloudInstance, string tenant, bool async, CancellationToken cancellationToken) { IPublicClientApplication client = await GetClientAsync(async, cancellationToken).ConfigureAwait(false); - return await ((IByRefreshToken)client).AcquireTokenByRefreshToken(scopes, refreshToken).WithAuthority(azureCloudInstance, tenant).ExecuteAsync(async, cancellationToken).ConfigureAwait(false); + return await ((IByRefreshToken)client).AcquireTokenByRefreshToken(scopes, refreshToken) + .WithAuthority(azureCloudInstance, tenant) + .WithClaims(claims) + .ExecuteAsync(async, cancellationToken) + .ConfigureAwait(false); } private static async ValueTask> GetAccountsAsync(IPublicClientApplication client, bool async) diff --git a/sdk/identity/Azure.Identity/src/SharedTokenCacheCredential.cs b/sdk/identity/Azure.Identity/src/SharedTokenCacheCredential.cs index cd5d78fd786ff..ab50e550370ba 100644 --- a/sdk/identity/Azure.Identity/src/SharedTokenCacheCredential.cs +++ b/sdk/identity/Azure.Identity/src/SharedTokenCacheCredential.cs @@ -113,7 +113,7 @@ private async ValueTask GetTokenImplAsync(bool async, TokenRequestC try { IAccount account = await GetAccountAsync(async, cancellationToken).ConfigureAwait(false); - AuthenticationResult result = await Client.AcquireTokenSilentAsync(requestContext.Scopes, account, async, cancellationToken).ConfigureAwait(false); + AuthenticationResult result = await Client.AcquireTokenSilentAsync(requestContext.Scopes, requestContext.Claims, account, async, cancellationToken).ConfigureAwait(false); return scope.Succeeded(new AccessToken(result.AccessToken, result.ExpiresOn)); } catch (MsalUiRequiredException) diff --git a/sdk/identity/Azure.Identity/src/UsernamePasswordCredential.cs b/sdk/identity/Azure.Identity/src/UsernamePasswordCredential.cs index 826c8e832d629..4e83b6a59ff76 100644 --- a/sdk/identity/Azure.Identity/src/UsernamePasswordCredential.cs +++ b/sdk/identity/Azure.Identity/src/UsernamePasswordCredential.cs @@ -185,7 +185,7 @@ private async Task GetTokenImplAsync(bool async, TokenRequestContex try { AuthenticationResult result = await _client - .AcquireTokenByUsernamePasswordAsync(requestContext.Scopes, _username, _password, async, cancellationToken) + .AcquireTokenByUsernamePasswordAsync(requestContext.Scopes, requestContext.Claims, _username, _password, async, cancellationToken) .ConfigureAwait(false); _record = new AuthenticationRecord(result, _clientId); diff --git a/sdk/identity/Azure.Identity/src/VisualStudioCodeCredential.cs b/sdk/identity/Azure.Identity/src/VisualStudioCodeCredential.cs index 308b5cd8652b5..1f31e38294ac3 100644 --- a/sdk/identity/Azure.Identity/src/VisualStudioCodeCredential.cs +++ b/sdk/identity/Azure.Identity/src/VisualStudioCodeCredential.cs @@ -71,7 +71,7 @@ private async ValueTask GetTokenImplAsync(TokenRequestContext reque var cloudInstance = GetAzureCloudInstance(environmentName); string storedCredentials = GetStoredCredentials(environmentName); - var result = await _client.AcquireTokenByRefreshToken(requestContext.Scopes, storedCredentials, cloudInstance, tenant, async, cancellationToken).ConfigureAwait(false); + var result = await _client.AcquireTokenByRefreshToken(requestContext.Scopes, requestContext.Claims, storedCredentials, cloudInstance, tenant, async, cancellationToken).ConfigureAwait(false); return scope.Succeeded(new AccessToken(result.AccessToken, result.ExpiresOn)); } catch (MsalUiRequiredException e) diff --git a/sdk/identity/Azure.Identity/tests/Mock/MockMsalPublicClient.cs b/sdk/identity/Azure.Identity/tests/Mock/MockMsalPublicClient.cs index 0d70c907b4e1a..2d1b0bf9f6f5e 100644 --- a/sdk/identity/Azure.Identity/tests/Mock/MockMsalPublicClient.cs +++ b/sdk/identity/Azure.Identity/tests/Mock/MockMsalPublicClient.cs @@ -32,7 +32,7 @@ public override ValueTask> GetAccountsAsync(bool async, Cancellat return new ValueTask>(Accounts); } - public override ValueTask AcquireTokenByUsernamePasswordAsync(string[] scopes, string username, SecureString password, bool async, CancellationToken cancellationToken) + public override ValueTask AcquireTokenByUsernamePasswordAsync(string[] scopes, string claims, string username, SecureString password, bool async, CancellationToken cancellationToken) { Func factory = UserPassAuthFactory ?? AuthFactory; @@ -44,7 +44,7 @@ public override ValueTask AcquireTokenByUsernamePasswordAs throw new NotImplementedException(); } - public override ValueTask AcquireTokenInteractiveAsync(string[] scopes, Prompt prompt, bool async, CancellationToken cancellationToken) + public override ValueTask AcquireTokenInteractiveAsync(string[] scopes, string claims, Prompt prompt, bool async, CancellationToken cancellationToken) { Func factory = InteractiveAuthFactory ?? AuthFactory; @@ -56,7 +56,7 @@ public override ValueTask AcquireTokenInteractiveAsync(str throw new NotImplementedException(); } - public override ValueTask AcquireTokenSilentAsync(string[] scopes, IAccount account, bool async, CancellationToken cancellationToken) + public override ValueTask AcquireTokenSilentAsync(string[] scopes, string claims, IAccount account, bool async, CancellationToken cancellationToken) { if (ExtendedSilentAuthFactory != null) { @@ -73,7 +73,7 @@ public override ValueTask AcquireTokenSilentAsync(string[] throw new NotImplementedException(); } - public override ValueTask AcquireTokenSilentAsync(string[] scopes, AuthenticationRecord record, bool async, CancellationToken cancellationToken) + public override ValueTask AcquireTokenSilentAsync(string[] scopes, string claims, AuthenticationRecord record, bool async, CancellationToken cancellationToken) { Func factory = SilentAuthFactory ?? AuthFactory; @@ -85,7 +85,7 @@ public override ValueTask AcquireTokenSilentAsync(string[] throw new NotImplementedException(); } - public override ValueTask AcquireTokenWithDeviceCodeAsync(string[] scopes, Func deviceCodeCallback, bool async, CancellationToken cancellationToken) + public override ValueTask AcquireTokenWithDeviceCodeAsync(string[] scopes, string claims, Func deviceCodeCallback, bool async, CancellationToken cancellationToken) { Func factory = DeviceCodeAuthFactory ?? AuthFactory;