Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add roles to ADFS IPrincipal

I have been looking for answer to this question for a few days now, but I have not found any success. I would post the links, but it would probably take up the entire page.

So here is what I have...

I have an MVC application, which uses the WC-Federation protocol. I have been able to configure the application, so that it authenticates the users, and returns the claims from ADFS. This works perfect. I can also extract all the claims with no issues. But I am doing this within one of the actions in the controller.

And here is what I want to do...

I want to use ADFS to authenticate the user, but I want to use my own internal roles to authorize the user to have access to specific controllers (e.g. [Authorize(Roles = "CoolRole")]). I want to be able to do this, because I already have a Web API that uses OAuth 2.0, with a backend SQL Server database to manage users and roles (internal and external user.) I now want a secure portal that will allow internal users to access the data with a single-sign-on experience. Looking at the Controller model, I noticed there are some properties associated with the authentication process (OnAuthentication, OnAuthenticationChallenge) and one for the authorization process (OnAuthorization.)

I don't necessarily need the code, but I feel like I've hit a brick all, and I need to be pointed in the right direction.

UPDATE

I tried this:

protected override void OnAuthorization(
       System.Web.Mvc.AuthorizationContext filterContext)
{
    //Private class to create a new IPrincipal based on my AppUserMgr
    var user =  _setCurrentUser(
                  (ClaimsIdentity)filterContext.HttpContext.User.Identity);
    filterContext.HttpContext.User = user;

    base.OnAuthorization(filterContext);
}

This returned a 401 (Unauthorized) response.

and...

protected override void OnAuthentication(
    System.Web.Mvc.Filters.AuthenticationContext filterContext)
{
    //Private class to create a new IPrincipal based on my AppUserMgr
    var user =  _setCurrentUser(
                  (ClaimsIdentity)filterContext.HttpContext.User.Identity);
    filterContext.Principal = user;

    base.OnAuthorization(filterContext);
}

This just calls the STS numerous times, before it fails. I even tried swapping after the assignment to after the base is called in both. No luck.

Prior to the previous ones, I also tried to add an AuthorizeFilter to the control, but that didn't help:

http://pratapreddypilaka.blogspot.in/2012/03/custom-filters-in-mvc-authorization.html

like image 958
Rogala Avatar asked May 08 '15 19:05

Rogala


1 Answers

I found this link: http://brockallen.com/2013/01/17/adding-custom-roles-to-windows-roles-in-asp-net-using-claims/

From there, I guessed my way through

Here is the basics of what I did:

I ended up overriding the OnAuthentication method of the Controller, but still made sure to call the base. I did this from within an extended class. Here is the concept:

public class AdfsController : Controller
{
    //Some code for adding the AppUserManager (used Unity)
    protected override void OnAuthentication(
            System.Web.Mvc.Filters.AuthenticationContext filterContext)
    {
        base.OnAuthentication(filterContext);
        //Private method to set the Principal
        _setCurrentUser(filterContext.Principal);
    }

    private void _setCurrentUser(IPrincipal principal)
    {
        //Put code to find to use your ApplicationUserManager or 
        //dbContext.  roles is a string array

        foreach(var role in roles)
        {
            ((ClaimsIdentity)((ClaimsPrincipal)principal).Identity)
                .AddClaim(new Claim(ClaimTypes.Role, role));
        }
    }
}

In the Controller, you can now add the follow:

public class HomeController : AdfsController
{
    //I used a magic string for demo, but store these in my globals class
    [Authorize(Roles = "CoolRole")]
    public ActionResult Index()
    {
        return View();
    }
}

I tested this by checking a role assigned to the current user, and that worked! Then I changed the role to something like "reject", which the user was not assigned; and I received a 401 Unauthorized.

like image 85
Rogala Avatar answered Nov 02 '22 22:11

Rogala