laravelcookiesaxioscsrfsanctum

CSRF Cookie is not being set when using axios GET - Laravel 9 Sanctum


I am currently trying to create a simple authentication feature using Laravel (v9.52.4) and Sanctum. From the frontend I am currently using Axios to get and post data. Both frontend and backend API are running on localhost (http://121.0.0.1:8000) but the API endpointscan be reached at http://121.0.0.1:8000/api/v1/{endpoint here}

When I try to log in, everything seems to be running as expected but no CSRF cookies are being send/set by the backend API. If I use the correct login credentials (email + password) the tokens get generated on the backend, get stored in the database and also sends a response that the login was successful - of course if the credentials are invalid no token gets generated and I recieve the proper response. (So the login logic seems to be working fine, but without the CSRF cookies I can't authorize myself on the admin subpages so it simply redirects me to the login page even after a successful login)

I have been searching for the solution, but with no luck so far. You can find all the files/pieces of code that might be relevant for this issue:

.env (The ROOT_URL variable is used to create HTML and Javascript URLs on frontend)

APP_URL=http://127.0.0.1:8000
...
SESSION_DOMAIN = "127.0.0.1:8000"
SANCTUM_STATEFUL_DOMAINS = "127.0.0.1:8000"
ROOT_URL="http://127.0.0.1:8000"

.AuthController - /login route uses this controller's functions

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Response;

class AuthController extends Controller
{
    public function login(Request $request){
        $credentials = [
            'email' => $request->email, 
            'password' => $request->password
        ];

        if(Auth::attempt($credentials)){
            $authUser = Auth::user();
            $success['token'] = $authUser->createToken('APIToken')->plainTextToken;
            $success['name'] = $authUser->name;
            return response()->json(['user' => $success], 200);
        }
        else {
            return response()->json(['error' => "Unauthenticated"], 404);
        }
    }

    public function logout(Request $request, $isAPI = true){
        $request->session()->invalidate();
        $request->session()->regenerateToken();

        auth()->user()->tokens()->delete();
        if($isAPI){
            return response()->json(['msg' => "user logged out"], 200);
        }
        return view('admin.login');
    }
}

cors.php

    'paths' => ['api/*', 'sanctum/csrf-cookie'],

    'allowed_methods' => ['*'],

    'allowed_origins' => ['*'],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => true,

Kernel.php (I have imported and added the middleware)

...        
'api' => [
            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
...

Frontend Axios handlers

const API_ROOT = `${ROOT_URL}/api/v1`
axios.defaults.withCredentials = true

async function loginUser(credentials){ //these credentials are coming from the HTML form inputs
    const CSRF = `${ROOT_URL}/sanctum/csrf-cookie`
    const LOGIN_URL = `${API_ROOT}/login`

    toggleLoader()
    await axios.get(CSRF)
    await axios.post(LOGIN_URL, credentials)
        .then((res) => handleResponse(res.data))
        .catch((err) => console.log(err))
        .finally(() => toggleLoader())
}

function handleResponse(response){
    if(response.user){
        console.log(`Logged in as ${response.user.name}`)
        window.location.replace(`${ROOT_URL}/admin`)
        return
    }
    console.log('failed to log in')
}

I really hope that someone has already met with this problem and can give me a helping hand. Thank you all for any help or suggestions!

Have a great day!

Sidenote: The authentication process (creating tokens, setting the cookies and logging in) was working when I was using the XAMPP for local hosting. Then I moved the project out of the htdocs directory and started hosting using php artisan serve command. Everything else (database, routes, etc.) is still working besides setting the CSRF cookies.


Solution

  • I finally managed to figure out a solution - the problem was mainly related to misconfigured domains. I have also deployed the project on a live server and it is working fine there as well.

    Here are my settings from .env file, that fixed my issue:

    APP_URL=http://127.0.0.1:8000
    SESSION_DOMAIN=127.0.0.1
    SESSION_DRIVER=cookie
    SANCTUM_STATEFUL_DOMAINS=127.0.0.1:8000
    ROOT_URL=//127.0.0.1:8000
    

    Note: ROOT_URL is being used when fetching the API! (So in my js file it looks like this: //127.0.0.1:8000/api/v1/login)

    Seems like it's quite important where to/not to feautre the scheme and port (':8000', 'http', etc...) in the URL.

    I really hope this solution will help some people out there. :)