Cookies and Same-Origin Policy concept

When an HTTP request is made to the backend application, a part of the answer can be stored in a cookie. This piece of information can be a unique session identifier or a token, identifying the user. This token is sent along with every request and the backend server remembers the user is logged. Therefore private data like account details if the app is a bank app can be sent to the frontend.

If the Same-Origin Policy does not exist, then another website could use the token to call the backend server and get private data:

This could definitely end badly as the other app does not necessarily have good intentions, as the call from the other app can be made without any user action or consent.

The Same-Origin Policy is enforced by modern browsers to make sure that web application can only make HTTP calls to API with the same origin:

If I’m webapp.com I can call webapp.com/api as the origins are the same, webapp.com

I can call as the origins are the same, If I’m anotherapp.com I cannot call webapp.com/api as the origins are not the same

The CORS, the practical way to ensure SOP in a microservices world

When you’ve got a monolithic app, like a Symfony app with Twig to render the views, you’re likely to have one domain for the frontend and the backend of the application.

Nevertheless, with modern frontend technologies as React or VueJS, we tend to decouple the frontend and the backend of the app, and therefore to have two domains. For instance:

app.myservice.com for the frontend

api.myservice.com for the backend

Thus when you want to make a legitimate request to api.myservice.com will being app.myservice, you encounter this kind of error:

Access to fetch https://some-url-here from https://some-other-url-here as being blocked by CORS policy.

Indeed, the origins are not matching. That’s the point where the CORS enter the game!

The CORS, Cross-Origin Resource Sharing, is a norm to actually by-pass the Same Origin Policy without decreasing the security.

If you want to make the previous request works, the HTTP response should contain a header which is :

Access-Control-Allow-Origin: app.myservice.com

With this header, you make the browser understand that the backend server knows the frontend origin, and it’s not likely a malicious call.

If you put “*” instead of the domain, you’re removing all security enforced by the Same-Origin Policy thus, it is not a good idea.

You also could have to add a header about the allowed methods:

Access-Control-Allow-Methods: GET, HEAD, OPTIONS, POST

Practical examples

Configure CORS for a Symfony application

If you’re configuring a Symfony application, use the Nelmio Bundle. Register the bundles in the Kernel and then create a nelmio_cors.yaml file in the config folder and add the following CORS configuration:

Configure CORS for a Django application

If you’re configuring a Django application, use the Django Cors headers package. Add the Corsheaders to the INSTALLED_APPS array and corsheaders.middleware.CorsMiddleware to the MIDDLEWARE array in your base.py file.

Then add the array CORS_ORIGIN_WHITELIST as an env variable, for instance: