.NET Core  

Beginner's Guide: Authentication & Authorization in Modern Applications

Privacy has never been optional. Every time you sign into an app, order food, or use a service, you are sharing pieces of your identity, your email, your name, sometimes even your location or payment details.

And yet, most of the time, we don't really think about what happens behind the scenes when we click "Login".

Authentication vs Authorization (Still the Most Confused Concepts)

A simple real-life example still explains this best: imagine you walk into a hotel.

At the reception, they check your identity and confirm your reservation. That's authentication (proving that you are who you claim to be).

Now, imagine you try to access the VIP lounge or a restricted area. Even if you are a guest, you might not be allowed in. That's authorization (deciding what you are allowed to do).

Even today, many systems fail not because authentication is weak, but because authorization is poorly designed.

How We Used to Do It (and Why It Changed)

A few years ago, most applications relied heavily on session-based authentication.

You logged in with a username and password. The server stored your session. Every request depended on that session being valid.

That worked well for simple applications, but it didn't scale well for:

  • Mobile apps

  • Microservices

  • Distributed systems

  • APIs

This is where token-based authentication became the standard.

Tokens: Your Digital Identity Card

Think of a token as a digital ID card.

Instead of asking the server "who are you?" on every request, you just present your token.

The server trusts the token and allows or denies access based on what's inside it.

What is a JWT

A JWT (JSON Web Token) is a compact, secure way to transmit information between systems.

But here's an important correction from older explanations:

  • A JWT is not inherently secure by itself

  • It is signed (and sometimes encrypted) to ensure integrity

You can think of it as a sealed envelope:

  • Anyone can read it (unless encrypted)

  • But no one can tamper with it without breaking the seal

JWT Structure (Still the Same, Still Important)

A JWT has three parts:

Header
Contains metadata like the signing algorithm (e.g., HS256, RS256)

Payload
Contains claims (data about the user)

Common claims include:

  • sub: user identifier

  • iss: issuer (who created the token)

  • aud: audience (who the token is for)

  • exp: expiration time

Signature

Ensures the token hasn't been modified

One important clarification: The signing algorithm is defined in the Header, not the Signature

OAuth2 and OpenID Connect

OAuth2

OAuth2 is not an authentication protocol.

It is an authorization framework that allows one application to access resources from another on behalf of a user.

Example:

When you click "Login with Google", your app does NOT get your password.

Instead:

  • Google authenticates you

  • Google gives your app a token

  • Your app uses that token to access limited user data

So OAuth2 is about: delegating access, not identifying the user

OpenID Connect (OIDC)

OpenID Connect sits on top of OAuth2 and adds authentication.

It introduces the concept of an ID Token, which is usually a JWT.

This ID token tells your application who the user is

So in modern systems:

  • OAuth2 : authorization (access to resources)

  • OIDC : authentication (identity)

Common Mistakes (Still Happening Today)

Even in modern systems, developers still fall into these traps:

1. Putting sensitive data in JWT payload

JWTs are not encrypted by default. Never store passwords or secrets.

2. Not validating tokens properly

Always validate:

  • Signature

  • Expiration

  • Issuer

  • Audience

3. Long-lived tokens

Short-lived access tokens + refresh tokens are the safer approach.

ASP.NET Core Identity

ASP.NET Core Identity is the default membership system provided by Microsoft. It handles everything related to user management.

  • User registration and login

  • Password hashing (secure by default)

  • Roles and claims

  • Token generation

For APIs and modern apps, JWT authentication is the standard.

Instead of sessions, you issue a token after login.

Basic JWT Setup

builder.Services.AddAuthentication("Bearer")
    .AddJwtBearer("Bearer", options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,

            ValidIssuer = "test-app",
            ValidAudience = "test-app",
            IssuerSigningKey = new SymmetricSecurityKey(
                Encoding.UTF8.GetBytes("your-secret-key"))
        };
    });

Authorization (Roles, Claims, Policies)

As mentioned before, authentication tells you who the user is, but authorization defines what they can do.

Role-based authorization

[Authorize(Roles = "Admin")]
public IActionResult AdminOnly()
{
    return Ok("Admin access");
}

Claims-based authorization

[Authorize(Policy = "CanEdit")]
public IActionResult Edit()
{
    return Ok();
}
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("CanEdit", policy =>
        policy.RequireClaim("permission", "edit"));
});

In modern systems, claims-based or policy-based authorization is preferred over simple roles because it’s more flexible.

ASP.NET Core Identity is an interesting topic that i will share about more videos and tutorials for better understanding how it works in the future.