8

My main goal is using the Windows Authentication to query my custom Users table to use through the web application. I am not sure there is a conventional way of doing this.

I have a predefined Users table and Roles table in a SQL database. How do I use the User.Identity.Name to query this Users table and map all the tables data along with the roles to a ApplicationUser class that can be further used later in the intranet web application?

I was unable to find anything closely related to what I am after from reading tons of articles. I assume this will be done in the Startup class under ConfigureServices but am also unsure of that. I need the user to be looked up whenever they navigate to the site for the first time.

adem caglin
  • 22,700
  • 10
  • 58
  • 78
HuntK24
  • 158
  • 2
  • 13

1 Answers1

5

I would go with ClaimsTransformer to get user claims. I just will try to show how to get user claims and to handle authorization for Windows Authenticatin.

First create a ClaimsTransformer class:

public class ClaimsTransformer : IClaimsTransformer
{
    // i assume you have a user service in which you get user info via entity framework
    private readonly IUserService _userService;   
    public ClaimsTransformer(IUserService userService)
    {
         _userService = userService;
    }
    public async Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context)
    {
        var identity = ((ClaimsIdentity)context.Principal.Identity);
        // ... add user claims if required
        var roles = _userService.GetRoles(identity.Name);
        foreach(var role in roles)
        {
            identity.AddClaim(new Claim(ClaimTypes.Role, role));
        }
        return await Task.FromResult(context.Principal);
    }
}

Then use it in Configure method

    public void Configure(IApplicationBuilder app)
    {
        //...
        app.UseClaimsTransformation(async (context) =>
        {
            IClaimsTransformer transformer = context.Context.RequestServices.GetRequiredService<IClaimsTransformer>();
            return await transformer.TransformAsync(context);
        });
        //...
    }

Unfortunately User.IsInRole method doesn't work with ClaimsTransformer(if you add role with ClaimsTransformer, IsInRole will be false) so you can't use [Authorize(Roles = "")] with ClaimsTransformer. In this case you can use Claims Based Authorization to handle authotorization.

So finally add below code to ConfigureServices and use Authorize attribute:

    public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddSingleton<IClaimsTransformer, ClaimsTransformer>();
        services.AddAuthorization(options =>
        {
            options.AddPolicy("RequireAdministratorRole", policy => policy.RequireClaim(ClaimTypes.Role, "Administrator"));
        });
        //...
    }

    [Authorize(Policy = "RequireAdministratorRole")]
    public IActionResult Index() { }
adem caglin
  • 22,700
  • 10
  • 58
  • 78
  • I believe this is exactly what I was after. I will mark correct after I implement and make sure I have no other questions. – HuntK24 Aug 19 '16 at 21:27
  • 2
    Hi, what about Core 2.2? `UseClaimsTransformation` doesn't exists there anymore :) – Givi Aug 06 '19 at 13:45
  • "if you add role with ClaimsTransformer, IsInRole will be false) so you can't use [Authorize(Roles = "")] with ClaimsTransformer." How come? Why is it like that? – JohanThorild Nov 08 '20 at 14:41