4
respostas

dataNascimentoClaim null

Após seguir os passos do vídeo, a dataNascimentoClaim segue null. O token é gerado, mas

var dataNascimentoClaim = context
                .User.FindFirst(claim =>
                claim.Type == ClaimTypes.DateOfBirth);

permanece null.

Estou usando no TokenService.cs a recomendação de um dos fóruns para gerar a chave

 var chave = new byte[32];
using (var rng = RandomNumberGenerator.Create())
{
    rng.GetBytes(chave);
}
var chaveBase64 = Convert.ToBase64String(chave);
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(chaveBase64));

Na Program.cs tb fiz uso desse procedimento, pois quando uso o exemplo de chave usado na aula ("9ASHDA98H9ah9ha9H9A89n0f") recebo erro 500.

4 respostas

Olá! Entendo que você está enfrentando um problema com a dataNascimentoClaim permanecendo como null após seguir os passos do vídeo.

A partir do contexto que você forneceu, parece que o problema pode estar na criação do token. Quando o token é criado, as informações do usuário, como a data de nascimento, são incluídas como "claims". Se a dataNascimentoClaim está retornando null, isso pode indicar que essa informação não foi incluída corretamente ao gerar o token.

Aqui está um exemplo de como você pode adicionar a data de nascimento como um "claim" ao criar o token:

var claims = new[]
{
    new Claim(ClaimTypes.Name, usuario.Username),
    new Claim(ClaimTypes.DateOfBirth, usuario.DataNascimento.ToString()),
    // outros claims
};

var token = new JwtSecurityToken(
    // parâmetros do token
    claims: claims
);

Neste exemplo, usuario é um objeto que contém as informações do usuário, e DataNascimento é uma propriedade desse objeto que armazena a data de nascimento do usuário.

Por favor, verifique se a data de nascimento está sendo incluída corretamente ao gerar o token. Se o problema persistir, pode ser útil revisar o código onde o token é criado e assegurar que todas as informações do usuário estão sendo incluídas corretamente.

Espero ter ajudado e bons estudos!

Sim. Verifiquei e a data de nascimento está sendo incluída. Estava dando uma revisada no código mas ainda não identifiquei o motivo. Na classe TokenService eu até alterei, conforme sugestão, a maneira de criar a claim relacionada ao nome usando o ClaimTypes.

TokenService.cs

namespace UsuariosApi.Services
{
    public class TokenService
    {
        public string GenerateToken(Usuario usuario)
        {
            Claim[] claims = new Claim[] {
                //new Claim("username", usuario.UserName),
                new Claim(ClaimTypes.Name, usuario.UserName),
                //new Claim("id", usuario.Id),
                new Claim(ClaimTypes.DateOfBirth, usuario.DataNascimento.ToString()),
            };
            var chave = new byte[32];
            using (var rng = RandomNumberGenerator.Create())
            {
                rng.GetBytes(chave);
            }
            var chaveBase64 = Convert.ToBase64String(chave);
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(chaveBase64));
            var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var token = new JwtSecurityToken
                (
                    expires: DateTime.Now.AddMinutes(10),
                    claims: claims,
                    signingCredentials: signingCredentials
                );
            return new JwtSecurityTokenHandler().WriteToken(token);
        }
    }
}

Token gerado: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoicm9uYWxkbyIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL2RhdGVvZmJpcnRoIjoiMS8xLzE5NzAgMTI6MDA6MDAgQU0iLCJleHAiOjE2OTI4ODU4ODl9.ilvO3nrFWd_FCNzMg1w6BXy2fiGX5q--Ef2_rel9WGk

IdadeAuthorization.cs

namespace UsuariosApi.Authorization
{
    public class IdadeAuthorization : AuthorizationHandler<IdadeMinima>
    {
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IdadeMinima requirement)
        {
            var dataNascimentoClaim = context.User.FindFirst(claim =>
                claim.Type == ClaimTypes.DateOfBirth);

            if (dataNascimentoClaim is null) return Task.CompletedTask;
            var dataNascimento = Convert.ToDateTime(dataNascimentoClaim.Value);
            var idadeUsuario = DateTime.Today.Year - dataNascimento.Year;
            if (dataNascimento > DateTime.Today.AddYears(-idadeUsuario)) idadeUsuario--;
            if (idadeUsuario >= requirement.Idade)
                context.Succeed(requirement);
            return Task.CompletedTask;
        }
    }
}

AcessoController.cs:

namespace UsuariosApi.Controllers
{
    [ApiController]
    [Route("[Controller]")]
    public class AcessoController : ControllerBase
    {
        [HttpGet]
        [Authorize(Policy = "IdadeMinima")]
        public IActionResult Get()
        {
            return Ok("Acesso permitido!");
        }
    }
}

Program.cs:

var builder = WebApplication.CreateBuilder(args);
var connString = builder.Configuration.GetConnectionString("UsuarioConnection");

builder.Services.AddDbContext<UsuarioDbContext>(
    opts => {
        opts.UseMySql(connString,
            ServerVersion.AutoDetect(connString));
    });
builder.Services
    .AddIdentity<Usuario, IdentityRole>()
    .AddEntityFrameworkStores<UsuarioDbContext>()
    .AddDefaultTokenProviders();
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
builder.Services.AddSingleton<IAuthorizationHandler, IdadeAuthorization>();
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var chave = new byte[32];
using (var rng = RandomNumberGenerator.Create())
{
    rng.GetBytes(chave);
}
var chaveBase64 = Convert.ToBase64String(chave);
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(chaveBase64));

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme =
        JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
    options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
    {
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = key,
        ValidateAudience = false,
        ValidateIssuer = false,
        ClockSkew = TimeSpan.Zero
    };
});
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("IdadeMinima", policy =>
        policy.AddRequirements(new IdadeMinima(18))
    );
});
builder.Services.AddScoped<UsuarioService>();
builder.Services.AddScoped<TokenService>();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();

Bom dia estudante, tudo blz?

Você tem a aplicação no github para podermos dar uma olhada melhor?

Att.

Sim. Te adicionei no repositório.