20

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.

7
  • can you show your code including your using statements. Im guessing at this stage youve not references System.DirectoryServices at the moment. When you do this you can get the AD information with relative ease Commented Oct 23, 2016 at 20:16
  • @SimonPrice I have no code to show sorry, I scrapped my every attempt because it didn't work. But to give you an idea it's just a new project with windows authentication enabled, and from there it's just me suffering and failing miserably. I will definitely look up 'System.DirectoryServices', also what is AD? Commented Oct 23, 2016 at 20:28
  • AD is Active Directory. What is the idea of the project that youre trying to achieve? Commented Oct 23, 2016 at 20:30
  • @SimonPrice If a company employs like 100 people, and they look after their windows accounts (status/information/etc..). Having a separate account for internally used website/application would be a bad solution for them. So I am looking if it's viable to just use the windows accounts, and apply roles to them. And what actual information I can grab form the account they connect with. I am new to web dev, so everything is very confusing still. Commented Oct 23, 2016 at 20:41
  • come and chat to me here chat.stackoverflow.com/rooms/126473/windows-auth Commented Oct 23, 2016 at 20:43

3 Answers 3

12

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Related issue on github - github.com/aspnet/Security/issues/863
@blowdart does this work in .netcore 2.0? I didn't find UseClaimsTransformation.
Looks like this was overhauled a bit in 2.0. See stackoverflow.com/questions/45709296/….
10

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;

    }
}
}

3 Comments

Would you be able to show/explain how to add roles to the windows account before or after they connect?
if you can be in the chat link that I sent yesterday at 20:00hrs this evening then yes, I can talk you through it
The code above perform a check against the Groups a user is part of, not Roles.
6

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);
  }
}

1 Comment

The type is changed to IClaimsTransformation nowadays.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.