10

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.

4
  • Do you have a call to services.AddAuthentication(...)? Commented Nov 28, 2018 at 17:06
  • No I do not.... Commented Nov 28, 2018 at 17:08
  • 1
    That's what may be missing. See link: learn.microsoft.com/en-us/aspnet/core/security/authentication/… Commented Nov 28, 2018 at 17:09
  • You are absolutely right. I have added that in and updated the code above. I guess my next question is how do i access the credentials to then build a policy around it so that i can use specific authorization attributes on my controller actions? Commented Nov 28, 2018 at 17:13

1 Answer 1

12

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"))
 {

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

7 Comments

This is great! Where does the if(User.IsInGroup)... go? Does it get dropped in the ClaimsTransformer Class?
Or would you use that as an alternative to the ClaimsTransformer?
@LCaraway , it depends you , it can be in any class .
When the group.Translate() is ran it returns an exception stating the trust relationship between the workstation and the primary domain has failed...
|

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.