As the title says, it is currently not possible to override the AuthorizeAttribute set on Controllers with an AuthorizeAttribute set on Actions.
While this is in itself not a bug, it is quite an inconvenience. The attribute would be easier to use if you were able to set it on an Action as well as on the Controller. This would pretty much result in a similar usage process as with the AllowAnonymousAttribute, which can in fact override the Controller level AuthorizeAttribute.
Pseudo-code:
```
[Authorize(Roles = "Administrator")]
public class MyController : ApiController
{
//A hundred (exaggerating here) functions that are limited to Administrators thanks to the AuthorizeAttibute on the Controller.
[Authorize(Roles = "User,Administrator")] //FEATURE: Override only this single action to allow users as well. As it stands now, this is never reached due to the AuthorizeAttribute on the Controller.
public MyObject MyMoreAccesibleAction()
{
}
[AllowAnonymous] //AllowAnonymous can already override the AuthorizeAttribute
public MyObejct MyPublicMethod()
{
}
}
```
Comments: I tried using the same package version (5.0.0-rtm-130619) from our nightly feed, and it was working for me. Full repro source and request/response logs are below.
Can you confirm if this sample works for you?
Thanks,
David
__Source Code__
using System;
using System.Security.Principal;
using System.ServiceModel;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using System.Web.Http.SelfHost;
class Program
{
static void Main()
{
using (var config = new HttpSelfHostConfiguration("http://localhost:12345/"))
{
config.HostNameComparisonMode = HostNameComparisonMode.Exact;
config.Filters.Add(new SchemeAuthenticationFilter());
config.Routes.MapHttpRoute("Rpc", "{controller}/{action}");
using (HttpSelfHostServer server = new HttpSelfHostServer(config))
{
server.OpenAsync().Wait();
Console.WriteLine("Press ENTER to exit . . .");
while (Console.ReadKey().Key != ConsoleKey.Enter) ;
server.CloseAsync().Wait();
}
}
}
}
public class SchemeAuthenticationFilter : IAuthenticationFilter
{
public Task<IAuthenticationResult> AuthenticateAsync(HttpAuthenticationContext context,
CancellationToken cancellationToken)
{
IAuthenticationResult result;
if (context.Request.Headers.Authorization != null)
{
result = new SucceededAuthenticationResult(new GenericPrincipal(new GenericIdentity("User"),
new string[] { context.Request.Headers.Authorization.Scheme }));
}
else
{
result = null;
}
return Task.FromResult(result);
}
public Task<IHttpActionResult> ChallengeAsync(HttpActionContext context, IHttpActionResult innerResult,
CancellationToken cancellationToken)
{
return Task.FromResult(innerResult);
}
public bool AllowMultiple
{
get { return false; }
}
}
public class MyObject
{
public string Property { get; set; }
}
[Authorize(Roles = "Administrator")]
public class MyController : ApiController
{
public MyObject MyNormalAction()
{
return new MyObject { Property = "AdminOnly" };
}
[OverrideAuthorization]
[Authorize(Roles = "User,Administrator")]
public MyObject MyMoreAccesibleAction()
{
return new MyObject { Property = "UserOrAdmin" };
}
[AllowAnonymous]
public MyObject MyPublicMethod()
{
return new MyObject { Property = "Anonymous" };
}
}
__Test Results__
POST http://localhost:12345/My/MyNormalAction HTTP/1.1
Host: localhost:12345
Content-Length: 0
HTTP/1.1 401 Unauthorized
Content-Length: 61
Content-Type: application/json; charset=utf-8
Server: Microsoft-HTTPAPI/2.0
Date: Fri, 21 Jun 2013 16:22:54 GMT
{"Message":"Authorization has been denied for this request."}
------------------------------------------------------------------
POST http://localhost:12345/My/MyNormalAction HTTP/1.1
Host: localhost:12345
Content-Length: 0
Authorization: User
HTTP/1.1 401 Unauthorized
Content-Length: 61
Content-Type: application/json; charset=utf-8
Server: Microsoft-HTTPAPI/2.0
Date: Fri, 21 Jun 2013 16:22:59 GMT
{"Message":"Authorization has been denied for this request."}
------------------------------------------------------------------
POST http://localhost:12345/My/MyNormalAction HTTP/1.1
Host: localhost:12345
Content-Length: 0
Authorization: Administrator
HTTP/1.1 200 OK
Content-Length: 24
Content-Type: application/json; charset=utf-8
Server: Microsoft-HTTPAPI/2.0
Date: Fri, 21 Jun 2013 16:23:04 GMT
{"Property":"AdminOnly"}
------------------------------------------------------------------
POST http://localhost:12345/My/MyMoreAccesibleAction HTTP/1.1
Host: localhost:12345
Content-Length: 0
HTTP/1.1 401 Unauthorized
Content-Length: 61
Content-Type: application/json; charset=utf-8
Server: Microsoft-HTTPAPI/2.0
Date: Fri, 21 Jun 2013 16:23:17 GMT
{"Message":"Authorization has been denied for this request."}
------------------------------------------------------------------
POST http://localhost:12345/My/MyMoreAccesibleAction HTTP/1.1
Host: localhost:12345
Content-Length: 0
Authorization: User
HTTP/1.1 200 OK
Content-Length: 26
Content-Type: application/json; charset=utf-8
Server: Microsoft-HTTPAPI/2.0
Date: Fri, 21 Jun 2013 16:23:22 GMT
{"Property":"UserOrAdmin"}
------------------------------------------------------------------
POST http://localhost:12345/My/MyMoreAccesibleAction HTTP/1.1
Host: localhost:12345
Content-Length: 0
Authorization: Administrator
HTTP/1.1 200 OK
Content-Length: 26
Content-Type: application/json; charset=utf-8
Server: Microsoft-HTTPAPI/2.0
Date: Fri, 21 Jun 2013 16:23:27 GMT
{"Property":"UserOrAdmin"}
------------------------------------------------------------------
POST http://localhost:12345/My/MyPublicMethod HTTP/1.1
Host: localhost:12345
Content-Length: 0
HTTP/1.1 200 OK
Content-Length: 24
Content-Type: application/json; charset=utf-8
Server: Microsoft-HTTPAPI/2.0
Date: Fri, 21 Jun 2013 16:23:41 GMT
{"Property":"Anonymous"}
------------------------------------------------------------------
POST http://localhost:12345/My/MyPublicMethod HTTP/1.1
Host: localhost:12345
Content-Length: 0
Authorization: User
HTTP/1.1 200 OK
Content-Length: 24
Content-Type: application/json; charset=utf-8
Server: Microsoft-HTTPAPI/2.0
Date: Fri, 21 Jun 2013 16:23:46 GMT
{"Property":"Anonymous"}
------------------------------------------------------------------
POST http://localhost:12345/My/MyPublicMethod HTTP/1.1
Host: localhost:12345
Content-Length: 0
Authorization: Administrator
HTTP/1.1 200 OK
Content-Length: 24
Content-Type: application/json; charset=utf-8
Server: Microsoft-HTTPAPI/2.0
Date: Fri, 21 Jun 2013 16:23:50 GMT
{"Property":"Anonymous"}
------------------------------------------------------------------