0

I am currently working on implementing protected routes on a simple Web API. But I can't seem to figure out how JWT works really. I am currently successfully creating and sending back the Token with:

            if (!ModelState.IsValid) return BadRequest(ModelState);
            var foundUser = await _userManager.Users.FirstOrDefaultAsync(u => u.UserName == model.Username);
            if (foundUser == null) return BadRequest("Invalid Username or Password");
            var correctPassword = await _userManager.CheckPasswordAsync(foundUser, model.Password);
            if (!correctPassword) return BadRequest("Invalid Username or Password");

            var token = await _tokenServices.CreateToken(foundUser);

            Response.Cookies.Append("auth_token", token, new CookieOptions
            {
                HttpOnly = true,
                Secure = false,
                SameSite = SameSiteMode.Strict,
                Expires = DateTime.UtcNow.AddHours(1)
            });

            return Ok(new { message = "Logged In succesfully!" });

And the token itself gets created like so:

 public async Task<string> CreateToken(Usuario usuario)
        {

            var claims = new List<Claim>
            {
                new Claim(JwtRegisteredClaimNames.Jti,usuario.Id),
                new Claim(JwtRegisteredClaimNames.Sub, usuario.UserName!),
            };
            var userRoles = await _userManager.GetRolesAsync(usuario);
            foreach (var role in userRoles)
            {
                claims.Add(new Claim(ClaimTypes.Role, role));
            }

            var creds = new SigningCredentials(_key, SecurityAlgorithms.Aes256CbcHmacSha512);

            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(claims),
                Expires = DateTime.UtcNow.AddHours(1),
                SigningCredentials = creds,
                Issuer = _config["JWT:Issuer"]
            };

            var tokenHandler = new JwtSecurityTokenHandler();
            var token = tokenHandler.CreateToken(tokenDescriptor);
            return tokenHandler.WriteToken(token);
        }

I am trying to implement my Protected routes through the use of Attibuttes within the Controllers:

    [HttpPost("create-new")]
    [Authorize(Roles = "Admin")]
    public async Task<IActionResult> Create([FromBody] CreateRolesRequestDto model)
    {
        if (await _roleManager.RoleExistsAsync(model.Role)) return BadRequest("That role already exists");

        var newRole = await _roleManager.CreateAsync(new IdentityRole(model.Role.ToUpper()));
        if (newRole == null) return BadRequest("Invalid Input Data");

        return Ok(newRole);
    }
}

Now I understand there is probably something else to be done since I am using JWT to handle my Security but what? What else do I need in order to have protected Routes?

In case necessary this is the data that is seeded and used for the Users and its roles:

    builder.Entity<Persona>().HasData(
        new Persona
        {
            Id = 1,
            Nombre = "Ismael",
            ApellidoPaterno = "Moron",
            ApellidoMaterno = "Pedraza",
            Carnet = "12597382",
            Telefono = "75526864",
            UsuarioId = "1"
        }
    );


    var hasher = new PasswordHasher<Usuario>();
    builder.Entity<Usuario>().HasData(

        new Usuario
        {
            Id = "1",
            UserName = "ismael",
            Email = "[email protected]",
            PasswordHash = hasher.HashPassword(null, "123456"),
            PersonaId = 1
        }
    );

    List<IdentityRole> roles = new List<IdentityRole>
    {
        new IdentityRole
        {
            Id= "1",
            Name="Admin",
            NormalizedName = "ADMIN"
        },
        new IdentityRole
        {
            Id= "2",
            Name="User",
            NormalizedName = "User"
        }
    };

    builder.Entity<IdentityRole>().HasData(roles);

    // Assign Admin Role to the User
    builder.Entity<IdentityUserRole<string>>().HasData(
        new IdentityUserRole<string>
        {
            UserId = "1", // The Id of the Usuario
            RoleId = "1"  // The Id of the Admin role
        }
    );

As well as the whole of my Program.cs configuration:

builder.Services.AddControllers().AddNewtonsoftJson(options => options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore);


builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("Default")));

builder.Services.AddIdentity<Usuario, IdentityRole>(options =>
{
    options.Password.RequiredLength = 6;
    options.Password.RequireUppercase = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireDigit = true;
}).AddEntityFrameworkStores<AppDbContext>().AddDefaultTokenProviders();

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidIssuer = builder.Configuration["JWT:Issuer"],
        ValidateAudience = false,
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["JWT:SecretKey"]!))
    };
});


builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AdminPolicy", policy => policy.RequireRole("Admin"));
    options.AddPolicy("UserPolicy", policy => policy.RequireRole("User"));

});

builder.Services.AddScoped<IRoleRepository, RoleRepository>();
builder.Services.AddScoped<ITokenServices, TokenServices>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();



app.Run();

I am still learning how to handle Authentication, Authorization and Role Based Access Control as a whole within .NET so any guidance or advice is more than welcome!

Some pics displaying the error and the successful login.

https://postimg.cc/PP9Nxn9K https://postimg.cc/xkydtJCF https://postimg.cc/rRdMXKVT/4718a7f0

1 Answer 1

0

When Creating the Token use the method CreateJwtSecurityToken:

var token = jwtTokenHandler.CreateJwtSecurityToken(tokenDescriptor);
return jwtTokenHandler.WriteToken(token);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.