Авторизация¶
Для авторизации в WebAPI
используем JWT
.
Коротко, что такое
JWT
, можно узнать по ссылке.
Для авторизации через JWT
в наше приложение нужно:
- В конфигурацию добавить секцию со следующими полями:
yaml # Опции авторизации AuthOptions: # Имя издателя токена Issuer: Curiosity sample API # Имя потребителя токена Audience: Curiosity sample Client # ключ для генерации токена (при смене - все старые токены не валидны) Key: 1075F0D5-0D2F-4639-9D18-271AC715B581 # длинна жизни токена LifeDays: 30
-
Устанавить пакет
Microsoft.AspNetCore.Authentication.JwtBearer
-
В классе
Startup
настроить авторизация и аутентификацию как на примере ниже: ```csharp services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { options.SaveToken = true; options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidIssuer = Configuration.AuthOptions.Issuer,ValidateAudience = true, ValidAudience = Configuration.AuthOptions.Audience, IssuerSigningKey = Configuration.AuthOptions.SymmetricSecurityKey, ValidateIssuerSigningKey = true, ValidateLifetime = true, }; });
services.AddAuthorization(); ```
c# public void Configure(IApplicationBuilder app) { app.UseAuthentication(); app.UseAuthorization(); }
Для генерации токена используем JwtSecurityTokenHandler
.
Полезную информацию записываем в виде Claims
.
Используем System.Security.Claims.ClaimTypes
для имен.
```c#
public string GenerateToken(UserEntity user)
{
var now = _dateTimeService.GetCurrentTimeUtc();
var claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Name, user.FIO),
new Claim(ClaimTypes.Role, user.Client.Role),
new Claim(ClientIdClimeName, user.Client.Id.ToString()),
new Claim(ClaimTypes.Version, "1"), // версия токена. При добавлении новых claim - версия + 1 (для фронта)
};
var jwt = new JwtSecurityToken(
issuer: _configuration.AuthOptions.Issuer,
audience: _configuration.AuthOptions.Audience,
notBefore: now,
expires: now.AddDays(_configuration.AuthOptions.LifeDays),
claims: claims,
signingCredentials: new SigningCredentials(_configuration.AuthOptions.SymmetricSecurityKey, SecurityAlgorithms.HmacSha256));
return TokenHandler.WriteToken(jwt);
}
```
Продебажить токен можно на сайте: https://jwt.io
Для успешной авторизации необходимо добавлять токен в хедер запроса. Пример:
```yaml
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6IjUiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoi0J_QvtC00YjRg9C8INCf0YDQuNCx0L7QtdCyIiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiQWdlbnQiLCJDbGllbnRJZCI6IjMiLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3ZlcnNpb24iOiIxIiwibmJmIjoxNjE3MjcyMzc1LCJleHAiOjE2MTk4NjQzNzUsImlzcyI6IklURyBCYW5rIEd1YXJhbnRlZXMgQVBJIiwiYXVkIjoiSVRHIEJhbmsgR3VhcmFudGVlcyBDbGllbnQifQ.FalR5clCPYxUzlrVkolGVSNlZoZx-uZceGQl7ryFCac"
```
Для управления доступа к методам API используем атрибуты:
-
[AllowAnonymous]
- авторизация не требуется -
[Authorize]
- авторизация обязательна. Для неавторизированных запросов будет приходит ответ с кодом 401 -
[Authorize(Roles = "Admin,Agent")]
- для успешной авторизации в Claims должна быть записана роль Admin или Agent"http://schemas.microsoft.com/ws/2008/06/identity/claims/role": "Agent"
-
для более сложных кейсов авторизации можно использовать Policy
Для получения id авторизованного пользователя на беке, так же используем Claims,
которые достаются из токена в слое Authorization
и помещаются в HttpContext.User
. Например, так (если есть Identity):
public long GetUserId(HttpContext httpContext)
{
var claimValue = _signInManager.UserManager.GetUserId(httpContext.User) ?? "";
if (!long.TryParse(claimValue, out var userId))
throw new InvalidOperationException($"Невозможно получить id пользователя из claims (claim value = \"{claimValue}\")");
return userId;
}
Более подробно код см. BLL.Auth.AuthService.cs
в sample/WebApp
.