audience while creating JWT tokennew JwtSecurityToken or disable it's validation in options.TokenValidationParameters: ValidateAudience = falseauth service) and audience (or multiple audiences) is something that should verify the user authentication and claims (roles, for example)/close audiencenew JwtSecurityTokenoptions.TokenValidationParametersValidateAudience = falseauth serviceusing System.IdentityModel.Tokens.Jwt;
using System.Text;
using LadaServ.Application.Common;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using TestAuth.WebApi;
using TestAuth.WebApi.Entities;
using TestAuth.WebApi.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.Configure<MyOptions>(builder.Configuration.GetSection(nameof(MyOptions)));
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); // => remove default claims
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.SaveToken = true;
options.TokenValidationParameters = new()
{
ValidateIssuer = true,
ValidIssuer = builder.Configuration["MyOptions:JWT_ISSUER"],
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(
builder.Configuration["MyOptions:SECRET_KEY"]!))
};
});
builder.Services.AddAuthorization();
builder.Services.AddIdentity<AppUser, AppRole>()
.AddEntityFrameworkStores<AppDbContext>();
builder.Services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlite(builder.Configuration.GetConnectionString("DefaultConnection"));
});
builder.Services.AddScoped<JwtService>();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using LadaServ.Application.Common;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using TestAuth.WebApi.Entities;
namespace TestAuth.WebApi.Services;
public class JwtService
{
private readonly UserManager<AppUser> _userManager;
private readonly IOptions<MyOptions> _options;
public JwtService(UserManager<AppUser> userManager, IOptions<MyOptions> options)
{
_userManager = userManager;
_options = options;
}
public async Task<string> GenerateJwtToken(AppUser user)
{
var claims = new Claim[]
{
new (JwtRegisteredClaimNames.NameId, user.Id.ToString()),
new (JwtRegisteredClaimNames.Email, user.Email!),
new (ClaimTypes.Role, user.Role.ToString()),
new (JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};
var authSecret = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_options.Value.SECRET_KEY));
var tokenObject = new JwtSecurityToken(
issuer: _options.Value.JWT_ISSUER,
expires: DateTime.Now.AddDays(60),
claims: claims,
signingCredentials: new SigningCredentials(authSecret, SecurityAlgorithms.HmacSha256)
);
string token = new JwtSecurityTokenHandler().WriteToken(tokenObject);
return token;
}
}using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using TestAuth.WebApi.DTOs;
using TestAuth.WebApi.Entities;
using TestAuth.WebApi.Services;
namespace TestAuth.WebApi.Controllers;
[ApiController]
[AllowAnonymous]
[Route("accounts")]
public class AccountController : ControllerBase
{
private readonly UserManager<AppUser> _userManager;
private readonly RoleManager<AppRole> _roleManager;
private readonly JwtService _jwtService;
public AccountController(UserManager<AppUser> userManager, RoleManager<AppRole> roleManager, JwtService jwtService)
{
_userManager = userManager;
_roleManager = roleManager;
_jwtService = jwtService;
}
[HttpPost]
public async Task<IActionResult> Register([FromBody] RegisterDto registerDto)
{
var user = new AppUser()
{
Role = RoleEnum.User,
Email = registerDto.Email
};
var result = await _userManager.CreateAsync(user, registerDto.Password!);
var roleExist = await _roleManager.RoleExistsAsync(user.Role.ToString());
if (!roleExist)
{
await _roleManager.CreateAsync(new AppRole { Name = user.Role.ToString() });
}
await _userManager.AddToRoleAsync(user, user.Role.ToString());
var token = await _jwtService.GenerateJwtToken(user!);
return new JsonResult(new { email = user.Email, token = token });
}
}using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using TestAuth.WebApi.Entities;
namespace TestAuth.WebApi.Controllers;
[ApiController]
[Route("test")]
public class TestController : ControllerBase
{
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[HttpGet("get1")]
public string Get1() => "authed";
[Authorize(Roles = nameof(RoleEnum.User))]
[HttpGet("get2")]
public string Get2() => "user";
[AllowAnonymous]
[HttpGet("get3")]
public string Get3() => "anonymous";
}{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"MyOptions": {
"JWT_ISSUER": "https://localhost:7267",
"SECRET_KEY": "my-32-character-ultra-secure-and-ultra-long-secret-AAAultra-long-secret-AAA"
},
"ConnectionStrings": {
"DefaultConnection": "Data Source=helloapp.db"
}
}