I have my api using laravel sanctum api for auth and in my api routes i have this
Route::get('/blog/{id}', BlogController::class);
and in my controller i have this
public function __invoke(Request $request)
{
$blog = Blog::where('id', $request->id)->first()
return response->json([
'blog' => $blog
'user' => $request->user()
]);
}
The problem is that i do not know why the user is null in my nextjs application even though i have logged in.
also if i add sanctum auth middleware to the route i am not able to access the page in my nextjs application.
any help to solve this will be appreciated
Note: i have also done this auth()->user() and auth()->id()
still null
Could you post your .env file with just the Sanctum config you've added (if any)?
Also, is your Nuxt app using the same domain as your API?
I have thus in my .env
APP_URL=http://localhost:8000
FRONTEND_URL=http://localhost:3000
SESSION_DRIVER=database
SESSION_LIFETIME=120
SESSION_ENCRYPT=false
SESSION_PATH=/
SESSION_DOMAIN=null
i am using laravel 11 so inside config/sanctum.php
i have this
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s%s',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
Sanctum::currentApplicationUrlWithPort(),
env('FRONTEND_URL') ? ','.parse_url(env('FRONTEND_URL'), PHP_URL_HOST) : ''
)))
Thanks. So from the docs, the following isn't working for you?
also if i add sanctum auth middleware to the route i am not able to access the page in my nextjs application.
->withMiddleware(function (Middleware $middleware) {
$middleware->statefulApi();
})
I haven't tried that yet, what i did was just
Route::get('/blog/{id}', BlogController::class)->middleware(['auth:sanctum']);
and that redirects the user even though they are logged in
Here's a direct link. Let me know if this doesn't work and I'll set up a local project (but with Vue) and see if there's anything that might be missing.
I need to update the Sanctum course anyway, so will be super helpful.
Hi Alex, so i did that was in the doc
->withMiddleware(function (Middleware $middleware) {
$middleware->api(prepend: [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
]);
$middleware->statefulApi();
$middleware->alias([
'verified' => \App\Http\Middleware\EnsureEmailIsVerified::class,
'onboarding' => \App\Http\Middleware\OnboardingRedirect::class,
'subdomainAuthorization' => \App\Http\Middleware\SubdomainAuthorization::class,
]);
Controller
class DashboardController extends Controller
{
public function __invoke(Request $request)
{
$blog = Blog::where('id', $request->id)->first();
return response()->json([
'blog' => $blog,
'user' => $request->user(),
'message' => 'Dashboard'
], 200);
}
}
api route
Route::get('/blog/{id}', DashboardController::class);
and in nextjs i did this
export async function getSubdomain(id) {
try {
const response = await axios.get(`/api/blog/${id}`);
console.log(response)
return response.data.blog;
} catch (error) {
console.log(error)
}
}
i still see null
No worries, I’ll get a repo set up today and will send it over, since I’ve not worked for it for a while.
With Sanctum, small things are so easy to miss ha.
Try setting up
SANCTUM_STATEFUL_DOMAINS=localhost:3000 // replace this with front-end side url
SESSION_DOMAIN=localhost
in .env
I've spent some time re-familiarising myself with the Sanctum setup, so here's a full working repo for authentication with Sanctum and Vue.
This will be a course shortly, so you'll be able to follow along there for a full explanation too.
Let me know if you're still struggling!
https://github.com/alexgarrettsmith/laravel-sanctum-vue
Notable parts from the .env
file (not commited)
SESSION_DOMAIN=laravel-sanctum-vue-api.test
SANCTUM_STATEFUL_DOMAINS=laravel-sanctum-vue-api.test:5173
The client/api are running on exactly the same domain locally, just with a different port.
Hi @Alex thanks for this.
I will check it out and update you shortly
Quicky question though i noticed you used Fortify just out of curiosity why didn't you use Breeze??
You can use Breeze, but since it just defines some basic controllers I’d always recommend Fortify for the additional functionality.
Are you using Breeze to authenticate using Sanctum?
Yeah i am using Breeze, but i will check out what you've provided and use Fortify.
I am currently trying to read the Laravel docs to know the difference. :)
Hi Alex, i tried it last night, the authentication works and all. but i still have the same problem for some weird reason, if i add sanctum middleware to my show route i keep getting redirected even though i have been authenticated.
Makes me wonder if the auth:sanctum middleware does not support show method in controller??
My application is just about user authenticating and creating a blog and i want to attach middleware to stop user that's authenticated from accessing blog page that does not belong to them.
Cheers Alex
Would you mind posting what you see in your network tab? e.g. the response codes, response or anything relevant where the redirect happens? Thanks!
Hi Alex,
in my route i did this
Route::get('/{publication}/dashboard', [DashboardController::class, 'show']);
in my controller i did this
/**
* Display the specified resource.
*/
public function show(Request $request, Publication $publication)
{
return response()->json([
'publication' => $publication,
'user' => $request->user(),
'message' => 'Dashboard'
], 200);
}
and i see this
{
"publication": {
"id": "9c095ff7-8d30-43ea-bfee-f063a27cba07",
"subdomain": "henry",
"publication_name": null,
"about": null,
"twitter": null,
"instagram": null,
"website": null,
"facebook": null,
"linkedin": null,
"header_color": "#ffffff",
"user_id": 1,
"created_at": "2024-05-13T22:53:06.000000Z",
"updated_at": "2024-05-13T22:53:06.000000Z"
},
"user": null,
"message": "Dashboard"
}
if i put auth:sanctum middleware in my routes Route::get('/{publication}/dashboard', [DashboardController::class, 'show'])->middleware('auth:sanctum');
it redirects to /dashboard even though i already been authenticated.
Are you using any other middleware in your DashboardController
?
Hi Alex, after spending time going through it, i have been able to solve it. The problem was how i was getting the data with Nextjs.
So i used server components to get the data using axios and the problem was that i was using another server component to display the response, which for some reason wasn't working.
When i switched to using client component by adding 'use client'
and running the process it works
so here is my final code
i have hooks/fetchPublication
import axios from "@/lib/axios"
export const useDomain = () => {
const csrf = () => axios.get('/sanctum/csrf-cookie')
const getPublication = async ( props ) => {
try{
await csrf()
const res = await axios
.get(`api/${props.id}/dashboard`)
return res.data
}catch(error){
console.log(error)
}
}
return {
getPublication
}
}
and in my client component i did this
'use client'
import { useAuth } from "@/hooks/auth"
import Header from "./components/Header"
import { useDomain } from "@/hooks/fetchPublication"
export default function Layout({params, children }) {
const { user } = useAuth({
middleware: 'auth',
})
const { id } = params
const { getPublication } = useDomain()
const data = getPublication({id})
if (!data) {
return redirect('/');
}
return (
<div>
<Header user={user} />
{children}
</div>
)
}
that works.
Thanks for your help mate.