Restricting access to a server using CORS

Since I’ve already created an endpoint in my API and an Angular service working with a mock, it’s not rocket science to bind them together, is it? Actually, there’s a little trick… When I tested the endpoint using Postman, everything was fine – breakpoints in the API were hit, a response was sent and displayed correctly. But when I modified the service to talk to the API, breakpoints were hit, a response was sent, but on the client side I couldn’t get its actual content, no matter whether the request was valid. I tried a few solutions with Promises (in simple words: a JavaScript wrapper for asynchronous actions which can return some particular result data or an error and be easily chained) and Observables (something similar to promises and the Observer pattern). In all cases the error path was executed and the response contained a weird object:

{
    "_body": {
        "isTrusted": true
    },
    "status": 0,
    "ok": false,
    "statusText": "",
    "headers": {},
    "type": 3,
    "url": null
}

I was logging responses to the console, so I missed an important message appearing there as well for a long time…

XMLHttpRequest cannot load http://localhost:27365/api/categories/5904c5fa2e529525cfcc81a9/advertisements. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost:3000 ‘ is therefore not allowed access.

What the heck if Postman could do it? The answer is CORS – Cross-Origin Resource Sharing, a security mechanism which defines what requests are allowed to access resources. As you can see in the message, a client and a server are hosted on different ports, so technically speaking they have different origin. This is why requests were actually blocked on the server side, even though breakpoints were hit there and the correct data were returned… The solution was to turn on CORS on the server side. There is an easy introduction here which explains the topic and describes what I’ve done. To cut a long story short, it only requires installing a Nuget package called Microsoft.AspNet.WebApi.Cors and adding the following in WebApiConfig.Register(), in the same place where routing is set:

var cors = new EnableCorsAttribute("http://localhost:3000", "*", "*");
config.EnableCors(cors);

This is my case where I allow any requests from that particular URL. Alternatively we can limit them to some headers or methods (the other parameters above), controllers or actions (then place an EnableCors attribute on them instead).
And here is a little explanation why Postman could pass. I’m not sure if it’s fully relevant because I use a desktop version, but I guess it works in a similar way.

By the way, by fixing this problem I’ve finally closed another GitHub issue. 🙂

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s