Instantly share code, notes, and snippets.
Created
April 2, 2013 15:15
-
Star
(2)
2
You must be signed in to star a gist -
Fork
(2)
2
You must be signed in to fork a gist
-
Save arthernan/5293014 to your computer and use it in GitHub Desktop.
Improved AuthorizeAttribute for MicroSoft MVC4 WebAPI
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Net; | |
using System.Net.Http; | |
using System.Security.Principal; | |
using System.Threading; | |
using System.Web; | |
using System.Web.Http; | |
using System.Web.Http.Controllers; | |
namespace Infrastructure | |
{ | |
public class NewAuthorize : AuthorizeAttribute | |
{ | |
private static readonly string[] _emptyArray = new string[0]; | |
private readonly object _typeId = new object(); | |
private string _roles; | |
private string[] _rolesSplit = _emptyArray; | |
private string _users; | |
private string[] _usersSplit = _emptyArray; | |
new public string Roles | |
{ | |
get { return _roles ?? String.Empty; } | |
set | |
{ | |
_roles = value; | |
_rolesSplit = SplitString(value); | |
} | |
} | |
new public string Users | |
{ | |
get { return _users ?? String.Empty; } | |
set | |
{ | |
_users = value; | |
_usersSplit = SplitString(value); | |
} | |
} | |
protected override bool IsAuthorized(HttpActionContext actionContext) | |
{ | |
if (actionContext == null) | |
{ | |
throw new ArgumentNullException("actionContext"); | |
} | |
IPrincipal user = Thread.CurrentPrincipal; | |
if (user == null || !user.Identity.IsAuthenticated) | |
{ | |
return false; | |
} | |
return true; | |
} | |
protected bool IsAllowed(HttpActionContext actionContext) | |
{ | |
if (actionContext == null) | |
{ | |
throw new ArgumentNullException("actionContext"); | |
} | |
IPrincipal user = Thread.CurrentPrincipal; | |
if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase)) | |
{ | |
return false; | |
} | |
if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole)) | |
{ | |
return false; | |
} | |
return true; | |
} | |
public override void OnAuthorization(HttpActionContext actionContext) | |
{ | |
if (actionContext == null) | |
{ | |
throw new ArgumentNullException("actionContext"); | |
} | |
if (SkipAuthorization(actionContext)) | |
{ | |
return; | |
} | |
if (!IsAuthorized(actionContext)) | |
{ | |
HandleUnauthorizedRequest(actionContext); | |
} | |
if (!IsAllowed(actionContext)) | |
{ | |
HandleForbiddenRequest(actionContext); | |
} | |
} | |
protected override void HandleUnauthorizedRequest(HttpActionContext actionContext) | |
{ | |
if (actionContext == null) | |
{ | |
throw new ArgumentNullException("actionContext"); | |
} | |
HttpResponseMessage result = new HttpResponseMessage() | |
{ | |
StatusCode = HttpStatusCode.Unauthorized, | |
RequestMessage = actionContext.Request | |
}; | |
actionContext.Response = result; | |
} | |
protected void HandleForbiddenRequest(HttpActionContext actionContext) | |
{ | |
if (actionContext == null) | |
{ | |
throw new ArgumentNullException("actionContext"); | |
} | |
HttpResponseMessage result = new HttpResponseMessage() | |
{ | |
StatusCode = HttpStatusCode.Forbidden, | |
RequestMessage = actionContext.Request | |
}; | |
actionContext.Response = result; | |
} | |
private static bool SkipAuthorization(HttpActionContext actionContext) | |
{ | |
if (actionContext == null) | |
{ | |
throw new ArgumentNullException("actionContext"); | |
} | |
return actionContext.ActionDescriptor.GetCustomAttributes().Any() | |
|| actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes().Any(); | |
} | |
internal static string[] SplitString(string original) | |
{ | |
if (String.IsNullOrEmpty(original)) | |
{ | |
return _emptyArray; | |
} | |
var split = from piece in original.Split(',') | |
let trimmed = piece.Trim() | |
where !String.IsNullOrEmpty(trimmed) | |
select trimmed; | |
return split.ToArray(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Very helpful! Amazed this behavior wasn't in Microsoft's implementation. Only thing I had to tweak to get this to work from a WebAPI controller was:
to