Mudit Rajput

Oct 25, 2025 • 10 min read

Learn about Authorization and Authentication — Backend First Principal

Learn about Authorization and Authentication — Backend First Principal

Hello everyone! This is my first article on Medium, and in it, I’ve tried to explain the fundamental backend concepts in simple language using examples. I’ve written this article in a way that even beginners can easily understand.

One more request — if you find any issues or errors in this article, please let me know in the comments. I’d really appreciate your feedback!

Press enter or click to view image in full size

What do you mean by Authentication?

Try to think of authentication as who the user is. The process of logging in is known as authentication.

Suppose you visit a website, create an account, and then try to log in — this process of verifying your identity is called authentication.

But wait, there’s more to learn about authentication!
Let’s understand how the backend handles this process and what some of the common best practices developers follow are. We’ll discuss all these decisions in detail.

Stateful Authentication (Explained Simply)

1. Login Flow

Let’s keep it simple. When you try to log in to any website, you enter your email and password. Now, what happens next?

Your email and password are sent to the server.
Forget for now how the data is sent or received — let’s just understand what happens after that. The server receives your email and password, then validates your details:

  • It checks if the email format is correct.

  • It checks if the password is correct.

If your credentials are invalid, the server sends an error response.
If they are valid, we proceed further.

2. Generating a session Id

In the process of stateful authentication, the server generates a session ID (a random string). You can think of this session ID as a short-term memory for that logged-in user.

Now you might be curious:

  1. How does a session ID look?

  2. Where is it stored?

  3. Why do we store it separately?

Let’s answer these one by one 👇

How does a session ID look?

A session ID usually contains random characters and numbers, like:
sessionId : abc123xyz

Where do we store the session ID?

The session ID can be stored in:

  • Database (SQL/MongoDB)

  • Redis (recommended, because sessions have a short lifespan)

Should we store the session ID in the user table?

This is an interesting question.
Always store the session ID in a separate table, not in the users table.

3. Understanding expiresAt (TTL)

You can see the expiresAt field in the table above.
It represents the TTL (Time To Live) — that is, how long the session ID will remain valid. Now a question arises:
Does the session ID delete automatically?
It depends on where you store it.

Case 1: Redis

When you use Redis, you can set a TTL value.
Redis automatically deletes the key when it expires — no manual deletion is needed.

Case 2: Database (SQL/MongoDB)

If you store sessions in a regular database, you can either:

  • Delete them manually when the user logs out, or

  • Use a cron job that periodically deletes expired sessions.

4. Sending the Cookie to the Client

After the session ID is generated and stored, the server sets this session ID inside a cookie. You can think of it as the session ID being wrapped inside a cookie. Then, the server sends this cookie in the response to the client. On the client side, the cookie is stored in the browser. You can view it in Developer Tools → Application → Cookies.

5. Making an Authenticated Request

Now, suppose the user wants to access their profile and hits an API endpoint like /api/user/me. Here’s an example request

fetch("/api/profile", {
 method: "GET",
 credentials: "include"
});

credentials: "include" means send the cookie even for cross-origin requests.(We’ll discuss more about CORS in a separate article.

6. Server Validates the Session

On the server side we extract the sessionId as follow:

const sessionId = req.cookies.sessionId;

The server reads the cookie and extracts the session ID. Then, it checks the session store (Redis or database) to find a matching session.

Example:

sessionId = "abcd1234" 
→ { userId: 101, email: "[email protected]", expiresAt: "6:00 PM" }

If the server finds this session and it hasn’t expired → it’s a valid session.
If it’s not found or has expired → it’s invalid.

Once validated, the server can use the stored user information:

const user = { userId: 101, email: "[email protected]" };

Now, the server can proceed — for example, to fetch the user’s profile.

Step 7: Handling Invalid Sessions

If authentication fails, an “Unauthorized” response is sent: return res.status(401).json({ message: “Unauthorized” }). This demonstrates that stateful authentication primarily relies on a sessionId.

Stateless Authentication (Explained Simply)

Firstly, let’s understand what stateless means. Stateless means there is no session or state stored on the server. The server doesn’t keep any user-related information between requests.

So, the question arises: 👉 If the server doesn’t store anything about the user, how does it know who is making the request?

The answer is JWT (JSON Web Token).

What is JWT?

A JWT is a long string divided into three main parts:
1. Header
2. payload
3. Signature

Structure of JWT

xxxxx.yyyyy.zzzzz
  • Header (xxxxx) → Contains metadata, like which algorithm is used (e.g., HS256)

  • Payload (yyyyy) → Contains user data (e.g., { "id": 1, "email": "[email protected]" })

  • Signature (zzzzz) → A proof that the token was generated and signed by the server.

Payload

The payload holds the user information that we want to store inside the JWT — for example, userId and userEmail.

Why do we store user info in the token?
Because later, when we verify or decode the JWT, we can extract the user information without querying the database again.

Flow of Stateless Authentication

  1. When a user tries to log in, they send their email and password to the server.

  2. The server receives this data (for example, in req.body). Whether the email format is correct, whether the uses exist in the database or not.

  3. If the email is not found or credentials are invalid, the server sends back:

res.status(400).json({ message: "Invalid credentials" });
If the user exists and credentials are correct, the next step is token generation.

4. Next step is generating the JWT
We use the jsonwebtoken library to generate a token.

import jwt from "jsonwebtoken";
const user = { id: 1, email: "[email protected]" };
const token = jwt.sign(user, process.env.JWT_SECRET_KEY, { expiresIn: "1h" });
console.log(token);

--------------
Payload → The user object
Secret Key (JWT_SECRET_KEY) → Used by the server to sign the token

Why is the Secret Key Required?

It’s used to digitally sign the token. This signature ensures that no one can tamper with the token. Only the server knows this key, so only the server can verify the token’s authenticity.

The secret key is stored safely in the .env file and never shared publicly.

5. After generating the JWT, we send it to the client with a success message. We can send the token in two ways:
Option 1 : Inside a Cookie (Recommended):

res.cookie("token", token, { httpOnly: true });
res.status(200).json({ msg: "User successfully logged in" });

Option 2: In Response Body:

res.status(200).json({ msg: "User successfully logged in", token });

If you send it this way, you can store the token in local Storage:

6. When the user wants to access a protected API, for example:

GET /api/cart/info

you have to send the token in the Authorization header:

Authorization: Bearer <token>

The server extracts and verifies the token:

const token = req.headers.authorization.split(" ")[1];
const decoded = jwt.verify(token, process.env.JWT_SECRET_KEY);
console.log(decoded); // { id: 1, email: "[email protected]", iat: ..., exp: ... }

Once verified, the server gets the user info (like userId) from decoded and fetches the related data (like user’s cart) from the database.

Finally, the server sends the response back to the client.

Summary

In stateless authentication, the server doesn’t store any user session data. Instead, it uses a JWT (JSON Web Token) to identify the user.

A JWT has three parts — Header, Payload, and Signature.

  • Header → Defines the algorithm (e.g., HS256)

  • Payload → Stores user info (like id, email)

  • Signature → Proves the token is issued by the server

When a user logs in:

  1. Server verifies the credentials.

  2. If valid, it generates a JWT using jwt.sign(payload, secretKey).

  3. The token is sent to the client (via cookie or response).

  4. The client sends this token in headers for future requests.

  5. The server verifies the token using jwt.verify(token, secretKey) and extracts user info.

Since the server doesn’t store any session — all info is verified from the token itself — this makes it stateless authentication.

OAuth (Open Authorization)

Now let’s talk about another method of authentication — OAuth. This method is not exactly a login system like traditional email-password login.
Instead of creating a new account, users can log in using platforms such as Google, GitHub, or Facebook.

OAuth allows one service (your app) to access another service’s data on behalf of the user — securely, without sharing passwords.

Wherever you see options like “Sign up with Google” or “Login with GitHub”, OAuth is being used.
Example : Suppose you built a website and added a “Sign in with Google” button. When the user clicks that button, your app uses OAuth 2.0 to request permission from Google to access the user’s basic info (like name and email).

Flow of OAuth

  1. User Clicks “Sign in with Google” Your app redirects the user to Google’s OAuth URL, for example:

https://accounts.google.com/o/oauth2/auth?client_id=123&redirect_uri=https://mywebsite.com/callback&scope=email profile

Here:

  • client_id → Your app’s unique ID provided by Google

  • redirect_uri → The URL where Google will send the user back after login

  • scope → The type of data your app wants (e.g., email, profile)

2. User Grants Permission Google shows a consent page:

“This website wants to access your email and profile information.”

If the user clicks “Allow,” Google confirms that this user has approved your app.

3. Google Sends Authorization Code : After approval, Google redirects the user back to your app’s redirect URI.

https://mywebsite.com/callback?code=XYZ123
Here code=XYZ123 is the authorization code, which is temporary.
Your app will exchange this code for an access token in the next step.

4. Exchange the Code for Access Token : Exchange the Code for Access Token

POST https://oauth2.googleapis.com/token
{
 code: "XYZ123",
 client_id: "your_client_id",
 client_secret: "your_client_secret",
 redirect_uri: "https://mywebsite.com/callback",
 grant_type: "authorization_code"
}

Google verifies everything and responds with:

{
 "access_token": "abcd1234",
 "refresh_token": "efgh5678",
 "expires_in": 3600
}

Now, your app has an access token, which can be used to request user data.

5. Get User Info Using Access Token : Your server now calls Google’s API using the access token:

GET https://www.googleapis.com/oauth2/v2/userinfo
Authorization: Bearer abcd1234

Google responds with the user’s details:

{
 "id": "12345",
 "email": "[email protected]",
 "name": "xyz"
}

You can now use this information to log the user into your app — without ever seeing or storing their password. You can also store the user’s email or Google ID in your database for future logins.

6. Refresh Token
When the access token expires (for example, after 1 hour), you can use the refresh token to request a new access token — so the user doesn’t need to log in again.

We can discuss the detailed difference between the access token and refresh token in another article.

Summary :

OAuth allows users to log in or share data securely between services — without exposing their password. It’s widely used for features like “Login with Google” or connecting apps like GitHub → VS Code, YouTube → Analytics, etc.

Authorization

Now let’s move forward and talk about authorization. Suppose you have logged in successfully — that means the authentication process is complete.
Now let’s understand what authorization means.

Once you are authenticated, authorization decides what actions or resources you are allowed to access. The website already knows who you are — your name, your email, etc.Think of it like the website saying:

“Hey, I know who you are, but what are you allowed to do?”

For example, when you visit an e-commerce website as a user, you can view products, add them to the cart, and make purchases. But if you log in as an admin, you can delete users, add new products, change product names or prices, and perform other administrative actions.

That level of access control is what we call authorization.

In the database schema, we usually store a role field (for example, as an enum with values like user or admin). When a user logs in, we check their role to determine what they’re allowed to do.

Some APIs are protected — normal users cannot access them, only admins can. This is where authorization is applied.

This is all about the Authorization and Authentication.
Thank you.

Join Mudit on Peerlist!

Join amazing folks like Mudit and thousands of other builders on Peerlist.

peerlist.io/

It’s available... this username is available! 😃

Claim your username before it's too late!

This username is already taken, you’re a little late.😐

0

4

0