Fundamental Backend Authentication Explained (Laravel)

Posted on

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|6YB3U9oRN6uTV6uPgPy33ryP2aScgmvQ7ixvOqYr06470e28

Breaking 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)
  • 3 means 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:

  1. Each login creates a brand new token
  2. Old tokens remain valid (unless you explicitly revoke them)
  3. 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
  • 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:

  1. Security Risk: Your passport gets photocopied 50 times a day. What if a dishonest staff member copies it?
  2. Privacy Issue: Every hotel employee sees your personal information repeatedly.
  3. Slow & Inefficient: Every access requires manual verification.
  4. 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:

  1. Security: Your passport is shown only once. The key card can be replaced instantly if lost.
  2. Privacy: Staff don’t see your personal details every time you access facilities.
  3. Fast: Just tap the card—instant access.
  4. 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: 79723d93d034910a3a89d5952b2bb739cb2879092b7b3e17a0176a5dce21817a

Key properties of hashing:

  1. One-way: You can’t reverse a hash back to the original
  2. Deterministic: Same input always gives same output
  3. Unique: Different inputs give different outputs (with extremely high probability)
  4. 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 requests

When 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-13

users 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-0456

What 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  | 6YB3U9oRN6uTV6uPgPy33ryP2aScgmvQ7ixvOqYr06470e28

Hacker 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  | 79723d93d034910a3a89d5952b2bb739cb2879092b7b3e17a0176a5dce21817a

Hacker tries:

curl -X POST https://api.example.com/orders \
  -H "Authorization: Bearer 79723d93d034910a3a89d5952b2bb739cb2879092b7b3e17a0176a5dce21817a" \
  -d '{"steal": "everything"}'

FAILED! 401 Unauthenticated

The 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 Expired

Hotel 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:

  1. Access Token (short-lived, 15 minutes)
    • Used for API requests
    • Expires quickly
  2. 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/3

Use 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 fine

Database 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 14

All three tokens work simultaneously!

Different Authentication Systems

While we focused on Laravel Sanctum, these concepts apply everywhere:

Authentication Systems

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