Kritim Yantra
Apr 11, 2025
Building secure APIs is crucial for modern web applications. In this guide, we'll implement JWT-less authentication in Laravel 12 using Sanctum (Laravel’s lightweight API auth system) and GraphQL.
By the end, you'll learn:
✅ How Sanctum works (Session-based API auth)
✅ Setting up Sanctum with GraphQL
✅ User Registration & Login with GraphQL
✅ Protecting GraphQL Queries & Mutations
Let’s get started!
Sanctum is Laravel’s official package for simple, session-based API authentication. Unlike Passport (OAuth), Sanctum is lightweight and perfect for:
It uses cookie-based sessions for web authentication and API tokens for mobile.
composer create-project laravel/laravel sanctum-graphql
cd sanctum-graphql
Install Lighthouse (GraphQL) and Sanctum:
composer require nuwave/lighthouse laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
Add Sanctum’s middleware to app/Http/Kernel.php
:
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
Update config/cors.php
:
'paths' => ['*'],
'supports_credentials' => true,
php artisan make:model User -m
Update the migration (database/migrations/xxxx_create_users_table.php
):
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->timestamps();
});
Run migrations:
php artisan migrate
graphql/schema.graphql
)type Mutation {
register(name: String!, email: String! @rules(apply: ["email", "unique:users"]), password: String! @rules(apply: ["min:8"])): User @create
login(email: String!, password: String!): String
logout: String @guard
}
type Query {
me: User @guard
}
type User {
id: ID!
name: String!
email: String!
created_at: String!
updated_at: String!
}
Generate a resolver:
php artisan make:graphql AuthResolver
Update app/GraphQL/Resolvers/AuthResolver.php
:
<?php
namespace App\GraphQL\Resolvers;
use Illuminate\Support\Facades\Auth;
class AuthResolver
{
public function login($root, array $args)
{
if (Auth::attempt(['email' => $args['email'], 'password' => $args['password']])) {
$user = Auth::user();
return $user->createToken('auth_token')->plainTextToken;
}
throw new \Error('Invalid credentials.');
}
public function logout()
{
$user = Auth::user();
$user->tokens()->delete();
return 'Logged out successfully!';
}
}
graphql/schema.graphql
type Mutation {
login(email: String!, password: String!): String @field(resolver: "App\\GraphQL\\Resolvers\\AuthResolver@login")
logout: String @guard @field(resolver: "App\\GraphQL\\Resolvers\\AuthResolver@logout")
}
mutation {
register(name: "John Doe", email: "john@example.com", password: "password123") {
id
name
}
}
mutation {
login(email: "john@example.com", password: "password123")
}
Response:
{
"data": {
"login": "1|abcdef123456..."
}
}
me
Query)Add the Authorization header in GraphQL Playground:
{
"Authorization": "Bearer 1|abcdef123456..."
}
Then run:
query {
me {
id
name
email
}
}
mutation {
logout
}
Use the @guard
directive to protect routes:
type Query {
secretData: String @guard
}
You’ve successfully implemented GraphQL authentication in Laravel 12 using Sanctum! 🎉
✔ Sanctum setup for session-based auth
✔ User registration & login with GraphQL
✔ Protected routes using @guard
✔ Token-based authentication
No comments yet. Be the first to comment!
Please log in to post a comment:
Continue with Google