rjcode
rjcode

Reputation: 1347

Laravel Sanctum Breeze with Next JS

I just installed this https://github.com/laravel/breeze-next repository and as expected everything works fine as documented. Login, Logout and registration work fine.

Now after login, I want to protect the API routes, but it throws errors as 401 when I try to access the protected route even after login.

Here is AXIOS setup as given in Repo,

import Axios from 'axios'

const axios = Axios.create({
    baseURL: process.env.NEXT_PUBLIC_BACKEND_URL,
    headers: {
        'X-Requested-With': 'XMLHttpRequest',
    },
    withCredentials: true,
})

export default axios

I just added a server call with Axios with \api\test

export async function getStaticProps() {
    const response = await axios.get(`/api/test`);
  
    return {
        props: {
            customers: response.data
        },
    }
  }

This is API in laravel.

Route::middleware(['auth:sanctum'])->get('/test', function () {
    return response()->json([
        'val' => 1,
        'msg' => 'successfully',
    ]);
});

If I remove middleware, it works fine. But when added middleware auth sanctum, it always shows 401 error.

Server Error
Error: Request failed with status code 401

This error happened while generating the page. Any console logs will be displayed in the terminal window.

So I can give authentication in SPA with sanctum?

Upvotes: 2

Views: 2991

Answers (2)

bytemore
bytemore

Reputation: 1

I was facing the same problem and instead using getStaticProps function I was able to resolve using useEffect() using the axios setup provinding by the repo, so you could try this way instead. Assuming your directories structure pages/test.js, in your case would be:


import axios from "../lib/axios";
import {useEffect, useState} from "react";
import AppLayout from "../components/Layouts/AppLayout";

const Test = () => {
    const [customers, setCustomers] = useState()
   
    useEffect(() => {
        axios
            .get("/api/tests")
            .then((response) => {
                setCustomers(response.data);
            })
            .catch((error) => console.error(error));
    }, []);

    return (
        <AppLayout
            header='Customers'
        >

            <Head>
                <title>Customers</title>
            </Head>

            <div className="py-12">
                <div className="max-w-7xl mx-auto sm:px-6 lg:px-8">
                    <div className="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                        <div className="p-6 bg-white border-b border-slate-200">
                            {customers.map((customer, index) => (
                                <div key={customer.val}>
                                    <div>
                                        {customer.val}
                                        {customer.message}
                                    </div>
                                </div>
                            ))}
                        </div>
                    </div>
                </div>
            </div>
        </AppLayout>
    )

}

And if you need to create a detail view with the same method within this directory structure test/[id].js:


import axios from "../../lib/axios";
import AppLayout from "../../components/Layouts/AppLayout";
import Head from "next/head";
import {useEffect, useState} from "react";
import {useRouter} from "next/router";

const Profiles = () => {
    const [customer, setCustomer] = useState()

    // Use router to get the id from the url your visiting
    const router = useRouter();

    useEffect(() => {
        if(!router.isReady) return;
        axios
            .get(`/api/tests/${router.query.id}`) // Here we accessing the url parameter from useRouter()
            .then((response) => {
                setCustomer(response.data);
            })
            .catch((error) => console.error(error));
    }, [router.isReady]);

    return (
        <AppLayout
            header='Customer'
        >

            <Head>
                <title>Customer</title>
            </Head>

            <div className="py-12">
                <div className="max-w-7xl mx-auto sm:px-6 lg:px-8">
                    <div className="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                        <div className="p-6 bg-white border-b border-slate-200">
                            <div>
                                {customer.val}
                                {customer.message}
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </AppLayout>
    )
}

credits:

Upvotes: 0

Maik Lowrey
Maik Lowrey

Reputation: 17594

Have you already added sanctum to your kernel.php?

By default \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,in your Kernel.php is commented out.

It should be look like that:

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

Upvotes: 0

Related Questions