DEV Community

Cover image for Authentication vs Authorization: What Is the Difference?
Tanu Priya
Tanu Priya

Posted on

Authentication vs Authorization: What Is the Difference?

You log into an application with your email and password.

The application checks your credentials and lets you in.

Now you open the admin dashboard.

The application checks something else: are you actually allowed to use the admin dashboard?

These two checks are related, but they aren't the same.

Authentication → Who are you?

Authorization  → What are you allowed to do?
Enter fullscreen mode Exit fullscreen mode

A simple real-world example makes the difference easier to understand.

When you show your ID at an office entrance, security verifies that you are actually you.

That's authentication.

Once you're inside, your ID might allow you to enter some rooms but not others.

That's authorization.

The same idea is used inside web applications.

Authentication: Who Are You?

Authentication is about verifying a user's identity.

A typical login request might look like:

POST /api/login
Enter fullscreen mode Exit fullscreen mode

with:

{
  "email": "alex@example.com",
  "password": "mypassword"
}
Enter fullscreen mode Exit fullscreen mode

The backend receives the credentials and verifies them.

Conceptually:

Email + Password
       ↓
    Backend
       ↓
Find user
       ↓
Verify password
       ↓
Credentials valid?
       ↓
Authenticated
Enter fullscreen mode Exit fullscreen mode

If everything checks out, the server now knows:

User ID: 42
Email: alex@example.com
Enter fullscreen mode Exit fullscreen mode

But there is a problem.

HTTP is stateless.

The next request doesn't automatically know that the previous login succeeded.

That's where sessions, cookies, and tokens come in.

Sessions: Remembering the User

One common solution is a server-side session.

After successful login, the server creates a session:

User 42
   ↓
Session created
   ↓
Session ID = abc123
Enter fullscreen mode Exit fullscreen mode

The server stores something similar to:

abc123 → User 42
Enter fullscreen mode Exit fullscreen mode

The browser then needs to send that session ID with future requests.

This is commonly done using a cookie.

Login
  ↓
Create session
  ↓
Send session cookie
  ↓
Browser stores cookie
  ↓
Future requests include cookie
Enter fullscreen mode Exit fullscreen mode

For example:

Set-Cookie: session_id=abc123
Enter fullscreen mode Exit fullscreen mode

Later:

Cookie: session_id=abc123
Enter fullscreen mode Exit fullscreen mode

The server can look up the session and determine which user is making the request.

So the flow becomes:

Browser
   ↓
Cookie
   ↓
Session ID
   ↓
Server
   ↓
User 42
Enter fullscreen mode Exit fullscreen mode

The browser doesn't need to send the user's password again.

What About Tokens?

Another common approach is token-based authentication.

After login, the server generates a token and gives it to the client.

Login
  ↓
Verify credentials
  ↓
Generate token
  ↓
Send token
Enter fullscreen mode Exit fullscreen mode

The client can then include the token with API requests.

A common format is:

Authorization: Bearer <token>
Enter fullscreen mode Exit fullscreen mode

The backend receives the token and verifies it.

If the token is valid, the backend can identify the user and continue processing the request.

This approach is particularly common with APIs and applications where the client and backend are separate systems.

Sessions vs Tokens

The difference is mainly about where authentication state is maintained.

With a traditional session:

Client
  ↓
Session ID
  ↓
Server
  ↓
Session data
Enter fullscreen mode Exit fullscreen mode

With a self-contained token:

Client
  ↓
Token
  ↓
Server validates token
Enter fullscreen mode Exit fullscreen mode

Neither approach is universally better.

The choice depends on the application, security requirements, infrastructure, and how authentication needs to be managed.

Authorization: What Can the User Do?

Now let's say Alex has successfully logged in.

Authentication is complete.

But Alex tries:

GET /api/admin/users
Enter fullscreen mode Exit fullscreen mode

Being logged in doesn't automatically give Alex access to this endpoint.

The backend needs to ask:

Does this user have permission to access this resource?

For example:

Alex
Role: user

/admin/users
     ↓
Access denied
Enter fullscreen mode Exit fullscreen mode

An administrator might have:

Sarah
Role: admin

/admin/users
     ↓
Access allowed
Enter fullscreen mode Exit fullscreen mode

That's authorization.

The complete flow looks like:

Request
   ↓
Authentication
   ↓
Who is the user?
   ↓
Authorization
   ↓
Is the user allowed?
   ↓
Business logic
Enter fullscreen mode Exit fullscreen mode

This distinction becomes especially important when building APIs.

Authentication and Authorization in Middleware

In a Node.js application, authentication and authorization are often separated into middleware.

For example:

function authenticate(req, res, next) {
    const token = req.headers.authorization;

    if (!token) {
        return res.status(401).json({
            message: "Authentication required"
        });
    }

    const user = verifyToken(token);

    if (!user) {
        return res.status(401).json({
            message: "Invalid token"
        });
    }

    req.user = user;

    next();
}
Enter fullscreen mode Exit fullscreen mode

The middleware identifies the user and attaches that information to the request.

Then authorization can happen separately:

function requireAdmin(req, res, next) {
    if (req.user.role !== "admin") {
        return res.status(403).json({
            message: "Access denied"
        });
    }

    next();
}
Enter fullscreen mode Exit fullscreen mode

The route can combine both:

app.get(
    "/admin/users",
    authenticate,
    requireAdmin,
    getUsers
);
Enter fullscreen mode Exit fullscreen mode

Now the request goes through two different checks.

GET /admin/users
       ↓
authenticate
       ↓
Who is this?
       ↓
requireAdmin
       ↓
Can they access this?
       ↓
getUsers
Enter fullscreen mode Exit fullscreen mode

That's a much cleaner design than putting all of the security logic inside every controller.

401 vs 403

You'll often see two status codes when working with protected APIs.

401 Unauthorized

The server doesn't have valid authentication information.

For example:

No token
Invalid token
Expired credentials
Enter fullscreen mode Exit fullscreen mode

Think:

"I don't know who you are."

403 Forbidden

The server knows who you are, but you don't have permission to perform the operation.

For example:

Logged in as normal user
        ↓
Trying to delete another user
        ↓
403 Forbidden
Enter fullscreen mode Exit fullscreen mode

Think:

"I know who you are, but you can't do this."

A simple way to remember it:

401 → Authentication problem

403 → Authorization problem
Enter fullscreen mode Exit fullscreen mode

Roles and Permissions

Authorization is often implemented using roles.

For example:

User
Admin
Moderator
Editor
Enter fullscreen mode Exit fullscreen mode

An admin might be allowed to:

Create users
Delete users
Manage settings
View reports
Enter fullscreen mode Exit fullscreen mode

while a normal user might only be able to:

View their profile
Create comments
View posts
Enter fullscreen mode Exit fullscreen mode

For larger applications, permissions can be more granular:

users:read
users:create
users:delete

posts:read
posts:update
posts:delete
Enter fullscreen mode Exit fullscreen mode

This makes it possible to give users exactly the permissions they need instead of relying entirely on broad roles.

Don't Trust the Frontend for Authorization

This is one of the most important points.

Suppose your frontend hides the delete button from normal users:

if (user.role === "admin") {
    showDeleteButton();
}
Enter fullscreen mode Exit fullscreen mode

That's good for the UI.

But it isn't a security mechanism.

A user can still manually send the request:

DELETE /api/users/123
Enter fullscreen mode Exit fullscreen mode

directly to your backend.

That's why authorization must happen on the server.

Frontend
   ↓
API Request
   ↓
Backend
   ↓
Authentication
   ↓
Authorization
   ↓
Allow / Reject
Enter fullscreen mode Exit fullscreen mode

The frontend decides what the user sees.

The backend decides what the user is actually allowed to do.

Where Passwords Fit In

Authentication often starts with a password, but passwords should not be stored directly in the database.

Instead, applications use password-hashing algorithms designed for secure password storage.

Conceptually:

Password
   ↓
Password hashing
   ↓
Stored password hash
Enter fullscreen mode Exit fullscreen mode

During login, the submitted password is verified against the stored hash.

The application should not need to retrieve the original password.

This is one of the basic security boundaries every authentication system needs to get right.

Putting Everything Together

A typical protected API request might look like this:

                    LOGIN
                      ↓
              Verify credentials
                      ↓
                Authentication
                      ↓
            Session / Cookie / Token
                      ↓
              Future API Request
                      ↓
                Authentication
                      ↓
                 Authorization
                      ↓
                 Controller
                      ↓
                  Database
                      ↓
                  Response
Enter fullscreen mode Exit fullscreen mode

Each part has a different job.

Authentication
→ Establish the user's identity

Authorization
→ Decide what that user can access
Enter fullscreen mode Exit fullscreen mode

Sessions, cookies, and tokens help the application maintain or carry authentication information between requests.

They don't decide what the user is allowed to do.

The Mental Model

Whenever you're building a protected API, ask two questions:

1. Who is making this request?

2. Is this user allowed to perform this action?
Enter fullscreen mode Exit fullscreen mode

The first question is authentication.

The second is authorization.

For example:

User logs in
     ↓
Authentication
     ↓
"I know who you are."
     ↓
User requests admin dashboard
     ↓
Authorization
     ↓
"I know who you are,
but are you allowed here?"
Enter fullscreen mode Exit fullscreen mode

That's the core difference.

Authentication establishes identity. Authorization controls access.

Once you understand that distinction, sessions, cookies, tokens, roles, permissions, 401, and 403 all start fitting into the same picture.

And when you're designing a backend, keeping authentication and authorization as separate responsibilities makes the security model much easier to reason about.

Top comments (0)