Как добавить роли в claims?
У меня в приложении asp.net core 2.2 реализована аутентификация по токенам (примерно как в этом ответе), теперь вот думаю, как мне передать в токен роли (штатные, из таблички dbo.AspNetRoles).
Поскольку я не особо разбираюсь в криптографии, то сижу пытаюсь понять, как это сделать правильно. Логично же, что в payload записывать нельзя, потому что можно будет подделать?
Вот мой текущий код:
public class AuthController : Controller
{
private readonly UserManager<ApplicationUser> UserManager;
private readonly SignInManager<ApplicationUser> SignInManager;
public AuthController(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager)
{
this.UserManager = userManager;
this.SignInManager = signInManager;
}
[HttpPost("/api/token")]
public async Task Token([FromBody] TokenRequest tokenRequest)
{
var principal = await this.GetIdentity(tokenRequest);
if (principal == null)
{
this.Response.StatusCode = 400;
await this.WriteResponse("Invalid username or password.");
return;
}
var response = new
{
token = new TokenGenerator().Generate(DateTime.UtcNow, principal.Claims),
username = principal.Identity.Name,
};
await this.WriteResponse(response);
}
private async Task WriteResponse(object response)
{
this.Response.ContentType = "application/json";
await this.Response.WriteAsync(JsonConvert.SerializeObject(response, new JsonSerializerSettings { Formatting = Formatting.Indented }));
}
private async Task<ClaimsPrincipal> GetIdentity(TokenRequest tokenRequest)
{
var user = this.UserManager.Users.FirstOrDefault(x => x.NormalizedEmail == tokenRequest.UserName);
if (user != null)
{
var check = await this.UserManager.CheckPasswordAsync(user, tokenRequest.Password);
if (check)
{
var principal = await this.SignInManager.CreateUserPrincipalAsync(user);
return principal;
}
}
return null;
}
public class TokenRequest
{
public string UserName { get; set; }
public string Password { get; set; }
}
}
и генерация токена:
public class TokenGenerator
{
public string Generate(DateTime now, IEnumerable<Claim> claims)
{
var token = Emit(now, claims);
var encoded = Encode(token);
return encoded;
}
private static JwtSecurityToken Emit(DateTime now, IEnumerable<Claim> claims)
{
return new JwtSecurityToken(
AuthOptions.ISSUER,
AuthOptions.AUDIENCE,
claims,
now,
now.Add(TimeSpan.FromHours(AuthOptions.LIFETIME)),
new SigningCredentials(AuthOptions.GetSymmetricSecurityKey(), SecurityAlgorithms.HmacSha256));
}
private static string Encode(JwtSecurityToken token)
{
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
Ответы (1 шт):
Странно, но похоже что это всё вообще реализуется автоматически где-то в недрах identity фреймворка.
Решил ещё раз глянуть что там в claims бегает, поэкспериментировал немного.
Вот чистый пользователь без ролей:
Вот пользователь с одной ролью:
И вот он же, ещё одну роль навесил:
Ну и соответственно, работает штатный атрибут Authorize:
[HttpPost]
[Authorize(Roles = "admin")]
public async Task<object> Create(Persons.Create.PersonData request, CancellationToken cancellationToken)
{
var command = new Persons.Create.Command(request, this.User);
var result = await this.Mediator.Send(command, cancellationToken);
return result;
}
При этом если смотреть sql profiler - видно, что да, при логине идёт как раз запрос к таблицам с ролями.


