February 18 2014

ASP.NET Web API 2 - Enum Authorize Attribute

This post shows you how to create a custom authorization attribute which allows you to pass in a list of enums as parameters to restrict access by role. I'm using this attribute on the controllers of a RESTful Web API built with ASP.NET WEB API 2.

The stock standard AuthorizeAttribute that ships with .NET only allows you to pass in a list of roles as a comma separated string to restrict access like this:

[Authorize(Roles = "Admin, User, etc")]

I wanted instead to use a strongly typed approach like passing in a list of enum values like this:

[AuthorizeRoles(Role.Admin, Role.User)]

To do this you need to create a custom authorization attribute which turns out to be surprisingly simple, this is all you have to do:

public class AuthorizeRolesAttribute : AuthorizeAttribute
{
    private Role[] _roles;
    public AuthorizeRolesAttribute(params Role[] roles)
    {
        _roles = roles;
    }

    protected override bool IsAuthorized(HttpActionContext actionContext)
    {
        return _roles.Contains(Globals.CurrentUser.Role);
    }
}

This is the Role enum, you can any roles you like here, Admin and User are just examples:

public enum Role {
	Admin,
	User
}

I'm checking the roles against the Globals.CurrentUser object which I set during request authentication using a slightly modified version of the custom HTTP module posted by Mike Wasson on Basic Authentication.

Here's my modified version of the AuthenticateUser method of the BasicAuthHttpModule:

private static bool AuthenticateUser(string credentials)
{
    var encoding = Encoding.GetEncoding("iso-8859-1");
    credentials = encoding.GetString(Convert.FromBase64String(credentials));

    var credentialsArray = credentials.Split(':');
    string userCode = credentialsArray[0];
    string password = credentialsArray[1];

    var user = _userService.GetByUsernameAndPassword(username, password);
    if (user == null)
        return false;

    var identity = new GenericIdentity(user.Username);
    SetPrincipal(new GenericPrincipal(identity, new[] { user.Role.ToString() }));
    Globals.CurrentUser = user;

    return true;
}

Sponsored by