A Complete Full-Stack Project Tutorial
Using Angular + ASP.NET Core + SQL Server
This tutorial covers everything needed to build a real authentication system used in modern web applications.
What You Will Build
A full end-to-end system including:
User Registration
User Login
JWT Authentication
Password Hashing
Protected API Endpoints
Angular AuthService for token handling
Angular Login + Register UI
Route Guards to protect pages
Auto-attach token to HTTP requests
Redirect if user not authenticated
This is the foundation of almost every real web application.
Project Breakdown
We will structure this tutorial into 3 main parts:
Backend: ASP.NET Core Web API
Frontend: Angular Application
Connecting the two
Let's begin.
PART 1: BACKEND (ASP.NET Core Web API)
Step 1: Create a new Web API project
dotnet new webapi -n AuthAPI
cd AuthAPI
Step 2: Install Required Packages
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
dotnet add package BCrypt.Net-Next
Step 3: Create SQL Server Database
CREATE DATABASE AuthDB;
Step 4: Create User Model
Create Models/User.cs:
public class User
{
public int Id { get; set; }
public string FullName { get; set; }
public string Email { get; set; }
public string PasswordHash { get; set; }
}
We store password hashes, not plain text.
Step 5: Add DbContext
File: Data/AppDbContext.cs
using Microsoft.EntityFrameworkCore;
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
public DbSet<User> Users { get; set; }
}
Step 6: Configure SQL Server
In appsettings.json:
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=AuthDB;Trusted_Connection=True;"
}
Step 7: Register DbContext
In Program.cs:
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
Step 8: Create JWT Service
File: Services/JwtService.cs
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
using System.Security.Claims;
using System.Text;
public class JwtService
{
private readonly IConfiguration _config;
public JwtService(IConfiguration config)
{
_config = config;
}
public string GenerateToken(string email)
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(ClaimTypes.Email, email)
};
var token = new JwtSecurityToken(
issuer: _config["Jwt:Issuer"],
audience: _config["Jwt:Audience"],
claims: claims,
expires: DateTime.Now.AddHours(1),
signingCredentials: creds);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
Step 9: Add JWT Config in appsettings.json
"Jwt": {
"Key": "VerySecretKey123456789",
"Issuer": "AuthAPI",
"Audience": "AuthAPIUser"
}
Step 10: Configure JWT Middleware
In Program.cs:
var key = Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]);
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(key)
};
});
builder.Services.AddScoped<JwtService>();
Middleware:
app.UseAuthentication();
app.UseAuthorization();
Step 11: Create Auth Controller
File: Controllers/AuthController.cs
Registration Endpoint
[HttpPost("register")]
public async Task<IActionResult> Register(UserDto request)
{
if (_context.Users.Any(x => x.Email == request.Email))
return BadRequest(new { Message = "Email already exists" });
var user = new User
{
FullName = request.FullName,
Email = request.Email,
PasswordHash = BCrypt.Net.BCrypt.HashPassword(request.Password)
};
_context.Users.Add(user);
await _context.SaveChangesAsync();
return Ok(new { Message = "User Registered Successfully" });
}
Login Endpoint
[HttpPost("login")]
public IActionResult Login(LoginDto request)
{
var user = _context.Users.FirstOrDefault(x => x.Email == request.Email);
if (user == null)
return Unauthorized(new { Message = "Invalid credentials" });
if (!BCrypt.Net.BCrypt.Verify(request.Password, user.PasswordHash))
return Unauthorized(new { Message = "Invalid credentials" });
var token = _jwt.GenerateToken(user.Email);
return Ok(new { Token = token });
}
Protected Endpoint
[Authorize]
[HttpGet("profile")]
public IActionResult Profile()
{
return Ok(new { Message = "Access granted to protected data" });
}
Step 12: Create DTOs
File: Models/UserDto.cs
public class UserDto
{
public string FullName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}

Join the conversation! Your thoughts help the community grow.