A few months ago, I was building a personal project, a billing app. I had the design, features, development and UI design. But when it came to authentication and authorization, I realized I had no idea how to do it securely. I could create a login page, but was it safe?
Let me walk you through my journey of how I Secured My App with Authentication and Authorization step by step, with real-world examples and the mistakes I made (so you don’t have to).

🧱 Step 1: Understanding the Basics
Before writing the code, I had to get two concepts clear:
- Authentication = Proving who the user is
- Authorization = Deciding what the user can do
Think of it like checking into a hotel:
- Showing your ID at the front desk is an authentication
- Getting the keycard to access only your room is authorization
🔑 Step 2: Choosing the Right Authentication Method
At first, I hardcoded a simple login system with usernames and passwords in plain text. 🙈That is the biggest mistake I’ve ever made. I quickly realised how risky that was.
I quickly get a decision and decided to use ASP.NET Core Identity, which gives you secure user management out of the box. You can also use JWT (JSON Web Tokens) if you’re building an API.
Here’s how I did it with JWT in a .NET 6 Web API:
🔧 Install NuGet packages:
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
🛡️ Configure JWT in Program.cs
:
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "MyApp",
ValidAudience = "MyAppUsers",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SuperSecretKey12345!"))
};
});
✍️ Generating a JWT token:
public string GenerateJwtToken(string username)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes("SuperSecretKey12345!");
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, username) }),
Expires = DateTime.UtcNow.AddHours(1),
Issuer = "MyApp",
Audience = "MyAppUsers",
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
🧾 Step 3: Protecting Endpoints (Authorization)
Once users are authenticated, I have to restrict what they can access.
[Authorize]
[HttpGet("tasks")]
public IActionResult GetTasks()
{
var username = User.Identity?.Name;
var tasks = _taskService.GetTasksForUser(username);
return Ok(tasks);
}
Want role-based access? It’s just as easy:
[Authorize(Roles = "Admin")]
[HttpPost("admin-only")]
public IActionResult AdminAction()
{
return Ok("You are an admin!");
}
And don’t forget to add roles when creating users or issuing tokens.
🔒 Step 4: Securing the Passwords
Remember how I said I once stored passwords in plain text? 🤦♂️ Yeah, don’t ever do that.
I used ASP.NET Identity’s built-in hashing system. But if you’re rolling your own:
string hashedPassword = BCrypt.Net.BCrypt.HashPassword("user_password");
// To verify:
bool isValid = BCrypt.Net.BCrypt.Verify("user_password", hashedPassword);
This saved me from worrying about attacks.
If I could go back and tell myself one thing when I started, it would be: “Start secure, stay secure.” Now go forth and build safe apps that users can trust
🔐 Authentication and Authorization Security Checklist
✅ Basic Setup
- Use HTTPS (force it with redirection in your app)
- Choose an appropriate auth method (JWT, OAuth, Identity)
- Store passwords using strong hashing (e.g., BCrypt or ASP.NET Identity)
✅ Authentication
- Generate access tokens securely (JWT with expiry)
- Use a strong signing key (minimum 256-bit)
- Include essential claims (e.g., username, roles)
- Prevent token replay attacks (store token identifiers if needed)
✅ Authorization
- Use
[Authorize]
attribute for protected endpoints - Apply role-based or policy-based authorization where needed
- Never expose sensitive routes without checks
✅ Token Management
- Use short-lived access tokens (e.g., 1 hour)
- Issue refresh tokens for long sessions
- Store tokens securely on the client (HttpOnly cookies or secure storage)
- Revoke tokens on logout or password reset
✅ Advanced Security
- Implement 2FA for sensitive accounts
- Add rate limiting to login endpoints
- Detect and lock accounts on multiple failed logins
- Use security headers (CSP, X-Content-Type-Options, etc.)
✅ Code Practices
- Never log sensitive data (passwords, tokens)
- Validate all input (even authenticated ones)
- Keep dependencies updated
- Monitor for vulnerabilities