coding•TUTORIAL

What Actually Happens When You Click “Login”?

Follow one login request from the browser to the database—and back again.

The Pathak
The Pathak@pathak
•
Sep 23, 2026
•
5 min read
What Actually Happens When You Click “Login”?
A login button looks like one of the simplest things on a website. You type your email, enter your password, click Login, and suddenly you're inside your account. But that single click can trigger an entire chain of events:

Browser → API → Validation → Database → Password Verification → Authentication → Response → Protected Resource

Understanding that chain is one of the easiest ways to stop thinking of web development as a collection of disconnected technologies.

1. It Starts in the Browser

When you submit a login form, your frontend collects the credentials. For example:
const handleLogin = async () => {
  const response = await fetch("/api/login", {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      email,
      password
    })
  });
};
The browser doesn't directly talk to your database. That's an important distinction. The frontend sends an HTTP request to your backend. The backend is responsible for deciding what to do with that request.

2. The Request Travels to the API

The browser sends something similar to:
POST /api/login
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "mypassword"
}
The server receives the request and enters the authentication flow. At this point, the server should not blindly trust anything coming from the browser. The browser is controlled by the user. That means the backend must validate the incoming data independently.

3. Validation Happens Before the Database

The server can check whether the email exists in the expected format and whether the password field is present. A schema validator such as Zod can make this explicit:
const LoginSchema = z.object({
  email: z.string().email(),
  password: z.string().min(8)
});
If the request doesn't satisfy the schema, the server can reject it before performing unnecessary database work. This is more than convenience. TypeScript protects your code. Runtime validation protects your application from actual input.

4. Now the Database Gets Involved

Once the request passes validation, the backend needs to find the account. Conceptually:
const user = await db.user.findUnique({
  where: {
    email
  }
});
Notice what the server is looking for. It isn't searching for:
email + password
Instead, it finds the user by an identifier such as their email address. The password verification happens separately.

5. The Password Should Never Be Stored as Plain Text

A secure application should never store:
password: "mypassword"
in the database. Instead, the password is transformed into a cryptographic hash before storage. During registration:
Password
   ↓
Hashing algorithm
   ↓
Password hash
   ↓
Database
During login:
Entered password
   ↓
Verification against stored hash
   ↓
Match / Reject
The server doesn't need to recover the original password. It needs to determine whether the supplied password matches the stored credential.

6. The Server Decides Whether You Are Authenticated

If the credentials are valid, the server needs a way to remember that this browser has successfully authenticated. Two common approaches are sessions and tokens such as JWTs. With a session-based system, the server maintains session state and gives the browser a session identifier. With JWT-based authentication, the server can issue a signed token containing claims that the server can later verify. The important part isn't choosing whichever one sounds more modern. The important part is understanding the security model you're implementing.

7. The Browser Receives the Result

A successful response might look conceptually like:
{
  "message": "Login successful"
}
Depending on the authentication architecture, the authentication state may be represented through a secure cookie or another mechanism. For browser applications, authentication cookies should generally be configured with appropriate security attributes such as HttpOnly, Secure, and an appropriate SameSite policy. The exact configuration depends on the architecture.

8. Login Is Not the End

This is where the process becomes interesting. Suppose the user now visits:
GET /api/profile
The browser sends its authentication information with the request. The server verifies it. Only then does it return protected data. The flow becomes:
Browser
   ↓
GET /api/profile
   ↓
Authentication check
   ↓
Identify user
   ↓
Authorization check
   ↓
Database
   ↓
Protected response
Authentication answers: “Who are you?” Authorization answers: “Are you allowed to do this?” Those are different questions.

9. Where Things Can Go Wrong

A login system can fail at almost every stage. The request might contain invalid data. The account might not exist. The password might be incorrect. The authentication token might be expired. The session might be invalid. The user might be authenticated but not authorized to access a particular resource. The database might be unavailable. The frontend might incorrectly interpret a successful response. That's why authentication isn't just a login form. It's a chain of trust.

The Complete Journey

The next time you click a login button, think beyond the button.
User enters credentials
        ↓
Frontend collects input
        ↓
HTTP request
        ↓
Backend receives request
        ↓
Runtime validation
        ↓
Database lookup
        ↓
Password verification
        ↓
Authentication state created
        ↓
Response returned
        ↓
Browser stores/uses authentication state
        ↓
Future requests are authenticated
        ↓
Authorization determines access
The UI is only the visible part. Behind it is a conversation between several different systems, each responsible for a specific part of the trust chain.

The Part Worth Remembering

You don't need to memorize every authentication library to understand login systems. Remember the boundaries. The frontend collects information.
The API receives and validates it.
The database stores account data.
Password hashing protects stored credentials.
Authentication establishes identity.
Authorization controls access. Once those boundaries make sense, frameworks become much easier to understand. Instead of thinking, “This is how NextAuth works” or “This is how JWT works,” you can ask the more useful question: “What problem is this piece solving in the authentication flow?” That's the point where authentication stops looking like magic and starts looking like engineering.
#Auth#web dev#React#APIs#JWT#Backend#Security
The Pathak
The Pathak@pathak

Lead Software Architect, Writer & Thinker exploring Technology, Science, Code, Ideas, and Words.

0

Discussion (0)

Type @ to tag readers

Sign in to join the discussion, reply, and tag authors.

No comments yet. Be the first to start the discussion!

More from CODING

The LeetCode Era Is Changing: What Happens When AI Enters the Coding Interview?
CODING•ARTICLE

The LeetCode Era Is Changing: What Happens When AI Enters the Coding Interview?

For years, aspiring software engineers have spent months solving algorithmic problems to prepare for technical interviews. Now, Google is experimenting with AI-assisted code comprehension, while HackerRank is questioning the interview culture it helped popularize. The change raises a bigger question: when AI can generate code, should hiring focus less on writing it and more on understanding, debugging, and validating it?

The Pathak1 min read
Your API Is Slow. Your Database Might Not Be.
CODING•TUTORIAL

Your API Is Slow. Your Database Might Not Be.

A slow API does not automatically mean a slow database. Before rewriting queries or adding indexes, measure the entire request path and find exactly where the time is being spent.

The Pathak7 min read
HTTP Just Got a New Method: Meet QUERY
CODING•ARTICLE

HTTP Just Got a New Method: Meet QUERY

HTTP has a new method: QUERY. It is designed for complex, read-only queries that don't fit comfortably inside a URL, allowing structured query data to be sent in the request body while retaining safe and idempotent semantics.

The Pathak6 min read