- 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
OAuth 2.0 Explained Without the Jargon: The Valet Key Guide
About Post
You pull up at a fancy hotel. The valet holds out a hand for your keys. You hesitate, because that key also opens the boot, the glovebox and, if you're unlucky, your house.
Some cars solve this with a valet key: it starts the engine and opens the driver's door, and that's it. The valet can park the car. They can't read your mail.
That's OAuth 2.0. Everything else in the spec is detail about how to hand over the valet key safely. Let's go through it without the jargon, then add back just enough jargon to read the docs.
The problem OAuth solves
Years ago, if a photo printing website wanted your pictures from another service, it asked for your username and password for that service. Then it logged in as you. With full access. Forever, or until you changed your password and broke every other app that did the same thing.
OAuth replaces "give me your password" with "let the service you trust give me a limited key". The printing site never sees your password. It gets a token that can read photos, maybe only for a while, and you can take it back any time.
The cast of characters
OAuth has four roles. Here they are in valet terms:
| OAuth name | Valet version | Photo example |
|---|---|---|
| Resource owner | You, the car owner | You, the person with the photos |
| Client | The valet | The photo printing website |
| Authorization server | The hotel desk that issues valet keys | The photo service's login and consent screen |
| Resource server | The car | The photo service's API |
The authorization server and resource server often belong to the same company, but they're different jobs: one hands out keys, the other checks them.
The flow you should use: authorization code with PKCE
OAuth has several "flows". For almost every app today, web, mobile or single-page, the answer is the authorization code flow with PKCE. Here it is, step by step.
Step 1: the app sends you to the authorization server
You click "Import from PhotoCloud". The printing site redirects your browser to PhotoCloud with a URL like this:
https://photocloud.example/authorize
?response_type=code
&client_id=print-shop
&redirect_uri=https://print.example/callback
&scope=photos.read
&state=af0ifjsldkj
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
&code_challenge_method=S256
In plain words: "Hi, I'm the print shop. I'd like to read this person's photos. Send them back to this address afterwards."
Step 2: you log in and consent
You log in on PhotoCloud's own page, not the print shop's. That's the crucial part: your password only ever goes to the service that owns it. PhotoCloud shows "Print Shop wants to view your photos" and you click Allow.
Step 3: you're sent back with a short-lived code
PhotoCloud redirects to https://print.example/callback?code=...&state=af0ifjsldkj. The code is not the key yet. It's more like a claim ticket: short-lived and single-use. The app checks that state matches what it sent, which protects against someone forging the callback.
Step 4: the app swaps the code for tokens
The print shop's backend calls PhotoCloud directly, server to server, and exchanges the code for an access token (and usually a refresh token). Then it calls the API with Authorization: Bearer <access token>. Valet key in hand.
So what is PKCE, and why does it matter?
PKCE (Proof Key for Code Exchange, pronounced "pixie") closes a gap in step 3. The code travels through the browser, and on mobile it travels through a redirect that another app could, in some cases, intercept. If an attacker grabs the code, could they swap it for tokens?
PKCE says no. Before step 1, the app invents a random secret, the code verifier, and keeps it. It sends only a hash of it, the code challenge, in the first URL. In step 4, it must present the original verifier. The authorization server hashes it and compares. A stolen code without the verifier is useless.
It was designed for mobile and single-page apps, which can't keep a client secret (anyone can unpack your app and read it). Current best practice is to use PKCE for every client, including server-side apps that also have a secret.
Scopes and tokens, briefly
- Scopes are the valet key's limits:
photos.read, notphotos.delete. Ask for the smallest set you need. Users read consent screens more than you'd think, and a scary list gets a "Deny". - Access tokens are short-lived. If one leaks, the damage window is small.
- Refresh tokens are long-lived and used only to get new access tokens from the authorization server. Store them like passwords: server-side or in secure device storage, never in
localStorage.
The old implicit flow, which returned the token directly in the browser URL, is no longer recommended. If a tutorial uses response_type=token, find a newer tutorial.
OAuth vs OpenID Connect: the most common confusion
Here's the thing that trips everyone up: OAuth is about access, not identity. A valet key proves you're allowed to drive the car. It doesn't tell the hotel who you are.
Plenty of apps used OAuth for "Log in with X" anyway, by calling some profile endpoint with the access token. Every provider did it differently. OpenID Connect (OIDC) standardises it: a thin layer on top of OAuth that adds an ID token, a signed JWT that says who the user is, which app it was issued for, and when.
| OAuth 2.0 | OpenID Connect | |
|---|---|---|
| Question it answers | "What can this app access?" | "Who is this user?" |
| Main token | Access token | ID token (plus access token) |
| Typical use | Calling an API on the user's behalf | "Sign in with Google" style login |
| Scope you'll see | Whatever the API defines | openid, profile, email |
If you're building login, you want OIDC. If you're calling someone's API for a user, you want OAuth. "Sign in with Google" is both at once.
The rules worth memorising: authorization code flow, always with PKCE. Validate state. Ask for minimal scopes. Short-lived access tokens, carefully stored refresh tokens. OAuth for access, OIDC for identity.
In Laravel
You rarely implement this by hand. As a client ("log in with GitHub"), Socialite handles the redirects, state and token exchange. As a provider (other apps logging in through yours), Passport is a full OAuth 2 server. If you only need tokens for your own SPA or mobile app, you probably don't need OAuth at all, and Sanctum is the simpler fit.
Knowing the flow still pays off. When a callback fails with "invalid_grant" at 6 pm, the person who understands steps 1 to 4 fixes it in minutes.
What was the OAuth concept that took you the longest to really understand? For me it was accepting that OAuth, on its own, isn't a login protocol.

Be first to comment it...