JWT авторизация с ролями в Identity Core - PullRequest
1 голос
/ 29 апреля 2019

У меня проблемы с пониманием Roles в Identity Core

Мой AccountController выглядит следующим образом, я добавил Roles в требованиях в GenerateJWTToken метод:

[HttpPost("Login")]
    public async Task<object> Login([FromBody] LoginBindingModel model)
    {
        var result = await this.signInManager.PasswordSignInAsync(model.UserName, model.Password, false, false);

        if (result.Succeeded)
        {
            var appUser = this.userManager.Users.SingleOrDefault(r => r.UserName == model.UserName);
            return await GenerateJwtToken(model.UserName, appUser);
        }

        throw new ApplicationException("INVALID_LOGIN_ATTEMPT");
    }

    [HttpPost("Register")]
    public async Task<object> Register([FromBody] RegistrationBindingModel model)
    {
        var user = new ApplicationUser
        {
            UserName = model.UserName,
            Email = model.Email,
            FirstName = model.FirstName,
            LastName = model.LastName
        };
        var result = await this.userManager.CreateAsync(user, model.Password);

        if (result.Succeeded)
        {
            await this.signInManager.SignInAsync(user, false);
            return await this.GenerateJwtToken(model.UserName, user);
        }

        throw new ApplicationException("UNKNOWN_ERROR");
    }

    private async Task<object> GenerateJwtToken(string userName, IdentityUser user)
    {
        var claims = new List<Claim>
        {
            new Claim(JwtRegisteredClaimNames.Sub, userName),
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
            new Claim(ClaimTypes.NameIdentifier, user.Id),
            new Claim(ClaimTypes.Role, Role.Viewer.ToString()),
            new Claim(ClaimTypes.Role, Role.Developer.ToString()),
            new Claim(ClaimTypes.Role, Role.Manager.ToString())
        };

        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(this.configuration["JwtKey"]));
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
        var expires = DateTime.Now.AddDays(Convert.ToDouble(this.configuration["JwtExpireDays"]));

        var token = new JwtSecurityToken(
            this.configuration["JwtIssuer"],
            this.configuration["JwtIssuer"],
            claims,
            expires: expires,
            signingCredentials: creds);

        return new JwtSecurityTokenHandler().WriteToken(token);
    }

Из этого кода мой токен отлично работает с [Authorize] атрибутом контроллера.

Мой вопрос: на каком шаге добавить role к моему зарегистрированному user, чтобы использовать (например) [Authorize("Admin")]?Как сохранить role в базу данных?

[Route("api/[controller]")]
[Authorize] //in this form it works ok, but how to add roles to it with JWT Token?
            //how to register user to role and get this role to JWT Token?
[ApiController]
public class DefaultController : ControllerBase

My ApplicationUser:

public class ApplicationUser : IdentityUser
{
    public string FirstName { get; set; }

    public string LastName { get; set; }
}

и Enum для Roles:

public enum Role
{
    Viewer,
    Developer,
    Manager
}

Как сохранить информацию о роли пользователя в Identity Database ив то время как при входе в систему эта роль должна нормально работать [Authorize] атрибут?

РЕДАКТИРОВАТЬ:

Что я хочу сделать, это сохранить Roles, как в моих перечислениях в User,Я хочу зарегистрировать пользователя как Developer, Manager и т. Д. Я верю, что могу сделать это с помощью ApplicationUser и добавить свойство Role, но из него я не могу получить авторизацию по атрибуту [Authorization(role)]

Ответы [ 2 ]

1 голос
/ 30 апреля 2019

Вы можете использовать встроенное управление ролями с ASP.NET Identity.Поскольку вы используете ASP.NET Core 2.1, вы можете сначала обратиться к ссылке ниже для включения ролей в системе идентификации:

https://stackoverflow.com/a/54069826/5751404

После включения ролей вы можете зарегистрировать роли/ users, затем добавляя роли к пользователю, например:

private async Task CreateUserRoles()
{   
    IdentityResult roleResult;
    //Adding Admin Role
    var roleCheck = await _roleManager.RoleExistsAsync("Admin");
    if (!roleCheck)
    {

        IdentityRole adminRole = new IdentityRole("Admin");
        //create the roles and seed them to the database
        roleResult = await _roleManager.CreateAsync(adminRole);

        _roleManager.AddClaimAsync(adminRole, new Claim(ClaimTypes.AuthorizationDecision, "edit.post")).Wait();
        _roleManager.AddClaimAsync(adminRole, new Claim(ClaimTypes.AuthorizationDecision, "delete.post")).Wait();

        ApplicationUser user = new ApplicationUser {
            UserName = "YourEmail", Email = "YourEmail",

        };
        _userManager.CreateAsync(user, "YourPassword").Wait();

        await _userManager.AddToRoleAsync(user, "Admin");
    }

}

Так что, когда этот пользователь войдет в ваше приложение, вы сможете найти role утверждений в ClaimsPrincipal, и это работает с атрибутом Authorize с ролями.

1 голос
/ 29 апреля 2019

Вам не нужно использовать IdentityUser и базу данных идентификации в вашем случае, вы используете JWT.Создайте модель User с заданным свойством Roles и просто сохраните ее в базе данных.Как:

public class User
{
   public string FirstName { get; set; }
   public string LastName { get; set; }
   public Role Role { get; set; }
}

public enum Role
{
   Viewer,
   Developer,
   Manager
}

токен:

var user = // ...
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(your_seccret_key);
var tokenDescriptor = new SecurityTokenDescriptor
{
    Subject = new ClaimsIdentity(new Claim[] 
         {
             new Claim(ClaimTypes.Name, user.FirstName),
             new Claim(ClaimTypes.Name, user.LastName),
             new Claim(ClaimTypes.Role, user.Role)
         }),
     Expires = DateTime.UtcNow.AddDays(1),
     SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key),SecurityAlgorithms.HmacSha256Signature)
 };
 var token = tokenHandler.CreateToken(tokenDescriptor);
 user.Token = tokenHandler.WriteToken(token);

метод контроллера:

[Authorize(Roles = Role.Developer)]
[HttpGet("GetSomethongForAuthorizedOnly")]
public async Task<object> GetSomething()
{ 
   // .... todo
}
...