[英].Net Core Custom Authentication using API Keys with Identity Server 4
I have a .NET Core 2.2 Web API that authenticates with JWT tokens.我有一个使用 JWT 令牌进行身份验证的 .NET Core 2.2 Web API。 Tokens are generated by Identity Server 4 on a separate API.
令牌由 Identity Server 4 在单独的 API 上生成。
All the authentication and authorisation works as expected with JWT tokens.使用 JWT 令牌,所有身份验证和授权都按预期工作。 But I need to extend this to allow usage of API keys.
但我需要扩展它以允许使用 API 密钥。 If an API key is supplied, I want to load up the claims of that particular user, add it to the request and let Authorize attribute deal with the set policies.
如果提供了 API 密钥,我想加载该特定用户的声明,将其添加到请求中并让 Authorize 属性处理设置的策略。
Here is what I have done so far following suggestions from here .以下是我根据此处的建议到目前为止所做的工作。 My error is exactly the same as the linked post and it works for me as well using GenericPrincipal with a set of roles but I am using AuthorisationPolicies and I always get 401 error with my current implementation, giving me errors similar to the link above.
我的错误与链接的帖子完全相同,它也适用于我,并使用 GenericPrincipal 和一组角色,但我使用的是 AuthorisationPolicies 并且我当前的实现总是收到 401 错误,给我的错误类似于上面的链接。
Startup.cs启动文件
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore(options =>
{
options.Filters.Add(new RequireHttpsAttribute());
options.Filters.Add(new AuthorizeFilter());
options.Filters.Add(typeof(ValidateModelStateAttribute));
options.AllowEmptyInputInBodyModelBinding = true;
})
.AddAuthorization(options =>
{
options.AddPolicies();
})
.AddJsonFormatters();
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
options.Authority = Configuration["Authentication:Authority"];
options.RequireHttpsMetadata = true;
options.ApiName = Configuration["Authentication:ApiName"];
});
services.AddCors();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseCors(policy =>
{
policy.AllowAnyHeader();
policy.AllowAnyMethod();
policy.AllowAnyOrigin();
});
app.UseHttpsRedirection();
app.UseMiddleware<ApiKeyMiddleware>();
app.UseAuthentication();
app.UseMvc();
}
AuthorizationPolicies.cs授权策略.cs
public static class AuthorizationPolicies
{
public const string ReadUsersPolicy = "ReadUsers";
public const string EditUsersPolicy = "EditUsers";
public static void AddPolicies(this AuthorizationOptions options)
{
options.AddPolicy(ReadUsersPolicy, policy => policy.RequireClaim(Foo.Permission, Foo.CanReadUsers));
options.AddPolicy(EditUsersPolicy, policy => policy.RequireClaim(Foo.Permission, Foo.CanEditUsers));
}
}
ApiKeyMiddleware ApiKey中间件
public class ApiKeyMiddleware
{
public ApiKeyMiddleware(RequestDelegate next)
{
_next = next;
}
private readonly RequestDelegate _next;
public async Task Invoke(HttpContext context)
{
if (context.Request.Path.StartsWithSegments(new PathString("/api")))
{
if (context.Request.Headers.Keys.Contains("ApiKey", StringComparer.InvariantCultureIgnoreCase))
{
var headerKey = context.Request.Headers["ApiKey"].FirstOrDefault();
await ValidateApiKey(context, _next, headerKey);
}
else
{
await _next.Invoke(context);
}
}
else
{
await _next.Invoke(context);
}
}
private async Task ValidateApiKey(HttpContext context, RequestDelegate next, string key)
{
var userClaimsService = context.RequestServices.GetService<IUserClaimsService>();
List<string> permissions = (await userClaimsService.GetAllPermissionsForApiKey(key))?.ToList();
if (permissions == null)
{
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
await context.Response.WriteAsync("Invalid Api Key");
return;
}
ICollection<Claim> claims = permissions.Select(x => new Claim(FooClaimTypes.Permission, x)).ToList();
var identity = new ClaimsIdentity(claims);
var principal = new ClaimsPrincipal(identity);
context.User = principal;
await next.Invoke(context);
}
}
UsersController.cs用户控制器.cs
[Authorize(AuthorizationPolicies.EditUsersPolicy)]
public async Task<IActionResult> Put([FromBody] UserUpdateDto userUpdateDto)
{
...
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.