I am trying to apply JWT Authorization in web application. Every time my application returns 401(Un-authorized), even after passing Authorize header attribute with valid bearer token.
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContextPool<SchoolCMS.Service.Context.SchoolCMSContext>(options
=> options.UseMySQL(Configuration["Data:ConnectionString"]));
services.AddControllersWithViews();
services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
services.AddSession(options => {
options.IdleTimeout = TimeSpan.FromMinutes(60);
});
services.AddSignalR();
services.AddMvc(option => option.EnableEndpointRouting = false);
//Provide a secret key to Encrypt and Decrypt the Token
var SecretKey = Encoding.ASCII.GetBytes("YourKey-2374-OFFKDI940NG7:56753253-tyuw-5769-
0921-kfirox29zoxv");
//Configure JWT Token Authentication - JRozario
services.AddAuthentication(auth =>
{
auth.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
auth.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(token =>
{
token.RequireHttpsMetadata = false;
token.SaveToken = true;
token.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(SecretKey),
ValidateIssuer = true,
//Usually this is your application base URL - JRozario
ValidIssuer = "http://localhost:45092/",
ValidateAudience = true,
//Here we are creating and using JWT within the same application. In this case base URL is fine
//If the JWT is created using a web service then this could be the consumer URL
ValidAudience = "http://localhost:45092/",
RequireExpirationTime = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
});
services.AddHttpContextAccessor();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseSession();
app.Use(async (context, next) =>
{
var JWToken = context.Session.GetString("JWToken");
if (!string.IsNullOrEmpty(JWToken))
{
context.Request.Headers.Add("Authorization", "Bearer " + JWToken);
}
await next();
});
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Dashboard}/{action=Index}/{id?}");
});
//app.UsePathBase(new PathString("/schoolapp-web"));//When merging code to master branch comment this line
var httpContextAccessor = app.ApplicationServices.GetRequiredService<IHttpContextAccessor>();
SessionUtility.Configure(httpContextAccessor);
app.ApplicationServices.GetService<AssignDailyTaskService>();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Account}/{action=Login}/{id?}");
});
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<NotificationHub>("/NotificationHub", options =>
{
options.Transports =
HttpTransportType.WebSockets |
HttpTransportType.LongPolling;
});
});
}
Account Controller
[HttpPost]
public async Task<ActionResult> Login(Login model)
{
if (ModelState.IsValid)
{
UserModel user = await _userService.ValidateUser(model);
if (user != null)
{
if (user.emailverify)
{
if (user.IsApprove)
{
if (user.IsLock)
{
@ViewBag.Message = "Your account has locked. Please contact
administrator.";
return View(model);
}
else if (user.ApplicationStartDate == null)
{
CustomResponseModel response = await
_applicantService.LockUnlockApplicant(user.PKUserID);
if (response.IsSuccess)
{
user.ApplicationStartDate = DateTime.Now.Date;
user.ApplicationEndDate = DateTime.Now.Date.AddDays(45);
}
}
var jwtSettings = _configuration.GetSection("JwtAuthorizationSettings");
var token = _tokenGenerator.GenerateJwtToken(
jwtSettings["SecretKey"],
jwtSettings["Issuer"],
jwtSettings["Audience"],
new List<Claim>
{
new Claim(ClaimTypes.Name, Convert.ToString(user.FirstName)),
new Claim(ClaimTypes.NameIdentifier, Convert.ToString(user.FirstName)),
new Claim(ClaimTypes.Email, Convert.ToString(user.EmailID)),
new Claim("UserId", Convert.ToString(user.PKUserID)),
},
Convert.ToInt32(jwtSettings["ExpirationTimeInMinute"]));
SessionUtility.SetObject("JWToken", token);
SessionUtility.SetObject("CurrentUser", user);
return RedirectToAction("Index", "Dashboard");
}
}
}
}
return View(model);
}
Generate Jwt Token
public string GenerateJwtToken(string secretKey, string issuer, string audience, IList<Claim> claims,
int expirationTimeInMinute)
{
//Provide the security key which was given in the JWToken configuration in Startup.cs
var key = Encoding.ASCII.GetBytes("YourKey-2374-OFFKDI940NG7:56753253-tyuw-5769-0921-
kfirox29zoxv");
//Generate Token for user - JRozario
var JWToken = new JwtSecurityToken(
issuer: "http://localhost:45092/",
audience: "http://localhost:45092/",
claims: claims,
notBefore: new DateTimeOffset(DateTime.Now).DateTime,
expires: new DateTimeOffset(DateTime.Now.AddDays(1)).DateTime,
//Using HS256 Algorithm to encrypt Token - JRozario
signingCredentials: new SigningCredentials(new SymmetricSecurityKey(key),
SecurityAlgorithms.HmacSha256Signature)
);
var token = new JwtSecurityTokenHandler().WriteToken(JWToken);
return token;
}
I am still getting User.Identity.Claims count 0. I don't know where I am doing the mistake. Please suggest me the valid solution.
I took refernce from this Url :- https://www.codeproject.com/Articles/5247609/ASP-NET-CORE-Token-Authentication-and-Authorizat-2
This code project is working, but unfortunately not working on my web application.
Thanks in advance!!