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
1 change: 1 addition & 0 deletions sdk/identity/Azure.Identity/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
### New Features
- Restoring Application Authentication APIs from 1.2.0-preview.6
- Added `IncludeX5CClaimHeader` to `ClientCertificateCredentialOptions` to enable subject name / issuer authentication with the `ClientCertificateCredential`.
- Added `RedirectUri` to `InteractiveBrowserCredentialOptions` to enable authentication with user specified application with a custom redirect url.

### Fixes and improvements
- Fixed issue with non GUID Client Ids (Issue [#14585](https://github.com/Azure/azure-sdk-for-net/issues/14585))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ public InteractiveBrowserCredentialOptions() { }
public string ClientId { get { throw null; } set { } }
public bool DisableAutomaticAuthentication { get { throw null; } set { } }
public bool EnablePersistentCache { get { throw null; } set { } }
public System.Uri RedirectUri { get { throw null; } set { } }
public string TenantId { get { throw null; } set { } }
}
public partial class ManagedIdentityCredential : Azure.Core.TokenCredential
Expand Down
2 changes: 2 additions & 0 deletions sdk/identity/Azure.Identity/src/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ internal class Constants

public static readonly TimeSpan SharedTokenCacheAccessRetryDelay = TimeSpan.FromMilliseconds(600);

public const string DefaultRedirectUrl = "http://localhost";

public static readonly string DefaultMsalTokenCacheDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), ".IdentityService");

public const string DefaultMsalTokenCacheKeychainService = "Microsoft.Developer.IdentityService";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ internal InteractiveBrowserCredential(string tenantId, string clientId, TokenCre

Pipeline = pipeline ?? CredentialPipeline.GetInstance(options);

Client = client ?? new MsalPublicClient(Pipeline, tenantId, clientId, "http://localhost", options as ITokenCacheOptions);
var redirectUrl = (options as InteractiveBrowserCredentialOptions)?.RedirectUri?.AbsoluteUri ?? Constants.DefaultRedirectUrl;

Client = client ?? new MsalPublicClient(Pipeline, tenantId, clientId, redirectUrl, options as ITokenCacheOptions);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Threading;

namespace Azure.Identity
Expand Down Expand Up @@ -36,6 +37,12 @@ public class InteractiveBrowserCredentialOptions : TokenCredentialOptions, IToke
/// </summary>
public bool AllowUnencryptedCache { get; set; }

/// <summary>
/// Uri where the STS will call back the application with the security token. This parameter is not required if the caller is not using a custom <see cref="ClientId"/>. In
/// the case that the caller is using their own <see cref="ClientId"/> the value must match the redirect url specified when creating the application registration.
/// </summary>
public Uri RedirectUri { get; set; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be null or DefaultRedirectUrl as default value?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could see an argument for both sides. I made it null to avoid the allocation but I could make a static readonly to accomplish the same. Currently there are other values which have a default when not set that we don't expose to the user such as ClientId so using null is a consistent with that as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok


/// <summary>
/// The <see cref="Identity.AuthenticationRecord"/> captured from a previous authentication.
/// </summary>
Expand Down
8 changes: 4 additions & 4 deletions sdk/identity/Azure.Identity/src/MsalPublicClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Azure.Identity
{
internal class MsalPublicClient : MsalClientBase<IPublicClientApplication>
{
private readonly string _redirectUrl;
internal string RedirectUrl { get; }

protected MsalPublicClient()
{
Expand All @@ -22,7 +22,7 @@ protected MsalPublicClient()
public MsalPublicClient(CredentialPipeline pipeline, string tenantId, string clientId, string redirectUrl, ITokenCacheOptions cacheOptions)
: base(pipeline, tenantId, clientId, cacheOptions)
{
_redirectUrl = redirectUrl;
RedirectUrl = redirectUrl;
}

protected override ValueTask<IPublicClientApplication> CreateClientAsync(bool async, CancellationToken cancellationToken)
Expand All @@ -33,9 +33,9 @@ protected override ValueTask<IPublicClientApplication> CreateClientAsync(bool as

PublicClientApplicationBuilder pubAppBuilder = PublicClientApplicationBuilder.Create(ClientId).WithAuthority(authorityUri).WithHttpClientFactory(new HttpPipelineClientFactory(Pipeline.HttpPipeline));

if (!string.IsNullOrEmpty(_redirectUrl))
if (!string.IsNullOrEmpty(RedirectUrl))
{
pubAppBuilder = pubAppBuilder.WithRedirectUri(_redirectUrl);
pubAppBuilder = pubAppBuilder.WithRedirectUri(RedirectUrl);
}

return new ValueTask<IPublicClientApplication>(pubAppBuilder.Build());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ public void ValidateConstructorOverload1()
DisableAutomaticAuthentication = true,
EnablePersistentCache = true,
AllowUnencryptedCache = true,
AuthenticationRecord = new AuthenticationRecord()
AuthenticationRecord = new AuthenticationRecord(),
RedirectUri = new Uri("https://localhost:8080"),
};

credential = new InteractiveBrowserCredential(options);
Expand Down Expand Up @@ -118,6 +119,15 @@ public void AssertOptionsHonored(InteractiveBrowserCredentialOptions options, In
Assert.AreEqual(options.EnablePersistentCache, credential.Client.EnablePersistentCache);
Assert.AreEqual(options.AllowUnencryptedCache, credential.Client.AllowUnencryptedCache);
Assert.AreEqual(options.AuthenticationRecord, credential.Record);

if (options.RedirectUri != null)
{
Assert.AreEqual(options.RedirectUri, new Uri(credential.Client.RedirectUrl));
}
else
{
Assert.AreEqual(Constants.DefaultRedirectUrl, credential.Client.RedirectUrl);
}
}

}
Expand Down