i am creating a token and it does not accept the token I created, the error code 401 returns
appsettings.json
{
"TokenOptions": {
"Audience": "https://localhost:7098",
"Issuer": "https://localhost:7098",
"AccessTokenExpiration": 500,
"SecurityKey": "mysecretkeymysecretkey"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
TokenOptions.cs
namespace Shared.Utilities.Security.Jwt;
public class TokenOptions
{
public string Audience { get; set; }
public string Issuer { get; set; }
public int AccessTokenExpiration { get; set; }
public string SecurityKey { get; set; }
}
JwtHelper.cs
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using Shared.Entities.Concrete;
using Shared.Extensions;
using Shared.Utilities.Security.Encyption;
namespace Shared.Utilities.Security.Jwt;
public class JwtHelper : ITokenHelper
{
public IConfiguration Configuration { get; }
private TokenOptions _tokenOptions;
private DateTime _accessTokenExpiration;
public JwtHelper(IConfiguration configuration)
{
Configuration = configuration;
_tokenOptions = Configuration.GetSection(key: "TokenOptions").Get<TokenOptions>();
}
public AccessToken CreateToken(User user, List<OperationClaim> operationClaims)
{
_accessTokenExpiration = DateTime.Now.AddMinutes(_tokenOptions.AccessTokenExpiration);
var securityKey = SecurityKeyHelper.CreateSecurityKey(_tokenOptions.SecurityKey);
var signingCredentials = SigningCredentialsHelper.CreateSigningCredentials(securityKey);
var jwt = CreateJwtSecurityToken(_tokenOptions, user, signingCredentials, operationClaims);
var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
var token = jwtSecurityTokenHandler.WriteToken(jwt);
return new AccessToken
{
Token = token,
Expiration = _accessTokenExpiration
};
}
public JwtSecurityToken CreateJwtSecurityToken(TokenOptions tokenOptions, User user, SigningCredentials signingCredentials, List<OperationClaim> operationClaims)
{
var Jwt = new JwtSecurityToken(
issuer: tokenOptions.Issuer,
audience: tokenOptions.Audience,
expires: _accessTokenExpiration,
notBefore: DateTime.Now,
claims: SetClains(user, operationClaims),
signingCredentials: signingCredentials
);
return Jwt;
}
private IEnumerable<Claim> SetClains(User user, List<OperationClaim> operationClaims)
{
var claims = new List<Claim>();
claims.AddNameIdentifier(user.Id.ToString());
claims.AddEmail(user.Email);
claims.AddName($"{user.FirstName} {user.LastName}");
claims.AddRole(operationClaims.Select(c => c.Name).ToArray());
return claims;
}
}
ITokenHelper.cs
using Shared.Entities.Concrete;
namespace Shared.Utilities.Security.Jwt;
public interface ITokenHelper
{
AccessToken CreateToken(User user, List<OperationClaim> operationClaims);
}
AccessToken.cs
namespace Shared.Utilities.Security.Jwt
{
public class AccessToken
{
public string Token { get; set; }
public DateTime Expiration { get; set; }
}
}
HashingHelper.cs
using System.Text;
namespace Shared.Utilities.Security.Hashing;
public class HashingHelper
{
public static void CreatePasswordHash(string password, out byte[] passwordHash, out byte[] passwordSalt)
{
using (var hmac = new System.Security.Cryptography.HMACSHA512())
{
passwordSalt = hmac.Key;
passwordHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(password));
}
}
public static bool VerifyPasswordHash(string password, byte[] passwordHash, byte[] passwordSalt)
{
using (var hmac = new System.Security.Cryptography.HMACSHA512(passwordSalt))
{
var computedHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(password));
for (int i = 0; i < computedHash.Length; i )
{
if (computedHash[i] != passwordHash[i])
{
return false;
}
}
}
return true;
}
}
SigningCredentialsHelper.cs
using Microsoft.IdentityModel.Tokens;
namespace Shared.Utilities.Security.Encyption;
public class SigningCredentialsHelper
{
public static SigningCredentials CreateSigningCredentials(SecurityKey securityKey)
{
return new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
}
}
SecurityKeyHelper.cs
using System.Text;
using Microsoft.IdentityModel.Tokens;
namespace Shared.Utilities.Security.Encyption;
public class SecurityKeyHelper
{
public static SecurityKey CreateSecurityKey(string securityKey)
{
return new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityKey));
}
}
ClaimExtensions.cs
using System.Security.Claims;
using Microsoft.IdentityModel.JsonWebTokens;
namespace Shared.Extensions;
public static class ClaimExtensions
{
public static void AddEmail(this ICollection<Claim> claims, string email)
{
claims.Add(new Claim(type: JwtRegisteredClaimNames.Email, value: email));
}
public static void AddName(this ICollection<Claim> claims, string name)
{
claims.Add(new Claim(type: ClaimTypes.Name, value: name));
}
public static void AddNameIdentifier(this ICollection<Claim> claims, string nameIdentifier)
{
claims.Add(new Claim(type: ClaimTypes.NameIdentifier, value: nameIdentifier));
}
public static void AddRole(this ICollection<Claim> claims, string[] roles)
{
roles.ToList().ForEach(role => claims.Add(new Claim(type: ClaimTypes.Role, value: role)));
}
}
AutofacBusinessModule.cs
using Autofac;
using Data.Abstract;
using Data.Concrete.EntityFramework;
using Services.Abstract;
using Services.Concrete;
using Shared.Utilities.Security.Jwt;
namespace Services.DependencyResolvers.Autofac
{
public class AutofacBusinessModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<ProductManager>().As<IProductService>();
builder.RegisterType<EfProductRepository>().As<IProductRepository>();
builder.RegisterType<CategoryManager>().As<ICategoryService>();
builder.RegisterType<EfCategoryRepository>().As<ICategoryRepository>();
builder.RegisterType<UserManager>().As<IUserService>();
builder.RegisterType<EfUserRepository>().As<IUserRepository>();
builder.RegisterType<AuthManager>().As<IAuthService>();
builder.RegisterType<JwtHelper>().As<ITokenHelper>();
}
}
}
AuthController.cs
using Entities.Dtos;
using Microsoft.AspNetCore.Mvc;
using Services.Abstract;
namespace WebAPI.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class AuthController : ControllerBase
{
private IAuthService _authService;
public AuthController(IAuthService authService)
{
_authService = authService;
}
[HttpPost("login")]
public async Task<IActionResult> Login(UserForLoginDto userForLoginDto)
{
var userToLogin = await _authService.Login(userForLoginDto);
if (!userToLogin.IsSuccess)
return BadRequest(userToLogin.Message);
var result = await _authService.CreateAccessToken(userToLogin.Data);
if (result.IsSuccess)
return Ok(result.Data);
return BadRequest(result.Message);
}
[HttpPost("register")]
public async Task<IActionResult> Register(UserForRegisterDto userForRegisterDto)
{
var userExists = await _authService.UserExists(userForRegisterDto.Email);
if (!userExists.IsSuccess)
return BadRequest(userExists.Message);
var registerResult = await _authService.Register(userForRegisterDto);
var result = await _authService.CreateAccessToken(registerResult.Data);
if (result.IsSuccess)
return Ok(result.Data);
return BadRequest(result.Message);
}
}
}
Program.cs
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Services.DependencyResolvers.Autofac;
using Shared.Utilities.Security.Encyption;
using Shared.Utilities.Security.Jwt;
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory()).ConfigureContainer<ContainerBuilder>(builder =>
{
builder.RegisterModule(new AutofacBusinessModule());
});
var tokenOptions = builder.Configuration.GetSection(key: "TokenOptions").Get<TokenOptions>();
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = tokenOptions.Issuer,
ValidAudience = tokenOptions.Audience,
IssuerSigningKey = SecurityKeyHelper.CreateSecurityKey(tokenOptions.SecurityKey),
ValidateIssuerSigningKey = true,
ValidateAudience = true,
ValidateIssuer = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
});
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
CreateTokenPostman.cs enter image description here
401ErrorPostman.cs enter image description here
CodePudding user response:
I have compared your code with this repo. And I find something, it maybe useful to you.
You should change your code like below.
options.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = tokenOptions.Issuer,
ValidAudience = tokenOptions.Audience,
IssuerSigningKey = SecurityKeyHelper.CreateSecurityKey(tokenOptions.SecurityKey),
ValidateIssuerSigningKey = true,
ValidateAudience = true,
ValidateIssuer = true,
ValidateLifetime = true,
//ClockSkew = TimeSpan.Zero
};
Or
options.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = tokenOptions.Issuer,
ValidAudience = tokenOptions.Audience,
IssuerSigningKey = SecurityKeyHelper.CreateSecurityKey(tokenOptions.SecurityKey),
ValidateIssuerSigningKey = true,
ValidateAudience = true,
ValidateIssuer = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero,
// add this line
RequireExpirationTime = true
};
CodePudding user response:
Thanks. I found the error related to the latest version of jwt. the error was fixed when i downloaded the old version of jwt