Access Control Services via IHttpModule with mvc 4 and and web api, different security settings for site and service?

StackOverflow https://stackoverflow.com/questions/10859596

Question

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

Était-ce utile?

La solution

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.

Autres conseils

There are several questions in your post so not sure exactly what you are expecting. I will just answer your question about why the module is not working, as this seems to be the main one.

Yes the SWTModule will intercept all calls explaining why it fails when you access the MVC route. The module does not know anything about the Authorize attribute. If you want it to work, you should better go with Aliostad's advice and use a DelegatingHandler. If you want to "simply" make it work for now, you could check the execution path of the request in the module so that it only checks paths of your api (note that this will not work for public api methods as the module is not aware of the attributes)

Yes, using 2 separated projects would also work as the module will then only be applied to the project in which it is added.

Again these are quick-and-dirty path to get it working, which can be fine if this is a POC of using ACS. Otherwise, you will have to do some more homework. Dominick has written some really good articles on this subject. Check out the articles "ASP.NET WebAPI Security #1 to #4"

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top