0
I have a system for studies, totally decoupled the front-end of the back-end.
I implemented JWT+Bearer, however I log in by the controller and it returns the information with the token:
But when I inputo this token in the header it returns me unauthorized 401:
If you can help me I’ll be immensely grateful, I’m a long time hunting where I went wrong!
Worflow do setup:
STARTUP
namespace WebApiLivraria
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddDbContext<ApplicationContext>(options =>
options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection"))
);
services.AddScoped<IUnityOfWork, UnityOfWork>();
services.AddCors();
var key = Encoding.ASCII.GetBytes(Settings.SecretKey);
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}
).AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors(option => option.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()); ;
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseAuthentication();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
TOKENSERVICE
namespace WebApiLivraria.Services
{
public static class TokenService
{
public static string GenerateToken(User user)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(Settings.SecretKey);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.Name, user.Name.ToString()),
new Claim(ClaimTypes.Role, user.Role.ToString())
}),
Expires = DateTime.UtcNow.AddDays(5),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
}
}
BOOKCONTROLLER (WHICH GIVES ME THE ERROR)
namespace WebApiLivraria.Controllers
{
[Route("[controller]")]
[ApiController]
public class BookController : ControllerBase
{
private readonly IUnityOfWork _uof;
public BookController(IUnityOfWork uof)
{
_uof = uof;
}
[HttpGet]
[Authorize]
public async Task<ActionResult> GetBook()
{
ResultModelList<Book> resultModel = new ResultModelList<Book>();
var allBooks = await _uof.BookRepository.GetAsync();
resultModel.Models = new List<Book>(allBooks);
return Ok(resultModel);
}
LOGIN CONTROLLER
[HttpPost]
[Route("Login")]
public async Task<ActionResult<dynamic>> Authenticate([FromBody] User model)
{
ResultModel<TokenInfo> resultModel;
// Recupera o usuário
resultModel = await _accountBusiness.FindByUser(model);
// Verifica se o usuário existe
if (resultModel == null)
{
return NotFound(resultModel);
}
else
{
// Retorna os dados
return Ok(resultModel);
}
}
FINDBYUSER (CALLED BY LOGINCONTROLLER)
public async Task<ResultModel<TokenInfo>> FindByUser(User user)
{
ResultModel<TokenInfo> resultModel = new ResultModel<TokenInfo>();
try
{
(bool gonaLogin, User userTemp) = await _uof.UserRepository.UserIsInDb(user);
if (gonaLogin)
{
resultModel.Model = new TokenInfo();
// Gera o Token
var token = TokenService.GenerateToken(userTemp);
// Oculta a senha
userTemp.Password = "";
resultModel.Model.User = userTemp;
resultModel.Model.Token = token;
resultModel.SuccessMessage = "Logado com sucesso";
return resultModel;
}
else
{
resultModel.ErrorMessage = "Credenciais incorretas";
return resultModel;
}
}
catch (Exception ex)
{
resultModel.ErrorMessage = "Erro interno, contatar o administrador";
return resultModel;
}
finally
{
_uof.Dispose();
}
}
USERINDB (CALLED BY FINDBYUSER)
public async Task<(bool, User)> UserIsInDb(User user)
{
User userCount = await _context.User.Where(w => (w.Name == user.Name || w.Email == user.Name) && w.Password == user.Password).FirstOrDefaultAsync();
if(userCount != null)
{
return (true, userCount);
}
else
{
return (false, null);
}
}
USER (THE MODEL USED AS A PARAMETER IN FUNC)
namespace ModelsShared.Models
{
public class User
{
public int UserId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string NumberPhone { get; set; }
public string Password { get; set; }
public string Role { get; set; }
}