Group claim duplication when using Negotiate authentication on Linux AD domain member with LDAP
y4r9 opened this issue · comments
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
When using the Negotiate authentication on a Linux AD domain member with LDAP claim resolution as described at link, the nested groups are resolved multiple times, because in file aspnetcore/src/Security/Authentication/Negotiate/src/Internal/LdapAdapter.cs on line 73 a new HashSet is created in every iteration of the surrounding foreach loop. Furthermore, on Windows the claims contain the SIDs of the groups instead of the names, whereas on linux only the group names are returned. To allow for more portable code adding the SIDs would be helpful.
Adding the SIDs has also been requested previously by #31959.
Expected Behavior
- Unique group claims should be returned upon authentication.
- Object SIDs should be added to the claims to allow for portable claim based/policy based authorization.
Steps To Reproduce
No response
Exceptions (if any)
No response
.NET Version
8.0.204
Anything else?
No response
API change proposal:
Background and Motivation
When adding SID resolution using LDAP on Linux to solve the issue #55705 @halter73 requested to make this an optional feature in order to reduce overhead (see here). To allow for such a configuration to be added the public facing API of LdapSettings
needs to be changed.
Proposed API
src/Security/Authentication/Negotiate/src/LdapSettings.cs
@@ -16,6 +16,14 @@ public class LdapSettings
/// This is mainly used on Linux.
/// </summary>
public bool EnableLdapClaimResolution { get; set; }
+
+ /// <summary>
+ /// Configure whether the SID claims should be resolved when
+ /// EnableLdapClaimResolution is true and the LDAP connection
+ /// is used to resolve claims.
+ /// This is mainly used on Linux.
+ /// </summary>
+ public bool EnableLdapSIDClaimResolution { get; set; }
/// <summary>
/// The domain to use for the LDAP connection. This is a mandatory setting.
and
src/Security/Authentication/Negotiate/src/PublicAPI.Shipped.txt
@@ -24,6 +24,8 @@ Microsoft.AspNetCore.Authentication.Negotiate.LdapSettings.Domain.get -> string!
Microsoft.AspNetCore.Authentication.Negotiate.LdapSettings.Domain.set -> void
Microsoft.AspNetCore.Authentication.Negotiate.LdapSettings.EnableLdapClaimResolution.get -> bool
Microsoft.AspNetCore.Authentication.Negotiate.LdapSettings.EnableLdapClaimResolution.set -> void
+Microsoft.AspNetCore.Authentication.Negotiate.LdapSettings.EnableLdapSIDClaimResolution.get -> bool
+Microsoft.AspNetCore.Authentication.Negotiate.LdapSettings.EnableLdapSIDClaimResolution.set -> void
Microsoft.AspNetCore.Authentication.Negotiate.LdapSettings.IgnoreNestedGroups.get -> bool
Microsoft.AspNetCore.Authentication.Negotiate.LdapSettings.IgnoreNestedGroups.set -> void
Microsoft.AspNetCore.Authentication.Negotiate.LdapSettings.LdapConnection.get -> System.DirectoryServices.Protocols.LdapConnection?
Usage Examples
Simply enable the optional SID claim resolution by setting the option at initialization.
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate(options =>
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
options.EnableLdap(settings =>
{
settings.Domain = "contoso.com";
settings.EnableLdapSIDClaimResolution = true;
});
}
});
Alternative Designs
Alternatively the option may be included in EnableLdap
as optional parameter in NegotiateOptions
:
EnableLdap(string domain, bool enableLdapSIDClaimResolution = false)
which would result in the following usage example:
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate(options =>
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
options.EnableLdap("contoso.com", true);
}
});
Risks
Apart from not duplicating nested group claims, the added SID claims should not cause breaking changes. However, there will be a performance impact, both due to the additional LDAP queries, but also due to the increased storage demand. Nevertheless, the SID resolution is default on Windows and this change would allow to write more portable code. Furthermore, the overhead can be avoided when disabling the resolution using the newly added option proposed here.
Thank you for submitting this for API review. This will be reviewed by @dotnet/aspnet-api-review at the next meeting of the ASP.NET Core API Review group. Please ensure you take a look at the API review process documentation and ensure that:
- The PR contains changes to the reference-assembly that describe the API change. Or, you have included a snippet of reference-assembly-style code that illustrates the API change.
- The PR describes the impact to users, both positive (useful new APIs) and negative (breaking changes).
- Someone is assigned to "champion" this change in the meeting, and they understand the impact and design of the change.