CORS not working ASP.Net MVC5 - c#

I am trying to block cross-domain access to my resources using CORS. I have tried WebApi.Cors and custom ActionFilter too. But I am still able to access the data from not allowed domains.
My ActionFilter code is below
public class AllowCrossSiteAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Credentials", "true");
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "https://example.com");
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Headers", "*");
base.OnActionExecuting(filterContext);
}
}
My Controller
[HttpGet]
[AllowCrossSite]
public ActionResult Index(string username)
{
//return json data
}
These headers are present in the response headers but why the request is not blocking from other domains, what am I doing wrong? Please help

Adding the response headers will not actually provide any sort of security. Regular cors implementations only add those response headers to inform the client about the cors rules that were applied.
Something on the server needs to compare your cors rules to the origin / method etc headers of the request, and then send back a 4XX response if they don't match up.
The NuGet package Microsoft.AspNet.WebApi.Cors allows you to do something like this:
[EnableCors(origins: "https://example.com")]
If you prefer to do your own custom implementation, you can see the source code for this attribute on github. That should give you a fairly good idea of what you need to do to make cors work by hand. It's simpler than it looks, really.

Related

Encrypt a web api request body content and decrypt on server

I am looking to create a simple security solution for which web API body content is not simply displayed to all whom wishes to see via intercepting the request with Fiddler or something. I am restricted in that I cannot use a SSL. I have already implemented a HMAC type of authentication and am wanting to take it a step further by creating a encrytpion of the body content on the client and sending that request to server were the server will then decrypt the body and forward to action as expected but decrypted. I used a filter for the server side HMAC and a delagatingHandler on the client.
I am not very familiar with working with http requests and do not fully understand how I might intercept all body content then encrypt it and put it back into the httpcontent.
Any ideas or help would be greatly appreciated.
In order to decrypt data before Model Mapping occurs in WEB API you can Hijack the AuthorizeAttribute because ActionFilterAttribute occurs after model mapping.
I know that the AuthorizeAttribute is meant for another reason , but hijacking it worked perfectly for me (I wanted to decompress zip content).
public class DecryptAttribute : AuthorizeAttribute
{
public override void OnAuthorization(HttpActionContext actionContext)
{
actionContext.Request.Content = DecryptContect(actionContext.Request.Content);
}
}
Then Decorate all your WebAPI controllers with this attribute.
In order to compress and embed to body i used a Delegating Handler
public class EncryptHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return base.SendAsync(request, cancellationToken).ContinueWith<HttpResponseMessage>((responseToCompleteTask) =>
{
HttpResponseMessage response = responseToCompleteTask.Result;
response.Content = new EncryptContent(response.Content);
return response;
},
TaskContinuationOptions.OnlyOnRanToCompletion);
}
}
Then just register it
GlobalConfiguration.Configuration.MessageHandlers.Add(new EncryptHandler());

Why is my DelegatingHandler firing for MVC requests?

I have a hybrid MVC/Web API project and I added a simple DelegatingHandler implementation to wrap the API responses. This works great, but the handler is also being invoked for requests to MVC controllers. My understanding is that DelegatingHandlers are only invoked for API routes.
I'm using OWIN and some attribute routes if that matters. The relevant code in Startup.cs is:
var config = new HttpConfiguration();
// ...
var debugging = HttpContext.Current == null || HttpContext.Current.IsDebuggingEnabled;
config.MessageHandlers.Add(new ApiResponseDelegatingHandler(debugging));
This causes both API and web requests to be wrapped and sent as JSON. Commenting it out resolves the problem but API requests are not wrapped. The error message on a web page is:
No HTTP resource was found that matches the request URI 'xxx'. No
route data was found for this request.
I tried forcing the order that routes are registered so that MVC routes are added before Web API but that didn't help.
This is easy to reproduce and I'm not sure if it's a bug or not.
Create a new web app using the ASP.NET MVC template
Install the Microsoft.AspNet.WebApi.Owin and
Microsoft.Owin.Host.SystemWeb NuGet packages
Move Web API startup from WebApiConfig.cs to a new Startup.cs file
Create a DelegatingHandler and add it to config.MessageHandlers in the Startup class
The DelegatingHandler will be invoked for MVC and API requests
I tried several combinations of initializing in Startup.cs and WebApiConfig.cs without success. If you;re not using attribute routing, the solution is to add the handler to the route. If you are, the only workaround I found was to examine the route in the handler and only wrap the API response if the route starts with "/api/".
public class WtfDelegatingHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
if (request.RequestUri.LocalPath.StartsWith("/api/", StringComparison.OrdinalIgnoreCase))
{
response = new HttpResponseMessage()
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent("I'm an API response")
};
}
return response;
}
}

C# Web API Request/Response Logging with OAuth

I am having a tough time figuring this out, but when I use a custom message handler in my Web API (created in VS2013) none of the /token request get processed through my handler.
What I'm trying to do is assist our support crew by implementing some logging to save request / response values for a few days. This will allow them to see the request and responses as raw as possible.
It's working, for everything except "/token" requests. We need to process the requests and responses for "/token" and "/authenticate" as a large percentage of our support calls end up being username and password issues.
I also need to do this in a message handler so I can isolate the code to message handlers.
Here is a sample handler I'm testing with in an isolated project. It's only in place ATM to debug/test this issue. I've also implemented a DelegatingHandler as well with the same results.
public class MyMessageProcessingHandler : MessageProcessingHandler {
protected override HttpRequestMessage ProcessRequest(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) {
Trace.WriteLine(string.Format("{0} {1}", request.Method, request.RequestUri));
return request;
}
protected override HttpResponseMessage ProcessResponse(HttpResponseMessage response, System.Threading.CancellationToken cancellationToken) {
Trace.WriteLine("response!");
return response;
}
}
in WebApiConfig.Register method I add the message handler to the config's message handler collection.
(I also tried Global.asax.cs is the Application_Start method)
GlobalConfiguration.Configuration.MessageHandlers.Add(new MyMessageProcessingHandler());
The order doesn't seem to matter - I've tried it as the first line of code, or the last.I've tried to Insert after the passive message handler is added by
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
GlobalConfiguration.Configuration.MessageHandlers.Insert(0, new MyMessageProcessingHandler());
Whenever I make an api/Values request or any api/Controller request the custom message handler handles the request just fine. However, when I post (or get) to /token (yes-properly) the custom message handler doesn't process the request.
I would like to know how to use a Message Handler to process the /token & /authenticate requests. I appreciate all your help!
Thanks,
-Rick
I went with a custom IHttpModule. It ended doing what I wanted in the way I wanted it by giving me direct access to the requests and allowing me to inspect them; even the authentication requests.
Thanks to all that looked at my issue.

Is it possible to decorate ASP.NET WEB API controller method with more than one Http attribute

I wonder if it's possible to decorate a WEB API controller method with more than one Http attribute as illustrated below and if possible is this the correct way to express that behaviour?
For example:
[HttpPut]
[HttpPost]
public HttpResponseMessage EditRegistration([FromUri] string id, [FromBody] Registration registration)
I tried this and the pipeline resolves the request correctly in both cases (PUT and POST request) but I wonder if this is because of the Http attributes or because WEB API uses some other way of mapping the request to the controller method.
There is more elegant way to express that:
[AcceptVerbs(HttpVerbs.Post | HttpVerbs.Put)]

servicestack REST API and CORS

Anyone know if the servicestack framework can be used to create CORS REST services?
I've been banging my haed against the WCF REST stuff for days now - utterly useless.
Thanks
Using the CorsFeature plugin
Enabling Global CORS support
We now have a CorsFeature which wraps CORS headers into the Plugin below to make it much easier to add CORS support to your ServiceStack services.
Commonly this is now all that's needed:
Plugins.Add(new CorsFeature());
Which uses the default values:
CorsFeature(allowedOrigins:"*",
allowedMethods:"GET, POST, PUT, DELETE, OPTIONS",
allowedHeaders:"Content-Type",
allowCredentials:false);
You can leave out any of the values matching the default. E.g. if you just wanted to restrict the allowed methods to just GET and POST requests, you can just do:
Plugins.Add(CorsFeature(allowedMethods:"GET, POST"));
Globally enable CORS for all OPTION requests
Once the CorsFeature (or manual Global Headers) is registered, you can optionally choose to enable CORS for all OPTION requests by adding a PreRequest filter to emit all registered Global Headers (i.e. the Headers in CorsFeature) and short-circuit all OPTIONS requests with:
this.PreRequestFilters.Add((httpReq, httpRes) => {
//Handles Request and closes Responses after emitting global HTTP Headers
if (httpReq.Method == "OPTIONS")
httpRes.EndRequest(); //add a 'using ServiceStack;'
});
Enabling CORS per-service support
Instead of using the plugin above, ServiceStack also allows you to enable CORS on a per-service basis by using [EnableCors] Response Filter attribute which has the same defaults as above. E.g. You can enable just GET, POST as above with:
[EnableCors(allowedMethods:"GET,POST")]
public class MyService : Service { ... }
Manually enabling CORS
The beauty of ServiceStack is that it's built on a highly flexible and simple core. We don't try to build strong-typed APIs over everything, as it's impossible to predict what new HTTP Headers / StatusCodes will exist in the future. So whilst we provide convenient behavior to accomplish common tasks, we also provide a flexible API that lets you configure any desired HTTP Output.
Setting Global HTTP Headers
This is how to globally enable Cross Origin Sharing in you AppHost config:
public override void Configure(Container container)
{
//Permit modern browsers (e.g. Firefox) to allow sending of any REST HTTP Method
base.SetConfig(new EndpointHostConfig
{
GlobalResponseHeaders = {
{ "Access-Control-Allow-Origin", "*" },
{ "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS" },
{ "Access-Control-Allow-Headers", "Content-Type" },
},
});
}
Returning Custom HTTP Headers in a service
These headers will get sent on every request, alternatively you can also enable it for specific web services, i.e. take the Hello World Web Service for example:
public class Hello {
public string Name { get; set; }
}
public class HelloResponse {
public string Result { get; set; }
}
public class HelloService : IService
{
public object Any(Hello request)
{
var dto = new HelloResponse { Result = "Hello, " + request.Name };
return new HttpResult(dto) {
Headers = {
{ "Access-Control-Allow-Origin", "*" },
{ "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS" }
{ "Access-Control-Allow-Headers", "Content-Type" }, }
};
}
}
The above is all the C# code you need to develop a web service which is then automatically wired up for you on all HTTP Verbs (GET, POST, etc) and built-in endpoints, i.e. JSON, XML, JSV, HTML, CSV, SOAP 1.1/1.2 - for free, without any config or friction required. Checkout the live example of the above web service.
In addition to the above endpoints each service is available to be called by JSONP (another popular way to enable cross-domain service calls in Ajax apps) where each service can be called via JSONP by simply adding the ?callback=cb parameter to the querystring, e.g:
http://www.servicestack.net/ServiceStack.Hello/servicestack/hello/world?callback=cb
This is another example of the flexibility and productivity wins of using ServiceStack where you're literally given friction-free flexibility and expressive freedom in your web service to literally return just about anything and it gets serialized as expected.
It's not only easier to use than WCF (with more features out-of-the-box) but it's also much faster where all its components are highly optimized for maximum performance.
Just FYI, as I had a hard time figuring out where the CORS plugin lived. Maybe I'm just thick.
It's in ServiceStack.ServiceInterface.Cors.

Resources