Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating Custom AuthorizeAttribute in Web API (.Net Framework)

I'm using OAuth2.0 Owin (password grant) in my WebAPI.My initial token Response is like below

{
    "access_token": "_ramSlQYasdsRTWEWew.....................",
    "token_type": "bearer",
    "expires_in": 17999,
    "permissions": {
        "user": [
            "Add",
            "Update",
            "Delete"
        ],
        "Product": [
            "Read",
            "Create"
        ]
    }
}

I've customized the response by creating a new Key called permissions which hold the privileges for the corresponding user.

From here I need to validate each Request from my Resource server,by checking whether the user has enough permissions to call the API using Authorize Attribute.

I found a similar example from here where it deals with Dot net Core, which is not suitable for my case.

The difficult part is that the permission JSON Key is itself making a complex with ArrayList

[CustomAuthorize(PermissionItem.Product, PermissionAction.Read)]
    public async Task<IActionResult> Index()
    {
        return View(Index);
    }

public class CustomAuthorize : AuthorizeAttribute {
    public AuthorizeAttribute (PermissionItem item, PermissionAction action) {
        //Need to initalize the Permission Enums
    }
    public override void OnAuthorization (HttpActionContext actionContext) {
        //Code to get the value from Permissions ArrayList and compare it with the Enum values
    }
}

The above is the idea I'm having. But due to the complexity of the Permissions Key and Enum comparison I'm couldn't able to move forward.

Also, there is a question like If the permission for User is Add as well as Update means I need to create two Attribute conditions before my Controller.

Like

[CustomAuthorize(PermissionItem.User, PermissionAction.Add)]
[CustomAuthorize(PermissionItem.User, PermissionAction.Update)]

Which leads to adding more lines of Attributes. So Is there is any way to make it as in a single Conditions with | separated?

[CustomAuthorize(PermissionItem.User, PermissionAction.Update|PermissionAction.Add)]
like image 954
Jayendran Avatar asked Jul 28 '18 05:07

Jayendran


People also ask

How do I create a custom authentication filter in Web API?

To create a custom authentication filter in ASP.NET MVC, we need to create a class by implementing the IAuthenticationFilter Interface. This IAuthenticationFilter interface has 2 methods. Open Visual Studio 2015 or an editor of your choice and create a new project.

How do I provide authentication in Web API?

Web API assumes that authentication happens in the host. For web-hosting, the host is IIS, which uses HTTP modules for authentication. You can configure your project to use any of the authentication modules built in to IIS or ASP.NET, or write your own HTTP module to perform custom authentication.

How do I use authorization filter in Web API?

Web API uses authorization filters to implement authorization. The Authorization filters run before the controller action. If the request is not authorized, the filter returns an error response, and the action is not invoked. Web API provides a built-in authorization filter, Authorize Attribute.


1 Answers

Why don't you allow your CustomAuthorize constructor to have multiple Permission actions.

public class CustomAuthorize : AuthorizeAttribute
{
    private readonly PermissionAction[] permissionActions;

    public CustomAuthorize(PermissionItem item, params PermissionAction[] permissionActions)
    {
        this.permissionActions = permissionActions;
    }

    public override void OnAuthorization(HttpActionContext actionContext)
    {
        var currentIdentity = System.Threading.Thread.CurrentPrincipal.Identity;
        if (!currentIdentity.IsAuthenticated) {
            // redirect to access denied page
        }

        var userName = currentIdentity.Name;
        // step 1 : retrieve user object

        // step 2 : retrieve user permissions

        // step 3 : match user permission(s) agains class/method's required premissions

        // step 4 : continue/redirect to access denied page
    }
}

And you'll annotate your class with: [CustomAuthorize(PermissionItem.User, PermissionAction.Update, PermissionAction.Add)]

I'm not sure, what does OP want to achieve here. If you are relying on HTTP request to provide access rights then that is A BIG SECURITY HOLE. On each request you should retrieve user's access right information from the database and then match is against the required permission of the class/method.

As a rule of thumb you should not rely on request object to tell you what are the permissions that current user have. You should retrieve them from the datastore.

My Implementation of CustomAttribute

public class CustomAuthorize : System.Web.Http.AuthorizeAttribute
{
    private readonly PermissionAction[] permissionActions;

    public CustomAuthorize(PermissionItem item, params PermissionAction[] permissionActions)
    {
        this.permissionActions = permissionActions;
    }

    protected override Boolean IsAuthorized(HttpActionContext actionContext)
    {
        var currentIdentity = actionContext.RequestContext.Principal.Identity;
        if (!currentIdentity.IsAuthenticated)
            return false;

        var userName = currentIdentity.Name;
        using (var context = new DataContext())
        {
            var userStore = new UserStore<AppUser>(context);
            var userManager = new UserManager<AppUser>(userStore);
            var user = userManager.FindByName(userName);

            if (user == null)
                return false;

            foreach (var role in permissionActions)
                if (!userManager.IsInRole(user.Id, Convert.ToString(role)))
                    return false;

            return true;
        }
    }
}
like image 106
Dipen Shah Avatar answered Oct 04 '22 14:10

Dipen Shah