A Beginner’s Guide to Understanding How Login Systems Really Work
Introduction
When you’re building your first backend application, one of the most confusing topics is authentication. You’ll hear terms like “password,” “token,” “session,” “hash,” and “expiration” thrown around, and it can feel overwhelming.
In this article, I’ll break down exactly how modern authentication works, using Laravel Sanctum as an example. But don’t worry—these concepts apply to almost every backend framework, whether you’re using Node.js, Django, Rails, or anything else.
By the end of this article, you’ll understand:
- Why we use tokens instead of passwords for every request
- What those weird token strings actually mean
- Why hashing matters for security
- The difference between passwords, tokens, and sessions
Let’s dive in!
Why can’t we just send the password with every API request?
Let’s start with a simple question: Why can’t we just send the password with every API request?
Imagine if every time you wanted to check your email, post on social media, or order food, you had to type your password. Not only would this be annoying, but it would be incredibly dangerous:
- Your password would be sent across the internet hundreds of times per day
- Any compromised network could steal your password
- Every server log would contain your password
- A single data breach would expose your password to everyone
The solution? We verify your password once during login, then give you a temporary “access card” (called a token) that you can use for everything else.
This is exactly how hotels work, you show your ID at check-in (password), then use a key card (token) to access your room and hotel facilities.
Understanding Laravel Sanctum Token Format
When you log in to a Laravel API using Sanctum, you might see a token that looks like this:
3|6YB3U9oRN6uTV6uPgPy33ryP2aScgmvQ7ixvOqYr06470e28Breaking Down the Token Format
This token has two parts separated by a pipe (|):
[Token ID] | [Random String]
↓ ↓
3 | 6YB3U9oRN6uTV...Part 1: Token ID (before the |)
- This is the record ID in the database (personal_access_tokens table)
3means this is the 3rd token ever created- It’s like a reference number that helps the server find the token quickly
Part 2: Plain Text Token (after the |)
- This is a long random string
- This is the actual “secret” that proves you’re authorized
- This string only appears ONCE when the token is first created
- After that, you’ll never see the original string again
Why Does the Token Change Every Time You Login?
You might notice that every time you call /api/login, you get a different token:
// First login
"token": "2|6YB1U9oRN6uOV6uPgPy33ryP2aScgmvQ7ixvOqYr0647..."
// Second login
"token": "3|6YB3U9oRN6uTV6uPgPy33ryP2aScgmvQ7ixvOqYr06470e28"This is by design. Here’s what happens:
- Each login creates a brand new token
- Old tokens remain valid (unless you explicitly revoke them)
- This allows you to be logged in on multiple devices simultaneously
Think about it: You can be logged into Netflix on your phone, laptop, and TV at the same time. Each device has its own token!
The Three Key Concepts
Before we go further, let’s define the three main concepts clearly:
1. Password
- What it is: Your secret credential that proves your identity
- When you use it: Only during the initial login
- Where it’s stored: In the database (but hashed—more on this later)
- Analogy: Your passport or ID card
2. Token
- What it is: A temporary “access card” that proves you’re authorized
- When you use it: For every API request after login
- Where it’s stored:
- Client side: The full token (e.g.,
3|6YB3U9oRN...) - Server side: Only a hashed version
- Client side: The full token (e.g.,
- Analogy: A hotel key card
3. Session
- What it is: The server’s memory that you’re currently logged in
- When it exists: From login until logout or expiration
- Where it’s stored: Server-side (in database, Redis, or memory)
- Analogy: The hotel’s computer system that knows you’re checked in
The Hotel Analogy: Understanding the Complete Flow
Let me explain authentication using a detailed hotel analogy. This will make everything crystal clear!
Checking Into a Hotel
Imagine you’re checking into a hotel. Here’s what happens:
Step 1: Check-In (Login)
You: "Hi, I have a reservation."
Receptionist: "Can I see your ID please?"
You: *Shows passport*
Receptionist: *Verifies your identity in the computer*
Receptionist: "Welcome! Here's your room key card."In API terms:
POST /api/login
{
"email": "john@example.com",
"password": "MySecretPassword123"
}
Response:
{
"token": "3|6YB3U9oRN6uTV6uPgPy33ryP2aScgmvQ7ixvOqYr06470e28"
}Step 2: Using Hotel Facilities (API Requests)
You want to:
- Enter your room → *Tap key card* → Door opens
- Access the gym → *Tap key card* → Gate opens
- Use the pool → *Tap key card* → Access granted
- Take the elevator → *Tap key card* → Elevator activated Notice: You never show your passport again! You just use the key card.
In API terms:
// Get user profile
GET /api/user
Headers: {
"Authorization": "Bearer 3|6YB3U9oRN6uTV6uPgPy33ryP2aScgmvQ7ixvOqYr06470e28"
}
// Place an order
POST /api/orders
Headers: {
"Authorization": "Bearer 3|6YB3U9oRN6uTV6uPgPy33ryP2aScgmvQ7ixvOqYr06470e28"
}
Body: { "items": [...] }
// Update profile
PUT /api/user/profile
Headers: {
"Authorization": "Bearer 3|6YB3U9oRN6uTV6uPgPy33ryP2aScgmvQ7ixvOqYr06470e28"
}Step 3: Check-Out (Logout)
You: "I'm checking out."
Receptionist: *Deactivates your key card*
Receptionist: "Thank you for staying with us!"In API terms:
POST /api/logout
Headers: {
"Authorization": "Bearer 3|6YB3U9oRN6uTV6uPgPy33ryP2aScgmvQ7ixvOqYr06470e28"
}
Response:
{
"message": "Logged out successfully"
}After logout, your token is revoked and can’t be used anymore.
Why Use a Key Card Instead of Your Passport?
Imagine if there were no key cards:
Every single time you wanted to do something:
- Enter your room → Show passport to security → Security verifies → You enter
- Use the gym → Show passport to staff → Staff verifies → You enter
- Use the pool → Show passport to attendant → Attendant verifies → You enter
Problems with this approach:
- Security Risk: Your passport gets photocopied 50 times a day. What if a dishonest staff member copies it?
- Privacy Issue: Every hotel employee sees your personal information repeatedly.
- Slow & Inefficient: Every access requires manual verification.
- If Lost: If you lose your passport in the hotel, you’re in big trouble! Getting a new passport takes weeks.
With a key card system:
- Security: Your passport is shown only once. The key card can be replaced instantly if lost.
- Privacy: Staff don’t see your personal details every time you access facilities.
- Fast: Just tap the card—instant access.
- Easy Recovery: Lost your card? Get a new one in 2 minutes without affecting your identity.
This is exactly why we use tokens instead of passwords!
How Hashing Keeps You Safe?
Now let’s talk about one of the most important security concepts: hashing.
Why Tokens Look Different in the Database?
When you receive a token from the API:
Response: "3|6YB3U9oRN6uTV6uPgPy33ryP2aScgmvQ7ixvOqYr06470e28"But when you check the database (personal_access_tokens table):
id: 3
token: 79723d93d034910a3a89d5952b2bb739cb2879092b7b3e17a0176a5dce21817a
Why are they different?
Let’s Understanding Hashing!
Hashing is a one-way mathematical function that transforms data into a fixed-length string. Here’s how it works:
Input: 6YB3U9oRN6uTV6uPgPy33ryP2aScgmvQ7ixvOqYr06470e28
↓
[SHA-256 Hash Function]
↓
Output: 79723d93d034910a3a89d5952b2bb739cb2879092b7b3e17a0176a5dce21817aKey properties of hashing:
- One-way: You can’t reverse a hash back to the original
- Deterministic: Same input always gives same output
- Unique: Different inputs give different outputs (with extremely high probability)
- Fixed length: Regardless of input size, output is always the same length
The Security Flow
When you login (token is created):
1. Server generates random token string:
"6YB3U9oRN6uTV6uPgPy33ryP2aScgmvQ7ixvOqYr06470e28"
2. Server hashes the token and saves this to database: "79723d93..." (hashed)
3. Server sends full token to client:
"3|6YB3U9oRN6uTV6uPgPy33ryP2aScgmvQ7ixvOqYr06470e28"
4. Client saves token for future requestsWhen you make an API request with the token:
1. Client sends:
Authorization: Bearer 3|6YB3U9oRN6uTV6uPgPy33ryP2aScgmvQ7ixvOqYr06470e28
2. Server extracts:
ID: 3
Token string: 6YB3U9oRN6uTV6uPgPy33ryP2aScgmvQ7ixvOqYr06470e28
3. Server hashes the token string from client:
SHA-256("6YB3U9oRN...") = 79723d93d034910a3a89d5952b2bb739cb2879092b7b3e17a0176a5dce21817a
4. Server finds record with id=3 in database:
Stored hash: 79723d93d034910a3a89d5952b2bb739cb2879092b7b3e17a0176a5dce21817a
5. Server compares:
Computed hash == Stored hash?
Return:
YES → Request authorized
NO → 401 Unauthenticated
But Wait, If Hackers Get the Database, Can’t They See Everything?
This is a common point of confusion. Let me explain:
Scenario: Database Gets Hacked
Hacker gains access to your database and sees:
personal_access_tokens table:
id | user_id | token (hash) | created_at
---|---------|-------------------------------------------|------------
1 | 5 | a3d5f82bc9e4... | 2024-11-13
2 | 3 | 79723d93d034... | 2024-11-13users table:
id | name | email | password (hash) | phone
---|----------|------------------------|---------------------|--------
3 | John Doe | john@example.com | $2y$10$abcd... | 555-0123
5 | Jane | jane@example.com | $2y$10$efgh... | 555-0456What the Hacker CAN Do?
- See user personal data (name, email, phone)
- See business data (orders, products, etc.)
- See hashed passwords and tokens
What the Hacker CANNOT Do?
- Cannot login as users (doesn’t know the original password)
- Cannot use the API (doesn’t know the original token string)
- Cannot directly access user accounts
Why Hashing Matters? The Comparison
Without Hashing (Plain Text Storage)
If tokens were stored as plain text:
Database:
id | token (plain text)
---|------------------------------------------
3 | 6YB3U9oRN6uTV6uPgPy33ryP2aScgmvQ7ixvOqYr06470e28Hacker can immediately:
curl -X POST https://api.example.com/orders \
-H "Authorization: Bearer 6YB3U9oRN6uTV6uPgPy33ryP2aScgmvQ7ixvOqYr06470e28" \
-d '{"steal": "everything"}'
SUCCESS! Hacker now has full access!With Hashing (Best Practice)
Database stores:
id | token (hash)
---|------------------------------------------
3 | 79723d93d034910a3a89d5952b2bb739cb2879092b7b3e17a0176a5dce21817aHacker tries:
curl -X POST https://api.example.com/orders \
-H "Authorization: Bearer 79723d93d034910a3a89d5952b2bb739cb2879092b7b3e17a0176a5dce21817a" \
-d '{"steal": "everything"}'
FAILED! 401 UnauthenticatedThe hacker has the hash, but cannot reverse it to get the original token string!
Advanced Concepts
Token Expiration
Tokens can have an expiration time for added security:
// Create token that expires in 24 hours
$token = $user->createToken('auth_token', ['*'], now()->addHours(24));How it works:
Token created: Nov 13, 2024, 10:00 AM
Expiration: Nov 14, 2024, 10:00 AM
Timeline:
10:00 AM (Nov 13) → Token created
11:00 AM (Nov 13) → Request Valid
05:00 PM (Nov 13) → Request Valid
09:59 AM (Nov 14) → Request Valid (1 minute before expiration)
10:01 AM (Nov 14) → Request 401 ExpiredHotel analogy: Your key card stops working after checkout time.
Activity-Based Timeout
Some systems invalidate tokens after a period of inactivity:
Last activity: Nov 13, 10:00 AM
Timeout period: 2 hours
Timeline:
10:00 AM → Make request (updates last activity)
11:00 AM → Make request (updates last activity)
11:30 AM → (no activity)
12:00 PM → (no activity)
12:30 PM → (no activity - 1.5 hours since last activity)
01:30 PM → Make request 401 (2+ hours of inactivity)Hotel analogy: If you don’t use your key card for 2 hours, the system assumes you’ve left and deactivates it.
Refresh Tokens
For better security, some systems use two types of tokens:
- Access Token (short-lived, 15 minutes)
- Used for API requests
- Expires quickly
- Refresh Token (long-lived, 7 days)
- Used to get new access tokens
- Stored securely, not sent with every request
Flow:
// 1. Login - Get both tokens
POST /api/login
Response: {
"access_token": "3|abc123...", // Expires in 15 min
"refresh_token": "4|xyz789...", // Expires in 7 days
"expires_in": 900 // 15 minutes
}
// 2. Make requests with access token (works for 15 min)
GET /api/user
Headers: { "Authorization": "Bearer 3|abc123..." }
// 3. After 15 min, access token expires
GET /api/user
Headers: { "Authorization": "Bearer 3|abc123..." }
Response: 401 Expired
// 4. Use refresh token to get new access token
POST /api/refresh
{
"refresh_token": "4|xyz789..."
}
Response: {
"access_token": "5|def456...", // New access token!
"expires_in": 900
}
// 5. Continue making requests with new access token
GET /api/user
Headers: { "Authorization": "Bearer 5|def456..." }
Success!Benefits:
- If access token is stolen, it’s only valid for 15 minutes
- Refresh token is used rarely, so less exposure
- Better security without constant re-login
Hotel analogy:
- Access token = Key card (expires quickly)
- Refresh token = Golden card (lets you get new key cards without going to reception)
Token Revocation
Sometimes you need to invalidate tokens before they expire:
// Revoke current token (logout)
POST /api/logout
// Revoke all tokens (logout from all devices)
POST /api/logout-all-devices
// Revoke specific token
DELETE /api/tokens/3Use cases:
- User logs out
- User changes password (invalidate all existing sessions)
- Suspicious activity detected
- User reports device stolen
Hotel analogy: Reporting your key card as lost/stolen—it gets deactivated immediately.
Multi-Device Support
Laravel Sanctum naturally supports multiple devices:
User logs in from:
- iPhone → Gets token 1
- Laptop → Gets token 2
- iPad → Gets token 3
Each token is independent:
- Logout from iPhone → Only token 1 is deleted
- Laptop and iPad still work fineDatabase looks like:
id | user_id | token_hash | name | created_at
---|---------|-------------------|-----------|------------
1 | 5 | abc123... | iPhone | Nov 13
2 | 5 | def456... | Laptop | Nov 13
3 | 5 | ghi789... | iPad | Nov 14All three tokens work simultaneously!
Different Authentication Systems
While we focused on Laravel Sanctum, these concepts apply everywhere:

Now go build something awesome—and keep it secure!
Happy coding!!!
