- Knowledge
- technology
- OOP
- Tips
- Programming
- Tips
- Tutorial
- SEO
- Ranking
- Knowledge
- Special Day
- Seo
- Bug
- Data science
- Seo
- artificial intelligence
- Machine Learning
- Robotics
- happyNewYear2021
- newYearEve
- 2021
- Automation
- Smart Home
- Career
- Best Practices
- Git
- Logging
- Web Fundamentals
- DNS
- HTTPS
- Performance
- AI Tools
- ChatGPT
- Claude
- Gemini
- Laravel
- Eloquent
- MySQL
- HTTPS
- TLS
- Web Security
- Certificates
- Developer Life
- Debugging
- Docker
- DevOps
- Transactions
- Queues
- LLMs
- AI
- AI Coding
- Developer Tools
- React Native
- Expo
- Kate PMS
- Mobile Apps
- Laravel
- Authentication
- Sanctum
- Cookies
- API Design
- Payments
- Idempotency
- DeepSeek
- Open Source AI
- LLMs
- AI News
- Git
- Version Control
- AI Coding
- Prompting
- PHP
- Checklist
- MCP
- AI Agents
- OpenAI
- Architecture
- Microservices
- Modular Monolith
- Estimation
- Developer Life
- Project Planning
- Humour
- OAuth
- OpenID Connect
- Authentication
- Embeddings
- Vector Search
- RAG
- pgvector
- OpenAI
- GPT-4.1
- Codex CLI
- Events
- Testing
- Clean Code
- Maintainability
- Code Review
- Webhooks
- API
- Security
- Claude Code
- Workflow
- AI
- LLM
- Prompt Injection
- Mobile
- React
- Networking
- TCP
- UDP
- HTTP/3
- CLAUDE.md
- AWS
- Cloud Security
- Backups
- PHPUnit
- Software Engineering
- Leadership
- Communication
- RAG
- Embeddings
- AI Engineering
- IT Infrastructure
- Networking
- Access Control
- CI/CD
- GitHub Actions
- Gemini CLI
- Claude Code
- JavaScript
- Async/Await
- Node.js
- Promises
- Security
- Cryptography
- Passwords
- MySQL
- Database
- Vibe Coding
- Software Quality
- DNS
- Code Reading
- Onboarding
- Productivity
- Background Jobs
- Developer Humour
- Estimates
- Dev Life
- JWT
- o3-mini
- DeepSeek R1
- Rate Limiting
- Kate PMS
- E-Signing
- Audit Trail
- REST
- GraphQL
- API Design
- Laravel 12
- Upgrade Guide
- Open Source
- Self-Hosting
- Task Scheduling
- Cron
- Secrets
- CORS
- PHP
- PHP-FPM
- OPcache
- GitHub Copilot
- Software Architecture
- Engineering
- TypeScript
- JavaScript
- Type Safety
- AI Security
- React Native
- Product Design
- AI Agents
- Kiro
- Queues
- Redis
- RabbitMQ
- AWS SQS
- Nginx
- Apache
- GPT-5
- gpt-oss
- Clean Code
- Architecture
- Naming
- Documentation
- Career
- ADR
- Teamwork
- Supply Chain
- Kate HRM
- HR Software
- Permissions
- System Design
- Pagination
- SSH
- Linux
- Big O
- Databases
- Laravel Boost
- MCP
- Developer Skills
- Validation
- Databases
- Indexes
- Code Quality
- Deployment
- Developer Humour
- Feature Flags
- Code Review
- Pull Requests
- Docker
- Cursor
- Authorization
- RBAC
- Gemini
- Long Context
- PHP 8.4
- Caching
- Dependency Injection
- Web Performance
- Browser
- CSS
- Database
- Migrations
- ChatGPT
- AI for Developers
- Monitoring
- On-Call
- REST
- Backend
- SQL
- NoSQL
- Database Design
- Coding Agents
- Claude 4
- API Resources
- REST API
- Load Balancing
- Scaling
- AWS
- AI Tools
- Claude
- Sora 2
- CTE
- 2FA
- TOTP
- Programming Languages
- Prompts
- Developer Workflow
- API Gateway
- APIs
- Passport
- API Auth
- Learning
- Burnout
- Developer Growth
- Web Development
- SEO
- Kate Mall
- ChatGPT Atlas
- Agent Skills
- Middleware
- Laravel 12
- Collections
- Context Window
- Monitoring
- Commit Messages
- Self Review
- Growth
- Regex
- Programming Basics
- Text Processing
- Database Design
- Normalization
- Linux
- Server Security
- Linux Foundation
- Open Standards
- Legacy Code
- Documentation
- AI Workflow
- File Uploads
- Test Data
- Hashing
- Performance
- Caching
- Enums
- Scope Creep
- Estimation
- Codex
- Gemini CLI
- Timezones
- Carbon
- Bugs
- PHP 8.5
- Gemini 3
- GPT-5.1
- Data Integrity
- Event Loop
- Async
- Opus 4.5
- AI Models
- React
- Forms
- Frontend
- Backups
- AI Images
- DALL-E
- Midjourney
- Race Conditions
- Concurrency
- Legacy Code
- Refactoring
- Senior Engineer
- Scope
- LLM
- CDN
- Web
- Sub-Agents
- Soft Deletes
- Audit Log
- Concurrency
- AI Learning
- NestJS
- AI Evals
- Policies
- SPF DKIM DMARC
- Unicode
- UTF-8
- Knowledge Graph
- Value Objects
- Technical Debt
- Feature Flags
- Laravel Pennant
- Deployment
- Copilot
- Composer
- Dependencies
- Artisan
- Automation
- AWS S3
- Object Storage
- Cloud
- Small Language Models
- Ollama
- Production
- Sessions
- HTTP
- Mentoring
- SQL
- Virtual Machines
- Web Development
- HTTP/2
- QUIC
- Web Performance
- AI Integration
- LLM API
- SOLID
- OOP
- Hosting
- Serverless
- Merge Conflicts
- Temperature
- AI Development
- Reverse Proxy
- Nginx
- Infrastructure
- Verification
- Passkeys
- WebAuthn
- Teams
- Communication
- Stakeholders
- Monorepo
- CI/CD
- Versioning
- JSON Schema
- Livewire
- Inertia
- Meetings
- Distributed Systems
- Privacy
- Full-Stack
- T-Shaped Skills
- Money
- Notifications
- Web Security
- HTTP Headers
- CSP
- Function Calling
- Load Testing
- k6
- Data Extraction
- Debugging
- WebSockets
- SSE
- Real-Time
- Laravel Reverb
- Infrastructure as Code
- Terraform
- Side Projects
- Laravel Pint
- OpenAPI
- Swagger
- UX
- Multimodal
- Jest
- Pair Programming
- APIs
- Rate Limiting
- Resilience
- Dev Humour
- Design Tokens
- JWT
- API Keys
- Sessions
- PHPStan
- Rector
- Incidents
- Reporting
- Dashboards
- Zero Trust
- IAM
- Search
- Laravel Scout
- Junior Developers
- Mentoring
- Images
- WebP
- AVIF
- Bug Reports
- Let's Encrypt
- Design Docs
- Software Design
- Observers
- Replication
- Accountability
- Data Structures
- Reliability
- LLM Memory
- Error Handling
- Payments
- Payment Gateway
- Webhooks
- PCI DSS
- Observability
- OpenTelemetry
- Personal Brand
- Writing
- Conventions
- Dates
- Scheduling
- Disaster Recovery
- Compression
- Brotli
- Deadlines
- Developer Habits
- State Machines
- Tech Roles
- UUID
- ULID
- Horizon
- Planning
- Engineering Culture
- Ownership
- Soft Skills
- Socialite
- Cost Control
- Collations
- Unicode
- Octane
- PostgreSQL
Laravel Sanctum vs Passport: Which Auth Package Do You Actually Need?
About Post
You need API authentication in Laravel. You search, and two official packages come up: Sanctum and Passport. Both issue tokens. Both protect routes. Both have long documentation pages.
So people pick one almost at random, or pick Passport because "OAuth sounds more serious". And then they spend a week configuring clients, grants and encryption keys for an app that only ever needed a login screen.
The choice is much simpler than it looks. It comes down to one question, and I'll get to it. First, what each package actually is.
Sanctum: simple auth for your own apps
Sanctum does two separate jobs, and mixing them up is the source of most confusion.
Job 1: SPA authentication with cookies
If your React or Vue front end runs on the same top-level domain as your Laravel API (say app.example.com and api.example.com), Sanctum doesn't use tokens at all. It uses Laravel's normal session cookie, with CSRF protection. No token in localStorage for an XSS bug to steal.
In Laravel 12 you turn it on in bootstrap/app.php and list your front-end domain in the SANCTUM_STATEFUL_DOMAINS env variable:
->withMiddleware(function (Middleware $middleware) {
$middleware->statefulApi();
})
The front end first asks for a CSRF cookie, then logs in normally:
axios.defaults.withCredentials = true;
axios.defaults.withXSRFToken = true;
await axios.get('/sanctum/csrf-cookie');
await axios.post('/login', { email, password });
// From now on, the session cookie authenticates API calls
Job 2: API tokens for mobile apps and scripts
A React Native app can't rely on browser cookies the same way, so Sanctum also issues simple API tokens. The user logs in, you create a token, and the app sends it as a Bearer header:
Route::post('/mobile/token', function (Request $request) {
$request->validate([
'email' => 'required|email',
'password' => 'required',
'device_name' => 'required',
]);
$user = User::where('email', $request->email)->first();
if (! $user || ! Hash::check($request->password, $user->password)) {
throw ValidationException::withMessages([
'email' => ['The provided credentials are incorrect.'],
]);
}
return $user->createToken($request->device_name, ['contracts:read'])
->plainTextToken;
});
Tokens are random strings, stored as a SHA-256 hash in the personal_access_tokens table. You can give them abilities ($request->user()->tokenCan('contracts:read')), set expiry, and revoke one device without logging out the others. Protect routes with auth:sanctum and you're done. (Simplified: add rate limiting to that login route in a real app.)
Passport: a full OAuth2 server
Passport is a different kind of tool. It turns your Laravel app into an OAuth2 authorization server, the same kind of system behind "Sign in with..." buttons and "Allow this app to access your account?" screens.
That means it supports OAuth2 grant types:
- Authorization code (with PKCE): a third-party app sends the user to your login page, the user approves access, and the app receives a token. The app never sees the user's password.
- Client credentials: machine-to-machine access, where a partner's server authenticates as itself, not as a user.
- Refresh tokens, OAuth scopes, client registration and consent screens.
It also brings real moving parts: encryption keys to generate and protect, OAuth clients to manage, more tables, and a protocol with plenty of ways to misconfigure it. That's a fair price when you need OAuth. It's pure overhead when you don't.
Side by side
| Sanctum | Passport | |
|---|---|---|
| What it is | Lightweight auth for your own clients | Full OAuth2 server |
| SPA on same domain | Cookie sessions + CSRF | Possible, but not its strength |
| Mobile app (your own) | Personal access tokens | Works, more setup |
| Third-party apps acting for your users | No | Yes (authorization code + PKCE) |
| Machine-to-machine | Token on a service user | Client credentials grant |
| Setup in Laravel 12 | php artisan install:api | php artisan install:api --passport |
| Complexity | Low | High |
The one question
Will apps that you don't own need to access your users' data on their behalf? If yes, you need an OAuth2 server: use Passport. If no, use Sanctum.
Almost everything else falls out of that. A typical setup with a web portal, a staff app and a tenant app, all built by the same team, is a Sanctum project: cookie auth for the web, tokens for the mobile apps, abilities and policies for permissions. No third party is asking your users for consent, so there's no OAuth flow to support.
Passport earns its place when you're building a platform: partners integrating with your API on behalf of shared customers, a developer portal, or "Connect your account to X" flows.
Mistakes I see with both
- Choosing Passport "for the future". If OAuth becomes a requirement, you can add it then. You'll pay the complexity cost every day until then.
- Using Sanctum tokens in a browser SPA when cookie auth was available. Tokens in
localStorageare readable by any injected script. - Forgetting
SANCTUM_STATEFUL_DOMAINSand the CORSsupports_credentialssetting, then wondering why the SPA gets 401s right after logging in. - Tokens that never expire. Set an expiry that fits your app, and schedule
sanctum:prune-expiredto clean old rows. - Treating abilities as authorisation. A token ability says what the token may do. Policies still decide whether this user may touch this record.
The short version
- Your own SPA on the same domain: Sanctum, cookie mode.
- Your own mobile app: Sanctum tokens.
- Other people's apps acting for your users: Passport.
- Not sure: Sanctum, until a real OAuth requirement shows up.
Have you ever migrated from one to the other? I'm curious which direction it went, and what pushed you to do it.

Be first to comment it...