Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 84

Handling CORS in Laravel for React Apps

Recommended resources

Hello! Welcome to the final module of our course, where we'll connect all the dots and build a full-stack e-commerce application.

In the previous modules, you built a sophisticated React front-end, complete with routing, state management, and a fully functional shopping cart. Your application is currently a standalone Single-Page Application (SPA). Now, it's time to bring your Laravel expertise into the picture and transform it into a dynamic, data-driven app powered by a real backend.

This lesson tackles the very first and most crucial step in that integration: configuring your Laravel backend to handle Cross-Origin Resource Sharing (CORS). We will explore why this is necessary and walk through the exact steps to allow your React app (running on one "origin") to securely communicate with your Laravel API (running on another).

1. Understanding the "Why": Same-Origin Policy and CORS

Before we touch any code, it's essential to understand the security principle that makes this configuration necessary. Browsers enforce a strict security rule called the Same-Origin Policy (SOP). In simple terms, a web page at one origin (e.g., http://localhost:5173 where your React app runs) is not allowed to make requests to a different origin (e.g., http://localhost:8000 where your Laravel API runs).

This is a vital security measure. Without it, a malicious website you visit could use your browser to make requests to your online banking site or email account in the background, potentially stealing your data.

But for our SPA, we need the frontend and backend to talk to each other across different origins. This is where Cross-Origin Resource Sharing (CORS) comes in. It's a mechanism that allows a server to relax the SOP in a controlled and secure way.

To get a clear, visual understanding of this concept, please read the following article. It does an excellent job of explaining the problem and the solution.

CS Visualized: CORS - DEV Community

The article 'CS Visualized: CORS' by Lydia Hallie provides a fantastic, easy-to-digest explanation of the Same-Origin Policy and how CORS works to solve the cross-origin communication problem.

Please read the sections titled 'Same-Origin Policy', 'Client-side CORS', and 'Server-side CORS'. Focus on understanding what an 'origin' is, why the same-origin policy exists, and the role of the Access-Control-Allow-Origin header.


2. Configuring Laravel for SPA Authentication

Since your goal is to build a full e-commerce app with user login, we'll configure CORS in the context of Laravel Sanctum, Laravel's authentication system for SPAs. Sanctum uses cookies for session-based authentication, which requires some specific CORS settings.

As a Laravel developer, you're familiar with .env files and configuration files in the config directory. We'll be making changes in a few key places.

This video provides a concise walkthrough of the exact settings we need.

Laravel Sanctum SPA Tutorial - React SPA Authentication With Sanctum

The video 'Laravel Sanctum SPA Tutorial' from the Program With Gio channel demonstrates how to configure a Laravel backend to work with a frontend SPA. We will focus on the environment and CORS configuration sections.

Watch the specified clips to see how to configure the necessary environment variables and CORS settings. Sanctum & Session Config (02:10 - 03:56): Pay close attention to setting the SANCTUM_STATEFUL_DOMAINS and SESSION_DOMAIN variables in your .env file. This is what allows your React app to participate in Laravel's cookie-based session. CORS Config (03:56 - 04:49): Observe the changes made in config/cors.php, specifically setting supports_credentials to true and ensuring all necessary routes (api/*, login, etc.) are included in the paths array.


3. Step-by-Step Laravel Configuration Checklist

Let's consolidate what you saw in the video into a clear checklist. Open your Laravel project and apply these settings. (I'll assume your React app is running on http://localhost:5173 and Laravel on http://localhost:8000. Adjust the ports if yours are different).

1. Update your .env file:

Add or update these lines. SESSION_DRIVER should be set to cookie for Sanctum's SPA authentication to work seamlessly.




# .env
SESSION_DRIVER=cookie
SESSION_LIFETIME=120




# The URL of your React application
SANCTUM_STATEFUL_DOMAINS=http://localhost:5173




# The root domain to share cookies across subdomains (or ports on localhost)
SESSION_DOMAIN=localhost

2. Modify config/cors.php:

This is the main file for controlling CORS behavior in Laravel.

// config/cors.php

return [
    /*
     | Allow requests from these API paths. You need to add any non-api/* routes
     | that your SPA will hit, like the login/logout routes from Sanctum/Fortify.
     */
    'paths' => ['api/*', 'sanctum/csrf-cookie', 'login', 'logout'],

    'allowed_methods' => ['*'],

    'allowed_origins' => [env('SANCTUM_STATEFUL_DOMAINS', 'http://localhost:5173')],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => [],

    'max_age' => 0,

    /*
     | This MUST be set to true to allow cookie-based authentication
     | from a different origin.
     */
    'supports_credentials' => true,
];
  • 'paths': We explicitly add Sanctum's routes here.
  • 'allowed_origins': We use the .env variable we just set. This makes your configuration flexible for different environments (development, staging, production).
  • 'supports_credentials': Setting this to true adds the Access-Control-Allow-Credentials: true header to responses. This is the crucial step that tells the browser it's okay to send cookies with requests to your API.

3. Verify app/Http/Kernel.php:

Ensure that Sanctum's middleware is present in your api middleware group. Modern Laravel installations have this by default. This middleware is what attaches the session cookies to API responses.

// app/Http/Kernel.php
'api' => [
    \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, // This should be here
    'throttle:api',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],

After making these changes, clear your config cache to make sure Laravel picks them up:

php artisan config:cache

Your Laravel backend is now correctly configured to accept and authenticate requests from your React application.


4. A Note on the Frontend Configuration

While this lesson focuses on the backend, it's worth noting the corresponding change required on the frontend. When you use fetch or a library like Axios to make API calls, you must explicitly tell it to include credentials (like cookies) in the cross-origin request.

For the fetch API, this is done by adding credentials: 'include' to the options object:

fetch('http://localhost:8000/api/user', {
    credentials: 'include' // This tells the browser to send cookies
});

This frontend change, combined with your backend's 'supports_credentials' => true, completes the handshake.


Conclusion

In this lesson, we bridged the gap between your frontend and backend by tackling the essential concept of CORS.

Key Takeaways:

  • The Same-Origin Policy is a browser security feature that prevents requests between different origins.
  • CORS is the standard mechanism for servers to grant permission for cross-origin requests.
  • In Laravel, CORS is managed via the config/cors.php file.
  • For authenticating an SPA with Laravel Sanctum, you must:
    • Set SANCTUM_STATEFUL_DOMAINS and SESSION_DOMAIN in your .env file.
    • Set 'supports_credentials' to true in config/cors.php.
    • Ensure Sanctum's middleware is active for your API routes.
  • On the client-side, requests must be made with the credentials: 'include' option to send cookies.

With the communication channel now open, you are ready to start fetching real data from your Laravel API.

Preview of the Next Lesson:

In our next session, we will put this new configuration to use. You will refactor the product catalog to fetch live data from your Laravel API endpoints, replacing the static data currently in your React application.