I am building an mvc 4 web api project on Azure. Requests to this API go through the route:
routes.MapHttpRoute(
name: "DefaultApi", // Route name
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
On the same domain and different route, I have an mvc web site set up:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
The mvc web site is just an HTML and Javascript page that interacts with Access Control Services to get a token, which it then passes to the service to get data via jQuery ajax.
To implement the security of services (validate the token sent to the API), I am using the SWTModule and TokenValidator classes as described on this article, along with a call in my MVC 4 web application project Web.Config system.webserver attribute:
<modules runAllManagedModulesForAllRequests="true">
<add name="SWTModule" type="SecurityModule.SWTModule, SecurityModule" />
</modules>
Even though I have not marked the MVC Controller methods with [Authorize], loading the default web page results in this error:
Server Error in '/' Application.
unauthorized
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ApplicationException: unauthorized
Source Error:
Line 43: Line 44: // check that it starts with 'WRAP' Line 45: if (!headerValue.StartsWith("WRAP ")) Line 46:
{ Line 47: throw new ApplicationException("unauthorized");Source File: D:\Dev\VisualStudio2010\Projects\myServices\Azure\myDataInterfaces\SecurityModule\SWTModule.cs Line: 45
Stack Trace:
[ApplicationException: unauthorized]
SecurityModule.SWTModule.context_BeginRequest(Object sender, EventArgs e) in D:\Dev\VisualStudio2010\Projects\myServices\Azure\myDataInterfaces\SecurityModule\SWTModule.cs:45 System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +80 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +270
It seems to me that, even though I have not marked my Controller methods with [Authorize], they are being rejected because my SWT token validation is firing for every response, presumably because it's called earlier in the web stack, because of the inclusion in the Web.Config attribute?
Can someone point me in the right direction on how to make this work? I want to make it so that the default web page (Home controller Index method) shows my login screen, which then redirects to a main page. That main page should return unauthorized if the user has not logged in with one of the available ACS identity providers. Similarly, I want to leave some of my Web API ApiController methods public and require authorization for others.
Currently, I have both the MVC app and the Web API service routed via a single Global.asax file within a single web application project in a single web role solution in Visual Studio. I am wondering if the way to fix this is to separate the HTML MVC site and the Web API into different web application projects under the same Web Role solution? That still would not give me the means to assign authorization requirements for some of controller methods, just give me a different place for routing Controllers and ApiControllers.
I feel like I'm close but maybe missing something big, but I don't seem to find it online. Would someone straighten me out?
Thanks, Alex
First of all, it looks to me that your authorization mechanism throws exception. Normally you would return a request with status 403 "Forbidden".
The right way to do this in Web API is to create
DelegatingHandler
rather than a module.Have a look at Dominick Baier's ThinkTecture.
Also shameless plug.