Проблемы с ролями и jwt токеном
При переходе на /admin пишет ошибку 401, однако вроде роли настроены, использую jwt токен
Мой код C#
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.Authorization;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
var adminRole = new Role("admin");
var userRole = new Role("user");
var people = new List<Account>
{
new Account("Lololoshka", "123", adminRole),
new Account("Karal", "qwerty", userRole)
};
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization();
//Конфигурация и валидация токена
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
// указывает, будет ли валидироваться издатель при валидации токена
ValidateIssuer = true,
// строка, представляющая издателя
ValidIssuer = AuthOptions.ISSUER,
// будет ли валидироваться потребитель токена
ValidateAudience = true,
// установка потребителя токена
ValidAudience = AuthOptions.AUDIENCE,
// будет ли валидироваться время существования
ValidateLifetime = true,
// установка ключа безопасности
IssuerSigningKey = AuthOptions.GetSymmetricSecurityKey(),
// валидация ключа безопасности
ValidateIssuerSigningKey = true,
};
});
var app = builder.Build();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseAuthentication();
app.UseAuthorization();
//Генерация токена во время входа
//Генерация токена во время входа
app.MapPost("/login", (Account user) =>
{
Account? person = people.FirstOrDefault(p => p.Login == user.Login && p.Password == user.Password);
if (person is null) return Results.Unauthorized();
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, person.Login),
new Claim(ClaimTypes.Role, person.Role.Name)
// добавьте другие необходимые заявки, если есть
};
var jwt = new JwtSecurityToken(
issuer: AuthOptions.ISSUER,
audience: AuthOptions.AUDIENCE,
claims: claims,
expires: DateTime.UtcNow.Add(TimeSpan.FromMinutes(2)),
signingCredentials: new SigningCredentials(AuthOptions.GetSymmetricSecurityKey(), SecurityAlgorithms.HmacSha256));
var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);
// вывод информации о токене в консоль
Console.WriteLine("Generated token: " + encodedJwt);
var response = new
{
access_token = encodedJwt,
username = person.Login
};
return Results.Json(response);
});
app.Map("/data", [Authorize] () => new { message = "Hello cats!" });
// доступ только для роли admin
app.Map("/admin", [Authorize(Roles = "admin")] () => new { message = "Admin!" });
app.Run();
//Настройки генерации токена
public class AuthOptions
{
public const string ISSUER = "CatServer";
public const string AUDIENCE = "CatClient";
const string KEY = "ewiuGFPEGQRBIIWT4GIU[35QGSOdsfIHTwerFNHVDU43";
public static SymmetricSecurityKey GetSymmetricSecurityKey()=>
new SymmetricSecurityKey(Encoding.UTF8.GetBytes(KEY));
}
public class Account
{
public string Login { get; set; }
public string Password { get; set; }
public Role Role { get; set; }
public Account(string login, string password, Role role)
{
Login = login;
Password = password;
Role = role;
}
}
public class Role
{
public string Name { get; set; }
public Role(string name) => Name = name;
}
Мой фронт
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>CAT.COM</title>
</head>
<body>
<div id="userInfo" style="display:none;">
<p>Добро пожаловать <span id="userName"></span>!</p>
<input type="button" value="Выйти" id="logOut" />
<p>
<button id="adminPanel">Административная панель</button>
</p>
</div>
<div id="loginForm">
<h3>Вход на сайт</h3>
<p>
<label>Введите логин</label><br />
<input type="email" id="email" />
</p>
<p>
<label>Введите пароль</label><br />
<input type="password" id="password" />
</p>
<input type="submit" id="submitLogin" value="Войти" />
</div>
<p>
<input type="submit" id="getData" value="Получить данные" />
</p>
<script>
var tokenKey = "accessToken";
document.getElementById("submitLogin").addEventListener("click", async e => {
e.preventDefault();
const response = await fetch("/login", {
method: "POST",
headers: { "Accept": "application/json", "Content-Type": "application/json" },
body: JSON.stringify({
Login: document.getElementById("email").value,
Password: document.getElementById("password").value
})
});
if (response.ok === true) {
const data = await response.json();
document.getElementById("userName").innerText = data.username;
document.getElementById("userInfo").style.display = "block";
document.getElementById("loginForm").style.display = "none";
sessionStorage.setItem(tokenKey, data.access_token);
}
else
console.log("Status: ", response.status);
});
document.getElementById("getData").addEventListener("click", async e => {
e.preventDefault();
const token = sessionStorage.getItem(tokenKey);
const response = await fetch("/data", {
method: "GET",
headers: {
"Accept": "application/json",
"Authorization": "Bearer " + token
}
});
if (response.ok === true) {
const data = await response.json();
alert(data.message);
}
else
console.log("Status: ", response.status);
});
document.getElementById("adminPanel").addEventListener("click", async e => {
e.preventDefault();
const token = sessionStorage.getItem(tokenKey);
const response = await fetch("/admin", {
method: "GET",
headers: {
"Authorization": "Bearer " + token
}
});
if (response.ok === true) {
window.location.href = "/admin";
} else {
console.log("Status: ", response.status);
}
});
document.getElementById("logOut").addEventListener("click", e => {
e.preventDefault();
document.getElementById("userName").innerText = "";
document.getElementById("userInfo").style.display = "none";
document.getElementById("loginForm").style.display = "block";
sessionStorage.removeItem(tokenKey);
});
</script>
</body>
</html>
Ответы (1 шт):
Автор решения: Alatyrev Danila Artemovich
→ Ссылка
Чтобы с ролями работать, нужно сначала их зарегистрировать в Identity
:
var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
var UserManager = serviceProvider.GetRequiredService<UserManager<Domain.Models.User>>();
string[] roleNames = { "Admin", "Manager", "Member" };
IdentityResult roleResult;
foreach (var roleName in roleNames)
{
var roleExist = await RoleManager.RoleExistsAsync(roleName);
if (!roleExist)
{
//create the roles and seed them to the database: Question 1
roleResult = await RoleManager.CreateAsync(new IdentityRole(roleName));
}
}