使用IdentityServer4身份验证为ClaimsIdentity设置自定义声明

时间:2018-09-04 16:17:58

标签: asp.net-core identityserver4

我有一个使用IdentityServer4.TokenValidation进行身份验证的ASP.NET Core 2.1应用程序

authenticationBuilder.AddIdentityServerAuthentication(AuthorizationConstants.IpreoAccountAuthenticationScheme, options =>
{
  options.RequireHttpsMetadata = false;
  options.ApiName = apiName;
  options.ApiSecret = apiSecret;
  options.Authority = authority;
  options.LegacyAudienceValidation = true;
});

如何向身份添加自定义声明的最佳方法是什么? 考虑到我们仍然需要有机会在Roles验证中使用Authorize属性。

例如,对于承载身份验证,我们可以使用在每个请求上触发的OnTokenValidated处理程序。但是对于IdentityServerAuthenticationOptions,Events属性属于对象类型,因此无法使用具有OnTokenValidated属性的虚拟对象对其进行初始化。

我们必须支持JWT和参考令牌。 我们还需要支持多种身份验证方案

有什么想法或建议吗?

2 个答案:

答案 0 :(得分:1)

Ruard van Elburg给了我一个关于使用中间件的好主意。我必须使用这种方法更新多种身份验证方案的唯一更新是重写IAuthenticationSchemeProvider以继续使用UseAuthentication中间件。

https://github.com/aspnet/Security/blob/beaa2b443d46ef8adaf5c2a89eb475e1893037c2/src/Microsoft.AspNetCore.Authentication/AuthenticationMiddleware.cs

因此它根据请求内容返回默认方案

我必须要做的:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
       app.UseAuthentication();
       app.UseMiddleware<ClaimsMiddleware>(); // to set claims for authenticated user
       app.UseMvc();
}

public void ConfigureServices(IServiceCollection services)
{
       services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);    
       services.AddTransient<IAuthenticationSchemeProvider, CustomAuthenticationSchemeProvider>(); 
       services.AddAuthorization();
       services.AddAuthentication // add authentication for multiple schemes
}

答案 1 :(得分:0)

您将需要中间件。作为示例,我建议您看一下PolicyServer。它具有相同的方法。

IdentityServer处理身份验证,而授权则由PolicyServer处理。 free OSS version在中间件中添加声明。

从源代码开始:

/// Add the policy server claims transformation middleware to the pipeline.
/// This middleware will turn application roles and permissions into claims
/// and add them to the current user
public static IApplicationBuilder UsePolicyServerClaims(this IApplicationBuilder app)
{
    return app.UseMiddleware<PolicyServerClaimsMiddleware>();
}

PolicyServerClaimsMiddleware在哪里:

public class PolicyServerClaimsMiddleware
{
    private readonly RequestDelegate _next;

    /// <summary>
    /// Initializes a new instance of the <see cref="PolicyServerClaimsMiddleware"/> class.
    /// </summary>
    /// <param name="next">The next.</param>
    public PolicyServerClaimsMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    /// <summary>
    /// Invoke
    /// </summary>
    /// <param name="context">The context.</param>
    /// <param name="client">The client.</param>
    /// <returns></returns>
    public async Task Invoke(HttpContext context, IPolicyServerRuntimeClient client)
    {
        if (context.User.Identity.IsAuthenticated)
        {
            var policy = await client.EvaluateAsync(context.User);

            var roleClaims = policy.Roles.Select(x => new Claim("role", x));
            var permissionClaims = policy.Permissions.Select(x => new Claim("permission", x));

            var id = new ClaimsIdentity("PolicyServerMiddleware", "name", "role");
            id.AddClaims(roleClaims);
            id.AddClaims(permissionClaims);

            context.User.AddIdentity(id);
        }

        await _next(context);
    }
}

从启动开始:

public void ConfigureServices(IServiceCollection services)
{

    services.AddMvcCore(options =>
    {
        // workaround: https://github.com/aspnet/Mvc/issues/7809
        options.AllowCombiningAuthorizeFilters = false;
    })
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
    .AddAuthorization();

    // This is not relevant for you, but just to show how policyserver is implemented.
    // The bottom line is that you can implement this anyway you like.

    // this sets up the PolicyServer client library and policy
    // provider - configuration is loaded from appsettings.json
    services.AddPolicyServerClient(Configuration.GetSection("Policy"))
            .AddAuthorizationPermissionPolicies();

}

public void Configure(IApplicationBuilder app)
{
    app.UseAuthentication();

    // add this middleware to make roles and permissions available as claims
    // this is mainly useful for using the classic [Authorize(Roles="foo")] and IsInRole functionality
    // this is not needed if you use the client library directly or the new policy-based authorization framework in ASP.NET Core
    app.UsePolicyServerClaims();

    app.UseMvc();
}