0

I am fairly new to .net and I am trying to create a restfull service where you can authenticate via OAuth2 to a service like facebook and also be able to login with a "normal account". The SPA template from VS2013 allowed me to do this quickly and easily and I am very happy with it.

Right now I am facing a different problem. I can't seem to find a way to separate access for these different types of logins. For example, I want to allow only users from the oauth authentication method to access X and users that authenticated in the "normal way" (also with a bearer token) to be able to see only Y.

I searched the web and it seems that I should be using the [Authorize] tag but I am not sure how to customize it nor differentiate between different logins. I found different methods of customizing the tag but none seem to be working and I keep stumbling into solutions that are out of date.

Can anyone help?

Thank you!


My final solution (thanks to 0leg)

Created an authorize tag for each authentication type:

public class AuthorizeExternalsOnly : AuthorizeAttribute
{
    protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
    {

        if (System.Web.HttpContext.Current.User.Identity.IsAuthenticated)
        {
            string externalClaim = "";
            try
            {
                externalClaim = (actionContext.ControllerContext.RequestContext.Principal.Identity as ClaimsIdentity).Claims.FirstOrDefault(x => x.Type == ClaimTypes.Authentication).Value;
            }
            catch (NullReferenceException)
            {
                Debug.WriteLine("no external claim found");
            }
            if (externalClaim != "")
            {
               return base.IsAuthorized(actionContext);
            }
            return false;
        }
        return false;
    }
}

At the account controler I then added the claim's at GetExternalLogin

oAuthIdentity.AddClaim(new Claim(ClaimTypes.Authentication, "External"));
(...)
identity.AddClaim(new Claim(ClaimTypes.Authentication, "External"));

right before each sign in.

  • When you say *access*, do you mean *authorization* ? Asp.net Identity comes with *IdentityRole* and other implementation. You can bifurcate third-party logins with native by Roles. – Palak Bhansali Apr 21 '14 at 15:55
  • Yes. In the project in question some routes should only be accessible to one login and others to the other. My problem is the user is essentially the same in both cases (the only thing different being the way they authenticated and got the access token). – The one with doubts Apr 21 '14 at 18:05
  • The solution will work. Although as a matter of reducing the amount of code, you could consolidate the two attributes into one and pass a parameter into it indicating what type of authorization you want. E.g. `[CustomAuthorizeAttribute("External")]` – 0leg Apr 22 '14 at 15:35

1 Answers1

1

You can create a Claim to define your user type (internal, facebook, etc). Then create a custom Authorize attribute to make the authorization decision.

Look at this, this and this links for some background info.

Code sample for custom Authorize attribute. HttpActionContext parameter lets you see what controller and action you called. It also lets you inspect the Claims collection for your user. Step through the code for the different login scenarios, you'll have different claims. Then you can decide whether your Controller.Action is authorized for a particular claim value.

protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
{
    ActionName = actionContext.ActionDescriptor.ActionName,
    ControllerName = actionContext.ControllerContext.ControllerDescriptor.ControllerName,
    Claims = (actionContext.RequestContext.Principal.Identity as ClaimsIdentity).Claims.ToList()
}
Community
  • 1
  • 1
0leg
  • 966
  • 5
  • 9
  • Hi 0leg, thank you for your help but I still have the same problems... At the moment I had overwritten the function "IsAuthorized" from the class AuthorizeAttribute instead of the funtcion "Authorize". Is this the right way to do it? And from here on I have no idea on how to verify which method is being used to authenticate. I am really clueless and there seems to be so little information on the topic... – The one with doubts Apr 21 '14 at 20:11
  • Yes, you are correct, I added a code sample showing how to override IsAuthorized. – 0leg Apr 22 '14 at 12:52
  • Thank you so much! I just added my solution to the original post. Probably not very optimized but does the job for now. – The one with doubts Apr 22 '14 at 14:50