I have a dot net core 2.2 application that needs to have Windows Authentication with an Active Directory Group lookup to get a list of assigned groups for the current principal. These assigned groups will be the 'roles' that will be used in the Authorize attribute of certain methods. At least, in theory, that's what I'm hoping to accomplish.
I have completed the AD lookup and retrieval of the groups. At this point I'm not sure how to configure the Startup to persist this info within an auth token/cookie of some type or any UserManager/RoleManager setup kinda stuff.
Here are a couple of previous, somewhat similar questions, among others I've looked at. This previous post from .net 4.5 appears to be a similar issue, but it's the wrong version of .NET : windows-authentication-with-active-directory-groups. Can these AD groups be added as roles? Here's a potentially helpful post with this where they create a role for a user: how-to-create-roles-in-asp-net-core-2-2-and-assign-them-to-users. Confused about how this works. I've always found Identity, claims, tokens, etc. confusing so hopefully someone can assist with this in Core 2.2.
What do I need to do to get this to work? I've included most of my current code (AD code, some middleware parts, etc.), but then what? I'm sure there are others that would benefit from this too! Thank you!
I get the current Windows user and their AD record here:
return Task.Run(() =>
{
try
{
PrincipalContext context = new PrincipalContext(ContextType.Domain);
UserPrincipal principal = new UserPrincipal(context);
if (context != null)
{
//var identityName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
var identityName = identity.Name; // when windows authentication is checked
principal = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, identity.Name);
}
return AdUser.CastToAdUser(principal);
}
catch (Exception ex)
{
//TODO LOGGING
throw new Exception("Error retrieving AD User", ex);
}
});
The extension method CastToAdUser to create a more useful model is here:
public static AdUser CastToAdUser(UserPrincipal user)
{
return new AdUser
{
AccountExpirationDate = user.AccountExpirationDate,
AccountLockoutTime = user.AccountLockoutTime,
BadLogonCount = user.BadLogonCount,
Description = user.Description,
DisplayName = user.DisplayName,
DistinguishedName = user.DistinguishedName,
EmailAddress = user.EmailAddress,
EmployeeId = user.EmployeeId,
Enabled = user.Enabled,
GivenName = user.GivenName,
Guid = user.Guid,
HomeDirectory = user.HomeDirectory,
HomeDrive = user.HomeDrive,
LastBadPasswordAttempt = user.LastBadPasswordAttempt,
LastLogon = user.LastLogon,
LastPasswordSet = user.LastPasswordSet,
MiddleName = user.MiddleName,
Name = user.Name,
PasswordNeverExpires = user.PasswordNeverExpires,
PasswordNotRequired = user.PasswordNotRequired,
SamAccountName = user.SamAccountName,
ScriptPath = user.ScriptPath,
Sid = user.Sid,
Surname = user.Surname,
UserCannotChangePassword = user.UserCannotChangePassword,
UserPrincipalName = user.UserPrincipalName,
VoiceTelephoneNumber = user.VoiceTelephoneNumber,
Token = string.Empty,
};
}
return Task.Run(() =>
{
PrincipalSearchResult<Principal> groups = UserPrincipal.Current.GetGroups();
IEnumerable<SecurityGroup> securityGroups = groups.Select(x => x.ToAdUserSecurityGroups());
return securityGroups;
});
With the extension method to create a useful model, ToAdUserSecurityGroups here:
public static SecurityGroup ToAdUserSecurityGroups (this Principal result)
{
var securityGroup = new SecurityGroup
{
Sid = result.Sid.Value,
Name = result.SamAccountName,
Guid = result.Guid.Value,
};
return securityGroup;
}
So now I have the AD user, and the security groups that will hopefully be used for Authorization. I wire in my AD lookup stuff using some custom middleware, called UseAdMiddleWare. In my Startup class, I have an extension in the Configure method to fire off all the above 'stuff':
app.UseAdMiddleware();
And in my ConfigureServices I have the AddAuthentication stuff, which is needed, but might not be configured correctly for what I'm trying to do:
services.AddAuthentication();
In separate classes I have the code that allows this. The IAdUserProvider is my own class that does the AD lookup, with an entry point called Create:
public static class MiddlewareExtensions
{
public static IApplicationBuilder UseAdMiddleware(this IApplicationBuilder builder) =>
builder.UseMiddleware<AdUserMiddleware>();
}
public class AdUserMiddleware
{
private readonly RequestDelegate next;
public AdUserMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context, IAdUserProvider userProvider, IConfiguration config)
{
if (!(userProvider.Initialized))
{
await userProvider.Create(context, config);
}
await next(context);
}
}
So I think I'm well on my way to getting this wired up, but how/where do I add the security group specifics into claims or whatever? Thank you very much!