Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion eng/Packages.Data.props
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
<PackageReference Update="Azure.Communication.Common" Version="1.2.1" />
<PackageReference Update="Azure.Core" Version="1.37.0" />
<PackageReference Update="Azure.Core.Amqp" Version="1.3.0" />
<PackageReference Update="Azure.Core.Experimental" Version="0.1.0-preview.31" />
<PackageReference Update="Azure.Core.Experimental" Version="0.1.0-preview.32" />
<PackageReference Update="Azure.Core.Expressions.DataFactory" Version="1.0.0-beta.6" />
<PackageReference Update="Azure.Data.SchemaRegistry" Version="1.2.0" />
<PackageReference Update="Azure.Data.Tables" Version="12.8.0" />
Expand Down
1 change: 1 addition & 0 deletions sdk/identity/Azure.Identity.Broker/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Features Added

- `InteractiveBrowserCredentialBrokerOptions` and `SharedTokenCacheCredentialBrokerOptions` now support a `UseOperatingSystemAccount` property to enable the use of the currently logged in operating system account for authentication rather than prompting for a credential.
- Preview support for Proof of Possession (PoP) tokens for `InteractiveBrowserCredential`. This feature is enabled via the `IsProofOfPossessionRequired` property on `InteractiveBrowserCredentialBrokerOptions`.

### Breaking Changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ public partial class InteractiveBrowserCredentialBrokerOptions : Azure.Identity.
public InteractiveBrowserCredentialBrokerOptions(System.IntPtr parentWindowHandle) { }
public bool? IsLegacyMsaPassthroughEnabled { get { throw null; } set { } }
public bool IsProofOfPossessionRequired { get { throw null; } set { } }
public bool UseOperatingSystemAccount { get { throw null; } set { } }
}
public partial class SharedTokenCacheCredentialBrokerOptions : Azure.Identity.SharedTokenCacheCredentialOptions
{
public SharedTokenCacheCredentialBrokerOptions() { }
public SharedTokenCacheCredentialBrokerOptions(Azure.Identity.TokenCachePersistenceOptions tokenCacheOptions) { }
public bool? IsLegacyMsaPassthroughEnabled { get { throw null; } set { } }
public bool IsProofOfPossessionRequired { get { throw null; } set { } }
public bool UseOperatingSystemAccount { get { throw null; } set { } }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ public partial class InteractiveBrowserCredentialBrokerOptions : Azure.Identity.
public InteractiveBrowserCredentialBrokerOptions(System.IntPtr parentWindowHandle) { }
public bool? IsLegacyMsaPassthroughEnabled { get { throw null; } set { } }
public bool IsProofOfPossessionRequired { get { throw null; } set { } }
public bool UseOperatingSystemAccount { get { throw null; } set { } }
}
public partial class SharedTokenCacheCredentialBrokerOptions : Azure.Identity.SharedTokenCacheCredentialOptions
{
public SharedTokenCacheCredentialBrokerOptions() { }
public SharedTokenCacheCredentialBrokerOptions(Azure.Identity.TokenCachePersistenceOptions tokenCacheOptions) { }
public bool? IsLegacyMsaPassthroughEnabled { get { throw null; } set { } }
public bool IsProofOfPossessionRequired { get { throw null; } set { } }
public bool UseOperatingSystemAccount { get { throw null; } set { } }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ public partial class InteractiveBrowserCredentialBrokerOptions : Azure.Identity.
public InteractiveBrowserCredentialBrokerOptions(System.IntPtr parentWindowHandle) { }
public bool? IsLegacyMsaPassthroughEnabled { get { throw null; } set { } }
public bool IsProofOfPossessionRequired { get { throw null; } set { } }
public bool UseOperatingSystemAccount { get { throw null; } set { } }
}
public partial class SharedTokenCacheCredentialBrokerOptions : Azure.Identity.SharedTokenCacheCredentialOptions
{
public SharedTokenCacheCredentialBrokerOptions() { }
public SharedTokenCacheCredentialBrokerOptions(Azure.Identity.TokenCachePersistenceOptions tokenCacheOptions) { }
public bool? IsLegacyMsaPassthroughEnabled { get { throw null; } set { } }
public bool IsProofOfPossessionRequired { get { throw null; } set { } }
public bool UseOperatingSystemAccount { get { throw null; } set { } }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ public class InteractiveBrowserCredentialBrokerOptions : InteractiveBrowserCrede
/// </summary>
public bool IsProofOfPossessionRequired { get; set; }

/// <summary>
/// Gets or sets whether to authenticate with the currently signed in user instead of prompting the user with a login dialog.
/// </summary>
public bool UseOperatingSystemAccount { get; set; }

/// <summary>
/// Creates a new instance of <see cref="InteractiveBrowserCredentialBrokerOptions"/> to configure a <see cref="InteractiveBrowserCredential"/>.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ public class SharedTokenCacheCredentialBrokerOptions : SharedTokenCacheCredentia
/// </summary>
public bool IsProofOfPossessionRequired { get; set; }

/// <summary>
/// Gets or sets whether to authenticate with the currently signed in user instead of prompting the user with a login dialog.
/// </summary>
public bool UseOperatingSystemAccount { get; set; }

/// <summary>
/// Initializes a new instance of <see cref="SharedTokenCacheCredentialBrokerOptions"/>.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ public void RespectsMsaPassthrough(
IMsalPublicClientInitializerOptions credentialOptions;
if (enableMsaPassthrough.HasValue)
{
credentialOptions = new InteractiveBrowserCredentialBrokerOptions(parentWindowHandle) { IsLegacyMsaPassthroughEnabled = enableMsaPassthrough.Value } as IMsalPublicClientInitializerOptions;
credentialOptions = new InteractiveBrowserCredentialBrokerOptions(parentWindowHandle) { IsLegacyMsaPassthroughEnabled = enableMsaPassthrough.Value };
}
else
{
credentialOptions = new InteractiveBrowserCredentialBrokerOptions(parentWindowHandle) as IMsalPublicClientInitializerOptions;
credentialOptions = new InteractiveBrowserCredentialBrokerOptions(parentWindowHandle);
}
PublicClientApplicationBuilder builder = PublicClientApplicationBuilder
.Create(Guid.NewGuid().ToString());
Expand All @@ -34,6 +34,20 @@ public void RespectsMsaPassthrough(
Assert.AreEqual(parentWindowHandle, Parent());
}

[Test]
public void RespectsUseOperatingSystemAccount(
[Values(true, false)] bool enableUseOperatingSystemAccount)
{
IntPtr parentWindowHandle = new(1234);
IMsalPublicClientInitializerOptions credentialOptions;
credentialOptions = new InteractiveBrowserCredentialBrokerOptions(parentWindowHandle) { UseOperatingSystemAccount = enableUseOperatingSystemAccount };
PublicClientApplicationBuilder builder = PublicClientApplicationBuilder
.Create(Guid.NewGuid().ToString());

var credential = new InteractiveBrowserCredential((InteractiveBrowserCredentialBrokerOptions)credentialOptions);
Assert.AreEqual(enableUseOperatingSystemAccount, credential.UseOperatingSystemAccount);
}

private static (BrokerOptions Options, Func<object> Parent) GetBrokerOptions(PublicClientApplicationBuilder builder)
{
var config = builder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,19 @@ public async Task AuthenticateWithBrokerAsync()
Assert.NotNull(token.Token);
}

[Test]
[Ignore("This test is an integration test which can only be run with user interaction")]
public async Task AuthenticateWithBrokerWithUseOperatingSystemAccount_DoesNotPrompt()
{
IntPtr parentWindowHandle = GetForegroundWindow();

var cred = new InteractiveBrowserCredential(new InteractiveBrowserCredentialBrokerOptions(parentWindowHandle) { UseOperatingSystemAccount = true });

AccessToken token = await cred.GetTokenAsync(new TokenRequestContext(new string[] { "https://vault.azure.net/.default" })).ConfigureAwait(false);

Assert.NotNull(token.Token);
}

[Test]
[TestCase(true)]
[TestCase(false)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,16 @@ public async Task SilentAuthenticateWithBrokerAsync()

Assert.NotNull(token.Token);
}

[Test]
[Ignore("This test is an integration test which can only be run with user interaction")]
public async Task AuthenticateWithBrokerWithUseOperatingSystemAccount_DoesNotPrompt()
{
var cred = new SharedTokenCacheCredential(new SharedTokenCacheCredentialBrokerOptions() { UseOperatingSystemAccount = true });

AccessToken token = await cred.GetTokenAsync(new TokenRequestContext(new string[] { "https://vault.azure.net/.default" })).ConfigureAwait(false);

Assert.NotNull(token.Token);
}
}
}
2 changes: 1 addition & 1 deletion sdk/identity/Azure.Identity/src/Azure.Identity.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<DefineConstants>PREVIEW_FEATURE_FLAG</DefineConstants>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\core\Azure.Core.Experimental\src\Azure.Core.Experimental.csproj" />
<PackageReference Include="Azure.Core.Experimental" />
</ItemGroup>
</When>
</Choose>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class InteractiveBrowserCredential : TokenCredential
internal AuthenticationRecord Record { get; private set; }
internal string DefaultScope { get; }
internal TenantIdResolverBase TenantIdResolver { get; }
internal bool UseOperatingSystemAccount { get; }

private const string AuthenticationRequiredMessage = "Interactive authentication is needed to acquire token. Call Authenticate to interactively authenticate.";
private const string NoDefaultScopeMessage = "Authenticating in this environment requires specifying a TokenRequestContext.";
Expand Down Expand Up @@ -95,6 +96,7 @@ internal InteractiveBrowserCredential(string tenantId, string clientId, TokenCre
AdditionallyAllowedTenantIds = TenantIdResolver.ResolveAddionallyAllowedTenantIds((options as ISupportsAdditionallyAllowedTenants)?.AdditionallyAllowedTenants);
Record = (options as InteractiveBrowserCredentialOptions)?.AuthenticationRecord;
BrowserCustomization = (options as InteractiveBrowserCredentialOptions)?.BrowserCustomization;
UseOperatingSystemAccount = (options as IMsalPublicClientInitializerOptions)?.UseOperatingSystemAccount ?? false;
}

/// <summary>
Expand Down Expand Up @@ -228,13 +230,23 @@ private async ValueTask<AccessToken> GetTokenImplAsync(bool async, PopTokenReque
Exception inner = null;

var tenantId = TenantIdResolver.Resolve(TenantId ?? Record?.TenantId, requestContext, AdditionallyAllowedTenantIds);
if (Record is not null)
if (Record is not null || UseOperatingSystemAccount)
{
try
{
AuthenticationResult result = await Client
.AcquireTokenSilentAsync(requestContext.Scopes, requestContext.Claims, Record, tenantId, requestContext.IsCaeEnabled, async, cancellationToken)
AuthenticationResult result;
if (Record is null)
{
result = await Client
.AcquireTokenSilentAsync(requestContext.Scopes, requestContext.Claims, PublicClientApplication.OperatingSystemAccount, tenantId, requestContext.IsCaeEnabled, async, cancellationToken)
.ConfigureAwait(false);
}
else
{
result = await Client
.AcquireTokenSilentAsync(requestContext.Scopes, requestContext.Claims, Record, tenantId, requestContext.IsCaeEnabled, async, cancellationToken)
.ConfigureAwait(false);
}

return scope.Succeeded(new AccessToken(result.AccessToken, result.ExpiresOn));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class SharedTokenCacheCredential : TokenCredential
internal string Username { get; }
internal MsalPublicClient Client { get; }
internal TenantIdResolverBase TenantIdResolver { get; }
internal bool UseOperatingSystemAccount { get; }

/// <summary>
/// Creates a new <see cref="SharedTokenCacheCredential"/> which will authenticate users signed in through developer tools supporting Azure single sign on.
Expand Down Expand Up @@ -83,6 +84,7 @@ internal SharedTokenCacheCredential(string tenantId, string username, TokenCrede
options ?? s_DefaultCacheOptions);
_accountAsyncLock = new AsyncLockWithValue<IAccount>();
TenantIdResolver = options?.TenantIdResolver ?? TenantIdResolverBase.Default;
UseOperatingSystemAccount = (options as IMsalPublicClientInitializerOptions)?.UseOperatingSystemAccount ?? false;
}

/// <summary>
Expand Down Expand Up @@ -118,8 +120,20 @@ private async ValueTask<AccessToken> GetTokenImplAsync(bool async, TokenRequestC
try
{
var tenantId = TenantIdResolver.Resolve(TenantId, requestContext, TenantIdResolverBase.AllTenants);
IAccount account = await GetAccountAsync(tenantId, requestContext.IsCaeEnabled, async, cancellationToken).ConfigureAwait(false);
AuthenticationResult result = await Client.AcquireTokenSilentAsync(requestContext.Scopes, requestContext.Claims, account, tenantId, requestContext.IsCaeEnabled, async, cancellationToken).ConfigureAwait(false);

IAccount account = UseOperatingSystemAccount ?
PublicClientApplication.OperatingSystemAccount :
await GetAccountAsync(tenantId, requestContext.IsCaeEnabled, async, cancellationToken).ConfigureAwait(false);

AuthenticationResult result = await Client.AcquireTokenSilentAsync(
requestContext.Scopes,
requestContext.Claims,
account,
tenantId,
requestContext.IsCaeEnabled,
async,
cancellationToken).ConfigureAwait(false);

return scope.Succeeded(new AccessToken(result.AccessToken, result.ExpiresOn));
}
catch (MsalUiRequiredException ex)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ internal interface IMsalPublicClientInitializerOptions
{
Action<PublicClientApplicationBuilder> BeforeBuildClient { get; }
bool IsProofOfPossessionRequired { get; set; }

bool UseOperatingSystemAccount { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,8 @@ public ExtendedInteractiveBrowserCredentialOptions(Action<PublicClientApplicatio

public bool IsProofOfPossessionRequired { get; set; }

public bool UseOperatingSystemAccount { get; set; }

Action<PublicClientApplicationBuilder> IMsalPublicClientInitializerOptions.BeforeBuildClient { get { return _beforeBuildClient; } }
}

Expand Down