**Here is my View that I want to secure using the JWTBEARER. **
` [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public IActionResult Privacy()
{
var token = HttpContext.Request.Headers["Authorization"].FirstOrDefault();
Debug.WriteLine($"Received token: {token}");
if (token != null && token.StartsWith("Bearer "))
{
Debug.WriteLine($"Token content: {token}");
// Rest of your code
return View();
}
else
{
// Handle the case where the token is missing or in an invalid format
return Unauthorized();
}
}
`
and this is my javascript that is being used to authenticate the login and that if it's a success it will redirect on the Home/Privacy view.
` <script>
$(document).ready(function () {
$('#login-button').click(function () {
console.log('login button clicked.');
var username = $('#username').val();
var password = $('#password').val();
var formData = new FormData();
formData.append("UserName", username);
formData.append("Password", password);
$.ajax({
url: '/api/Account/Login',
method: 'POST',
processData: false, // Important: Prevent jQuery from processing data
contentType: false, // Important: Prevent jQuery from setting content type
data: formData,
success: function (data) {
console.log('Login success:', data);
if (data.token) {
// Store the received JWT token securely
localStorage.setItem('jwtToken', data.token);
console.log('JWT token stored:', data.token);
var jwtToken = localStorage.getItem('jwtToken').trim();
if (!jwtToken.startsWith('Bearer ')) {
jwtToken = 'Bearer ' + jwtToken;
}
$.ajax({
url: '/Home/Privacy',
method: 'GET', // Assuming it's a GET request
headers: {
'Authorization': jwtToken
},
success: function (privacyData) {
// Handle the successful response for 'Home/Privacy'
window.location.href = '/Home/Privacy';
},
error: function (xhr, textStatus, errorThrown) {
// Handle the error response for 'Home/Privacy'
console.error('Error accessing Home/Privacy:', textStatus, errorThrown);
alert('Failed to access Home/Privacy. Please check your authentication.');
}
});
} else {
console.warn('Login failed:', data.error);
alert('Login failed. Please check your credentials.');
}
},
error: function (xhr, textStatus, errorThrown) {
console.error('Login error occurred:', textStatus, errorThrown);
alert('Login failed. Please check your credentials.');
}
});
});
});
</script>
`
now the problem is that even though I checked the returned type and it match I'm receiving error 401 after being redirected to the Home/Privacy. The token match but it's still giving that error.
My login api on Account
`
[HttpPost]
[Route("Login")]
public IActionResult Login([FromForm] AuthenticationRequest authenticationRequest)
{
try
{
var authResult = _jwtAuthenticationManager.Authenticate(authenticationRequest.UserName, authenticationRequest.Password);
if (authResult == null)
{
Debug.WriteLine("Authentication failed.");
return Unauthorized();
}
else
{
Debug.WriteLine("Authentication successful. Token: " + authResult.token);
return Ok(authResult);
}
}
catch (Exception ex)
{
// Log the exception details
Console.WriteLine($"Exception: {ex.Message}");
return StatusCode(500, "An error occurred while processing the request.");
}
}
}
}`
Here is my AuthenticationManager where the token creation and the where the username and password condition is written that is being called on the javascript using ajax
`public class JwtAuthenticationManager
{
private readonly IConfiguration _configuration;
public JwtAuthenticationManager(IConfiguration configuration)
{
_configuration = configuration;
}
public JwtAuthResponse Authenticate(string userName, string password)
{
// Validating the Username and Password
string storedUsername = _configuration["MySecrets:Username"];
string storedPassword = _configuration["MySecrets:Password"];
// Add logging to see the values
Debug.WriteLine($"Input Username: {userName}, Stored Username: {storedUsername}");
Debug.WriteLine($"Input Password: {password}, Stored Password: {storedPassword}");
if (userName != storedUsername || password != storedPassword)
{
Console.WriteLine("Authentication failed.");
return null;
}
var tokenExpiryTimeStamp = DateTime.Now.AddMinutes(Constants.JWT_TOKEN_VALIDITY_MINS);
var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
var tokenKey = Encoding.ASCII.GetBytes(Constants.JWT_SECURITY_KEY);
var securityTokenDescriptor = new SecurityTokenDescriptor
{
Subject = new System.Security.Claims.ClaimsIdentity(new List<Claim>
{
new Claim("username", userName),
}),
// Expiration of the token
Expires = tokenExpiryTimeStamp,
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(tokenKey), SecurityAlgorithms.HmacSha256Signature)
};
var securityToken = jwtSecurityTokenHandler.CreateToken(securityTokenDescriptor);
var token = jwtSecurityTokenHandler.WriteToken(securityToken);
return new JwtAuthResponse
{
token = token,
user_name = userName,
expires_in = (int)tokenExpiryTimeStamp.Subtract(DateTime.Now).TotalSeconds
};
}
}
}
`
lastly my program.cs I'm using .net core also.
I think i've searched enough before asking this problem here, and I can't think of any errors that I have made. The headers and token is being sent successfully but its still returning error 401
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
{
options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
});
builder.Configuration.AddUserSecrets<Program>();
//jwt authentication
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Constants.JWT_SECURITY_KEY)), // Use the correct key
ValidateIssuer = false,
ValidateAudience = false,
};
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.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.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();