LaravelLaravel & VueJsVueJs

★ Handling CORS in a Laravel application



Uptime and SSL certificate monitoring doesn’t have to be boring, confusing or expensive. Together with my buddy Mattias Geniar I’m currently building Oh Dear: a webapp to keep an eye on the health of your websites. Sign up here to get beta access.
(sponsored link)
Recently we released laravel-cors. This package can add the necessary CORS headers of your Laravel app. In this post I’d like to give a quick explanation of what CORS is and how you can use the package.

What is CORS #

Image that all JavaScript code for domain X running in a browser would be able to make HTTP requests to a domain Y. Malicious code on domain X would be able to interact with site Y without you knowing. In most circumstances you don’t want this. Luckily all major browsers only allow sites to make requests against their own domain. They don’t allow JavaScript code to make request against a sites on different domains. This is called the same-origin policy.

But there are some scenarios where you do want to allow that behaviour. Think of an API running on domain X that you want to consume via JavaScript running on domain Y. CORS stands for cross-origin resource sharing. It’s a standardized way to legitimately poke some holes in the same-origin policy.

★ READ ALSO ★  Pro REST API Development with Node.js

Simple requests #

When JavaScript running on domain X performs a HEAD GET or certain POST request (with application/x-www-form-urlencoded, multipart/form-data or text/plain) to domain Y the browser will add an Origin header. The application running on domain Y can use this header to check if the request is permitted. If the server responds with a header Access-Control-Allow-Origin containing the domain X then the browser will conclude that request was allowed. If the server didn’t do that most browsers won’t allow the JS on domain X to perform any requests towards domain Y.

All other requests #

All requests covered by the previous section will probably only be used to retrieve some data. All other ones such as certain POST requests, PUT, PATCH, DELETE will probably modify existing data on the server. For those kinds of request the browser will send a preflight request before doing the actual request.

This preflight request uses the OPTIONS verb. The browser will also send along the Origin header mentioned in the previous section. The server should return a response with the Access-Control-Allow-Origin, Access-Control-Allow-Methods and Access-Control-Max-Age headers set. The Access-Control-Allow-Methods contains the HTTP verbs that are allowed. The Access-Control-Max-Age contains the time in seconds that no new preflight request should be sent.

Using spatie/laravel-cors #

Our spatie/laravel-cors package can handle verifying and setting all required headers for you. The package can be installed via Composer

composer require spatie/laravel-cors

After that you must register the Cors middleware

★ READ ALSO ★  SICA 402.5mm Metal Poker Guard Card Protector Coin Chip Color Gold Plated With Round Plastic Case
// app/Http/Kernel.php

protected $middleware = [
    ...
    SpatieCorsCors::class
];

Your application will now allow cross origin request coming from all domains. You probably want to publish the config file and set the allow_origins key to all domains you will allow requests from. Here’s the default content of that config file.

return [
    /*
     * A cors profile determines which orgins, methods, headers are allowed for
     * a given requests. The `DefaultProfile` reads its configuration from this
     * config file.
     *
     * You can easily create your own cors profile.
     * More info: https://github.com/spatie/laravel-cors/#creating-your-own-cors-profile
     */
    'cors_profile' => SpatieCorsCorsProfileDefaultProfile::class,

    /*
     * This configuration is used by `DefaultProfile`.
     */
    'default_profile' => [

        'allow_origins' => [
            '*',
        ],

        'allow_methods' => [
            'POST',
            'GET',
            'OPTIONS',
            'PUT',
            'PATCH',
            'DELETE',
        ],

        'allow_headers' => [
            'Content-Type',
            'X-Auth-Token',
            'Origin',
            'Authorization',
        ],

        /*
         * Preflight request will respond with value for the max age header.
         */
        'max_age' => 60 * 60 * 24,
    ],
];

Using CORS profiles #

Imagine you want to specify allowed origins based on the user that is currently logged in. In that case the DefaultProfile which just reads the config file won’t cut it. Fortunately it’s very easy to write your own CORS profile. A valid CORS profile is any class that extends SpatieCorsDefaultProfile.

Here’s a quick example where it is assumed that you’ve already added a allowed_domains column on your user model:

namespace AppServicesCors;

use SpatieCorsDefaultProfile;

class UserBasedCorsProfile extends DefaultProfile;
{
    public function allowOrigins(): array
    {
        return Auth::user()->allowed_domains;
    }
}

Don’t forget to register your profile in the config file.

// config/cors.php

 ...
 'cors_profile' => AppServicesCorsUserBasedCorsProfile::class,
 ...

In the example above we’ve overwritten the allowOrigins method, but of course you may choose to override any of the methods present in DefaultProfile.

In closing #

It might appear that this whole CORS business is something that aims to protect your server, but that is not the case. It’s primary purpose is to protect the user of the browser by not making any requests to unwanted other domains. Don’t see CORS as a mechanism to protect your server.

★ READ ALSO ★  Looping an image with Vue Perfectlooper

If you want to know more about our laravel-cors package, go check it out on GitHub. You could also opt to use Barry vd. Heuvel’s CORS package. Our package is a modern rewrite of the basic features of Barry’s excellent one. We created our own solution because we needed our configuration to be very flexible.

Be sure to also check out the packages our team has previously made. There’s probably something there that could be of use in your next project.

http://platform.twitter.com/widgets.js




Source link

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Close