Search code examples
c#asp.net-coreasp.net-core-mvc

How do I use Windows Authentication with users in database


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.


Solution

  • 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() { }