1
votes

I am trying to get React and Laravel to work together using the middleware Sanctum.

I can read many examples of people trying to do this with a cookie based setup, but I am trying to use the token setup for a pure API approach. I am doing this because I want to prepare the backend for use in a mobile app where cookies are not available.

This is a part of my setup:

/backend/routes/api.php:

Route::post('/login', [ UserController::class, 'getAccessToken'] );

/frontend/store/api.js

static login( user ) {

    var formData = new FormData();
    formData.append('username', user.username);
    formData.append('password', user.password )
    formData.append('deviceName', 'browser');

    return fetch( 
        'http://localhost:5001/api/login, {
            method : 'post',
            body : formData
        }
    );
}

My problems is that it forces a CSRF token check, when the login route is accessed. That is even if the login route shouldn't be guarded by Sanctum. This of course fails when I am logging in and don't yet have a token to attach to the request. As I understand the token is only needed on accessing guarded routes after login. I have double checked that it is accessing the right route by renaming it to something fake and getting an error.

Am I doing something wrong with the use of Sanctum or is Sanctum just not the preferred use for api tokens? Should I maybe look into JWT instead?

Thank you in advance for your help. <3

2

2 Answers

1
votes

Please, check this url, I was able to make it work thanks to this tutorial.

https://laravel-news.com/using-sanctum-to-authenticate-a-react-spa

here is my LoginForm.jsx

import React from "react";
import apiClient from "./services/apiClient";

const LoginForm = (props) => {
  const [email, setEmail] = React.useState("");
  const [password, setPassword] = React.useState("");

  const handleSubmit = (e) => {
    e.preventDefault();

    apiClient.get("/sanctum/csrf-cookie").then((response) => {
      apiClient
        .post("/api/sanctum-token", {
          email: email,
          password: password,
          device_name: "React v0.1",
        })
        .then((response) => {
          console.log(response);
        });
    });
  };
  return (
    <div>
      <h1>Login</h1>
      <form onSubmit={handleSubmit}>
        <input
          type="email"
          name="email"
          placeholder="Email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          required
        />
        <input
          type="password"
          name="password"
          placeholder="Password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          required
        />
        <button type="submit">Login</button>
      </form>
    </div>
  );
};

export default LoginForm;

apiClient.js

import axios from "axios";

const apiClient = axios.create({
  baseURL: "http://localhost",
  withCredentials: true,
});

export default apiClient;
0
votes

In:

/backend/app/Http/Kernel.php

I had added:

\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,

It worked when I removed that line. I had failed to understand that a SPA equals the use of cookies, because I would say that I am also working on a SPA that just uses API tokens instead.

Next issue is that I am using Doctrine instead of Eloquent, which I can now see it far from compatible with Sanctum when it comes to issuing the token. But that will be a topic for another question.