I have attribute [Authorize] on my action. I tried to authenticate my user with JWT token but getting error 401. Error 401
My Configuration
using FluentValidation;
using FluentValidation.AspNetCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.FileProviders;
using Server.Api.Extensions;
using Server.Api.Middlewares;
using Server.Domain.Interfaces;
using Server.Domain.Services;
using Server.Infrastructure;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("AveAnticaDbContextConnection") ?? throw new InvalidOperationException("Connection string 'AzureDbConnection' not found.");
ConfigurationManager configuration = builder.Configuration;
builder.Services.AddDbContext<AveAnticaDbContext>(x => x.UseSqlServer(connectionString));
builder.Services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
builder.Services.AddControllers();
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
builder.Services.AddFluentValidationAutoValidation();
builder.Services.AddValidatorsFromAssemblies(AppDomain.CurrentDomain.GetAssemblies());
builder.Services.AddScoped<IProductService, ProductService>();
builder.Services.AddScoped<IImageService, ImageService>();
builder.Services.AddScoped<ICategoryService, CategoryService>();
builder.Services.AddScoped<ILanguageService, LanguageService>();
builder.Services.AddScoped<ITagService, TagService>();
builder.Services.AddScoped<ILikesService, LikesService>();
builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddScoped<IAccountService, AccountService>();
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
builder.Services.AddAuthentication();
builder.Services.ConfigureIdentity();
builder.Services.ConfigureJWT(builder.Configuration);
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.ConfigureSwagger();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseCors(options =>
{
options.AllowAnyHeader();
options.AllowAnyMethod();
options.AllowAnyOrigin();
});
app.UseMiddleware<JwtTokenMiddleware>();
app.UseMiddleware<ExceptionMiddleware>();
app.UseHttpsRedirection();
//app.UseResponseCaching();
app.UseAuthentication();
app.UseAuthorization();
var directPath = "Uploads";//builder.Configuration.GetConnectionString("Path");
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, directPath)),
RequestPath = "/" + directPath
});
app.MapControllers();
app.Run();
Configuration extensions
public static class ServiceExtension
{
public static void ConfigureIdentity(this IServiceCollection services)
{
var builder = services.AddIdentity<Customer, IdentityRole>(o =>
{
o.Password.RequireDigit = false;
o.Password.RequireLowercase = false;
o.Password.RequireUppercase = false;
o.Password.RequireNonAlphanumeric = false;
o.User.RequireUniqueEmail = true;
})
.AddEntityFrameworkStores<AveAnticaDbContext>()
.AddDefaultTokenProviders();
}
public static void ConfigureJWT(this IServiceCollection services, IConfiguration configuration)
{
var jwtConfig = configuration.GetSection("JwtOptions");
var secretKey = jwtConfig["Key"];
services.AddAuthentication(opt =>
{
opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateLifetime = true,
ValidateAudience = true,
ValidateIssuerSigningKey = true,
ValidIssuer = jwtConfig["Issuer"],
ValidAudience = jwtConfig["Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey))
};
});
}
public static void ConfigureSwagger(this IServiceCollection services)
{
services.AddSwaggerGen(option =>
{
option.SwaggerDoc("v1", new OpenApiInfo { Title = "Demo API", Version = "v1" });
option.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
In = ParameterLocation.Header,
Description = "Please enter a valid token",
Name = "Authorization",
Type = SecuritySchemeType.Http,
BearerFormat = "JWT",
Scheme = "Bearer"
});
option.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type=ReferenceType.SecurityScheme,
Id="Bearer"
}
},
new string[]{}
}
});
});
}
}
My Account Service(Only functions that relates to token generation)
public async Task<string> CreateTokenAsync(Customer user)
{
var signingCredentials = GetSigningCredentials();
var claims = await GetClaims(user);
var tokenOptions = GenerateTokenOptions(signingCredentials, claims);
return new JwtSecurityTokenHandler().WriteToken(tokenOptions);
}
private SigningCredentials GetSigningCredentials()
{
var jwtConfig = configuration.GetSection("JwtOptions");
var key = Encoding.UTF8.GetBytes(jwtConfig["Key"]);
var secret = new SymmetricSecurityKey(key);
return new SigningCredentials(secret, SecurityAlgorithms.HmacSha256);
}
private async Task<List<Claim>> GetClaims(Customer user)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.UserName)
};
var roles = await userManager.GetRolesAsync(user);
foreach (var role in roles)
{
claims.Add(new Claim(ClaimTypes.Role, role));
}
return claims;
}
JWT Options
"JwtOptions": {
"Issuer": "AveAntica",
"Lifetime": 12,
"Audience": "AveAnticaAudience",
"Key": "1234234rearaeta4wa4rras4tra"
},
Also, you can visit my repository for more information:Repository
I tried different configurations. Also it doesn't matter if i use [Authorize] or [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)].
I know, that my token is delivered to the server and it is normal, at least decoded on some sites.
I download another project with +-similar code and similar configurations. It works correctly(I also checked and update nugets, it doesn`t changes the situation).
In your GenerateTokenOptions() :
Try to change audience: jwtSettings["Issuer"],
into audience: jwtSettings["Audience"],