0
votes

I want to use React with Sanctum. In Sanctum, I generated the token and return it after login, and it works correctly. However, after login, I can see my token in the console, but if I want to open the route for logged-in users, I must send this token in the header. What is the best method to do that?

public function login(Request $request)
{
    $attr = $request->validate([
        'email' => 'required|string|email|',
        'password' => 'required|string|min:6'
    ]);

    if (!Auth::attempt($attr)) {
        return $this->error('Credentials not match', 401);
    }

    return response()->json([
       'access_token' => auth()->user()->createToken('auth_token')->plainTextToken,
       'token_type' => 'Bearer',
    ]);
}

And login into React.

function Login () {
    const emailRef = useRef(),
          passwordRef = useRef();

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

        axios.post('http://localhost:8000/api/auth/login', { email: emailRef.current.value, password: passwordRef.current.value })
            .then(res => {
                console.log(res);
            }).catch((error) => {
                console.log(error)
            });
    }
    return(
       // Here is my form
    );
}

@Edit

I don't sure I good understand but it doesn't work. If I try to get address witch need to autorize I have a status 401. I make instance instance.php

import axios from 'axios'
let instance = axios.create({
    baseURL: 'http://localhost:8000',
    headers: {
        common: {
            'X-Requested-With': 'XMLHttpRequest',
        }
    },
    withCredentials: true,
});

export default instance;

And I login user. In React it look like this

instance.post('/api/auth/login', {

        email: emailRef.current.value,
        password: passwordRef.current.value
    
}).then(res => {
    console.log(res);
})

Generally it works. I want to add someting which need to authorize.

instance.get('/api/me')
    .then(res => {
        console.log(res.data.data.token);
    }).catch((error) => {
        console.log(error)
    });

And in Api.php it look like this

Route::post('/auth/register', [AuthController::class, 'register']);

Route::post('/auth/login', [AuthController::class, 'login']);

Route::group(['middleware' => ['auth:sanctum']], function () {
    Route::get('/me', function() {
        echo "Hello World";
    })->name('me');

    Route::post('/auth/logout', [AuthController::class, 'logout']);
});
1

1 Answers

0
votes

You should be able to not need to store anything in any special place by just using Axios config like this:

axios.create({
    headers: {
        common: {
            'X-Requested-With': 'XMLHttpRequest',
        },
    },
    withCredentials: true,
});

The withCredentials: true will store the CSRF token and any credential once you login, so you would not have to worry anymore about sending any credentials or anything like so.

This is another example.


You could also take advantage of Axios and also delete any data you have store when a request returns 401 (Unauthorized) or 419 (Session Expired).

authClient.interceptors.response.use(
    (response) => response,
    (error) => {
        if (error.response &&
            [401, 419].includes(error.response.status) &&
            store.getters[`user/${IS_GUEST_GETTER}`]
        ) {
            store.dispatch(`user/${LOGOUT_ACTION}`);
        }

        return Promise.reject(error);
    }
);

In this example, I am using a store like and I am asking first if the current user is a guest or not, and then deleting everything from the session with a simple logout (on Vue and Laravel).

You can do this with Interceptors.