使用 IdentityServer4 从单个客户端接受承载身份验证和 OpenIdConnect

在对IdentityServer4 Quickstart 示例解决方案(特别是 8_AspNetIdentity 示例)进行一些调整后,我遇到了一些问题。

我会先说我不确定我正在尝试做的事情是否不受支持,或者我做错了。

此示例解决方案包含与我的问题相关的以下项目:

  • 一个身份服务器,

  • 一个使用 OpenIdConnect 对其用户进行身份验证的 MVC 客户端(名为 MVCClient),

  • 对其用户使用不记名身份验证的 Web API 客户端(名为 API)

  • 设计为 API 客户端的控制台应用程序(名为 ResourceOwnerClient)

我正在尝试做的是将 API 项目合并到 MVCClient 中,以便 MVCClient 既可以使用 OIDC 对来自其 MVC 网站的用户进行身份验证,也可以使用承载身份验证对 ResourceOwnerClient 进行身份验证。

我对 MVCClient 的 Startup.cs 进行了以下更改:

改为services.AddMvc();:


services.AddMvc(config =>

{

    var policy = new AuthorizationPolicyBuilder(new[]

        {

            JwtBearerDefaults.AuthenticationScheme,

            CookieAuthenticationDefaults.AuthenticationScheme,

            "oidc"

        })

        .RequireAuthenticatedUser()

        .Build();


    config.Filters.Add(new AuthorizeFilter(policy));

});

将 JWT 不记名选项添加到services.AddAuthentication():


.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>

{

    options.Authority = "http://localhost:5000";

    options.RequireHttpsMetadata = false;

    options.Audience = "api1";

})

现在从技术上讲,这确实有效,因为 ResourceOwnerClient 和 MVC 用户都可以成功地通过 MVCClient 进行身份验证。然而,我有一个警告:


当我从 MVC 端对用户进行身份验证时,我注意到我当前的用户中有两个身份。两者在声明等方面都是相同的。这只发生在我在 MVCClient 中设置断点时,在 IdentityServer 上只有一个身份。

http://img.mukewang.com/634a5e7b0001936708350184.jpg

在 IdentityServer 上,我注册了一个 UserClaimsPrincipalFactory,它将我自己的自定义声明添加到 ClaimsIdentity。在 IdentityServer 上的两个身份中,我可以看到重复的声明。因此,我看到的不是一个身份和两个自定义声明,而是两个身份,每个身份都有 4 个自定义声明。我的 UserClaimsPrincipalFactory 中的 CreateAsync 方法也被单次登录击中 5 次。

虽然这种行为很奇怪,但它似乎没有任何负面影响。但这只是我正在构建的更大应用程序的概念证明,我担心我将来可能会因此遇到问题。

如果有人以前尝试过这种事情,或者知道为什么会发生这种行为,我们将不胜感激。


泛舟湖上清波郎朗
浏览 137回答 1
1回答

素胚勾勒不出你

虽然这种设计不会发生任何不好的事情,但我会完全改造它。为什么?因为您正在混合 aClient和 an ApiResource,它们应该在逻辑上分开。AClient是一个应用程序,一些用户与之交互的东西,即使它是一个无头的应用程序(即自动化服务);而 anApiResource由提供给 Clients 的资源组成,因此没有用户可以直接与其交互。您可以针对 IdentityServer 添加两种身份验证,一种作为 API(并将其添加为JwtBearer),另一种作为客户端(并将其添加为Cookies)。然后,您可以根据该动作/控制器的功能使用[Authorize(AuthenticationSchemes = "JwtBearer")]和。= "Cookies"撇开这一点不谈,问题是您的应用程序正在为 MVC 端获取一个身份,而为 API 端获取一个身份,因为它无法告诉您想要哪个身份。只要你有一个想法,这就是我的一个带有 ASP.NET Core Identtiy 的 IdentityServer 的样子,你可以使用 UI 登录它,还可以使用 JwtToken 访问 REST 端点:services    .AddAuthentication(options =>    {        options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;        options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;        options.DefaultSignInScheme = IdentityConstants.ExternalScheme;    })    .AddIdentityServerAuthentication(JwtBearerDefaults.AuthenticationScheme, options =>    {        options.Authority = Configuration["IdentityServerUrl"];        options.ApiName = Configuration["ApiName"];        options.RequireHttpsMetadata = false;    })    .AddCookie(IdentityConstants.ApplicationScheme, o =>    {        o.LoginPath = new PathString("/Account/Login");        o.Events = new CookieAuthenticationEvents()        {            OnValidatePrincipal = SecurityStampValidator.ValidatePrincipalAsync        };    })    .AddCookie(IdentityConstants.ExternalScheme, o =>    {        o.Cookie.Name = IdentityConstants.ExternalScheme;        o.ExpireTimeSpan = TimeSpan.FromMinutes(5.0);    })    .AddCookie(IdentityConstants.TwoFactorRememberMeScheme, o =>    {        o.Cookie.Name = IdentityConstants.TwoFactorRememberMeScheme;    })    .AddCookie(IdentityConstants.TwoFactorUserIdScheme, o =>    {        o.Cookie.Name = IdentityConstants.TwoFactorUserIdScheme;        o.ExpireTimeSpan = TimeSpan.FromMinutes(5.0);    });
打开App,查看更多内容
随时随地看视频慕课网APP