6

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

noelicus
  • 14,468
  • 3
  • 92
  • 111
Rogala
  • 2,679
  • 25
  • 27
  • Are you able to share your implementation. Do you have any template checked into git? – Avi Feb 10 '17 at 17:09

2 Answers2

5

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.

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Rogala
  • 2,679
  • 25
  • 27
  • I used the code from the link you posted, would be great to see that added to your answer as well. – Nacht Jul 04 '17 at 01:39
-3

ADFS is the authentication/token service in Azure. to enable the Roles Based Authentication, you can use Azure RBAC (Role Based Access Controll) service to basically Augment the claims that you get back from the ADFS and add the roles that you get back from RBAC to the token, and use the same token in your API so lock down or secure the backend with that augmented token... here is the reference for RBAC:

http://azure.microsoft.com/en-in/documentation/articles/role-based-access-control-configure/

Aram
  • 5,537
  • 2
  • 30
  • 41
  • This is using Azure AD to manage users. I don't want to use Azure AD to manage the user because I want to use the ADFS (on-premise) to authenticate. Also, I am not trying to secure my API. I am trying to secure a new MVC application. – Rogala May 08 '15 at 21:13
  • Agreed with Rogala – Avi Feb 10 '17 at 17:03