ASP.NET Core - Authorization Using Windows Authentication

10,569

That seems you want to use claims-based authorization via policies . After setting windows authentication in your application , you could add custom claim to ClaimsPrincipal ,check user's identity and confirm which permission current user has :

  1. You can add a claims transformation service to your application:

    class ClaimsTransformer : IClaimsTransformation
    {
        public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
        {
            var id = ((ClaimsIdentity)principal.Identity);
    
            var ci = new ClaimsIdentity(id.Claims, id.AuthenticationType, id.NameClaimType, id.RoleClaimType);
            if (ci.Name.Equals("name"))
            {
                ci.AddClaim(new Claim("permission", "readOnly"));
            }
            else
            {
                ci.AddClaim(new Claim("permission", "write"));
    
            }
    
    
            var cp = new ClaimsPrincipal(ci);
    
            return Task.FromResult(cp);
        }
    }
    
  2. Add to Startup.cs(.net Core 2.0) :

        services.AddTransient<IClaimsTransformation, ClaimsTransformer>();
    
  3. Set your policy :

        services.AddAuthorization(options =>
        {
            options.AddPolicy("Readonly", policy =>
                              policy.RequireClaim("permission", "readOnly"));
    
            options.AddPolicy("Write", policy =>
                            policy.RequireClaim("permission", "write"));
        });
    
  4. Restrict access to a controller or action by requiring this policy:

        [Authorize(Policy = "Write")]
        public IActionResult Contact()
        {
            ViewData["Message"] = "Your contact page.";
    
            return View();
        }
    

If you have already add groups(write,readonly) in your AD and add the related users to group , you can also check the groups :

public static class Security
{
    public static bool IsInGroup(this ClaimsPrincipal User, string GroupName)
    {
        var groups = new List<string>();

        var wi = (WindowsIdentity)User.Identity;
        if (wi.Groups != null)
        {
            foreach (var group in wi.Groups)
            {
                try
                {
                    groups.Add(group.Translate(typeof(NTAccount)).ToString());
                }
                catch (Exception)
                {
                    // ignored
                }
            }
            return groups.Contains(GroupName);
        }
        return false;
    }
}

And use like :

 if (User.IsInGroup("GroupName"))
 {

 }
Share:
10,569
LCaraway
Author by

LCaraway

Updated on July 19, 2022

Comments

  • LCaraway
    LCaraway almost 2 years

    I have configured my web api to work with windows authentication. My goal is essentially to restrict certain actions in my controllers based on a users windows account. Some will be able to preform read actions while others will be able to preform actions that will write to the underlying database. I have found plenty of documentation on how to set up claims based authorization which is the route I think I need to go. What I have not found is how to set this up with windows auth. I think I am missing a middle step such as registering the windows auth as the identity provider?

    startup.cs

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
    
        services.AddAuthentication(IISDefaults.AuthenticationScheme);
    
        services.AddAuthorization(options =>
        {
            options.AddPolicy("readOnly", policy =>
                              policy.RequireClaim(`???????????????????????`));
            options.AddPolicy("write", policy =>
                              policy.RequireClaim(`???????????????????????`));
        });
    }
    

    Controller

    [Authorize(Policy = "ReadOnly")]
    public class MyController : Controller
    {
        public ActionResult SomeReadOnlyAction()
        {
            //Return data from database
        }
    
        [Authorize(Policy = "Write")]
        public ActionResult AWriteAction()
        {
            //Create/Update/Delete data from database
        }
    }
    

    I guess another way to ask this question is how do you configure or access claims/roles etc... with windows authentication.

  • LCaraway
    LCaraway over 5 years
    This is great! Where does the if(User.IsInGroup)... go? Does it get dropped in the ClaimsTransformer Class?
  • LCaraway
    LCaraway over 5 years
    Or would you use that as an alternative to the ClaimsTransformer?
  • Nan Yu
    Nan Yu over 5 years
    @LCaraway , it depends you , it can be in any class .
  • LCaraway
    LCaraway over 5 years
    When the group.Translate() is ran it returns an exception stating the trust relationship between the workstation and the primary domain has failed...
  • Nan Yu
    Nan Yu over 5 years
  • Stef Chäser
    Stef Chäser over 4 years
    Isn't the code faster if you translate the AD-GroupName to the SID representation. IdentityReference sidAdGroup = new NTAccount(GroupName).Translate(typeof(SecurityIdentifier)); then comparing it with the SIDs in wi.Groups (Instead of translate/cast all wi.Groups to NTAccount?)
  • Caesar Tex
    Caesar Tex almost 3 years
    Why not just use the built in User.IsInRole(AD Group Name) for option 2?
  • jondow
    jondow about 2 years
    Great answer, really helpful thanks