Reputation: 2909
I created an asp.net core project in visual studio 2015 with windows authentication. I can't figure out how to add roles to the Identity.
I have a table with usernames for the windows account. And when the user opens the website the user is added to the Identity (I assume that's what happens, because I can display the username by User.Identity.Name) and I want to pull out Roles from another table and assign them to the user, is this possible? Or perhaps is there a better way to do it? (Why?, How?)
I couldn't find any examples specific examples related to windows authentication, but I have read the documentation and went through this guide. And I'm still stuck.
Upvotes: 20
Views: 28722
Reputation: 3261
this is working code that I use to check is a user is in a role \ group, please use it at your leisure
using System.Collections.Generic;
using System.DirectoryServices.AccountManagement;
using System.Linq;
using System.Security.Principal;
namespace Santander.IsUserInGroupOrRole_cs
{
public class IsUserInRole
{
public static bool IsInGroup(string groupName)
{
var myIdentity = GetUserIdWithDomain();
var myPrincipal = new WindowsPrincipal(myIdentity);
return myPrincipal.IsInRole(groupName);
}
public bool IsInGroup(List<string> groupNames)
{
var myIdentity = GetUserIdWithDomain();
var myPrincipal = new WindowsPrincipal(myIdentity);
return groupNames.Any(group => myPrincipal.IsInRole(group));
}
public static WindowsIdentity GetUserIdWithDomain()
{
var myIdentity = WindowsIdentity.GetCurrent();
return myIdentity;
}
public static string GetUserId()
{
var id = GetUserIdWithDomain().Name.Split('\\');
return id[1];
}
public static string GetUserDisplayName()
{
var id = GetUserIdWithDomain().Name.Split('\\');
var dc = new PrincipalContext(ContextType.Domain, id[0]);
var adUser = UserPrincipal.FindByIdentity(dc, id[1]);
return adUser.DisplayName;
}
}
}
Upvotes: 10
Reputation: 983
For anyone interested, here is a simple example of how you can inject an EF DBContext into a custom ClaimsTransformer and add some custom role claims.
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IClaimsTransformer, MyClaimsTransformer>();
services.AddMvc();
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(
Configuration.GetConnectionString("MyConnStringSetting")
));
(...)
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseClaimsTransformation(context =>
{
var transformer = context.Context.RequestServices.GetRequiredService<IClaimsTransformer>();
return transformer.TransformAsync(context);
});
(...)
}
MyClaimsTransformer.cs
public class MyClaimsTransformer : IClaimsTransformer
{
private readonly MyDbContext _context;
public MyClaimsTransformer(MyDbContext context)
{
_context = context;
}
public Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context)
{
var identity = (ClaimsIdentity)context.Principal.Identity;
var userName = identity.Name;
var roles = _context.Role.Where(r => r.UserRole.Any(u => u.User.Username == userName)).Select(r => r.Name);
foreach (var role in roles)
{
var claim = new Claim(ClaimTypes.Role, role);
identity.AddClaim(claim);
}
return Task.FromResult(context.Principal);
}
}
Upvotes: 6
Reputation: 56500
With Windows Authentication the roles come from Active Directory, not a database.
You could use Claims Transformation to change the inbound identity on every request to pull extra roles from your database.
public class ClaimsTransformer : IClaimsTransformer
{
public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
((ClaimsIdentity)principal.Identity).AddClaim(
new Claim("ExampleClaim", "true"));
return Task.FromResult(principal);
}
}
And then wire it up with
app.UseClaimsTransformation(new ClaimsTransformationOptions
{
Transformer = new ClaimsTransformer()
});
Note that in the current incarnation there's no DI support, so you'll have to manually pull out your database information from DI if that's where it is.
Upvotes: 12