AspNet用户声称丢失

时间:2019-08-09 16:48:18

标签: c# asp.net-mvc asp.net-identity identityserver4 claims

研究身份提供者的概念证明,需要帮助来理解特定于用户声明的aspnet身份的细微差别。

我要完成的任务:

1)公开一个MVC应用程序,该应用程序提供对2种微服务之一的安全访问,这些微服务将公开体育和运动员数据。

2)同时允许本地用户帐户和外部帐户(例如google或facebook auth)。

当前设置:

1)利用Identity Server 4进行身份验证的Asp.Net MVC应用程序。

2)两个Web Api 2 Web服务(一个用于运动,一个用于运动员)。体育API不安全...即开放API。尽管应该通过基于策略的授权来保护运动员API。

3)Identity Server 4 Web应用程序,通过IdentityServer4 nuget软件包利用Entity Framework和ASP.NET Identity。

4)已为api资源,身份资源,客户端,几个角色不同且声明要进行测试的测试用户“完全”配置了SQL Server数据库。

当前有效的方法:

1)所有用户都可以登录(本地和Google)

2)声明似乎正在按我的预期加载(仍然难以理解Identity Server数据模型中声明表的所有关系)。

3)MVC应用显示id_token,access_token,refresh_token,然后为用户循环浏览并显示这些声明。

什么不起作用:

1)并非所有我认为应该在mvc应用程序中显示的声明都已显示。

我的意思示例:

1)在下面的第一个屏幕截图中,您可以看到named_name和family_name作为用户“ bob”的声明。这是使用MVC剃须刀中的以下代码片段显示的:

enter image description here

@if (User.Identities.First().IsAuthenticated)
{
    <h1>Tokens:</h1>

    <dt>id token</dt>
    <dd>@await ViewContext.HttpContext.GetTokenAsync("id_token")</dd>

    <dt>access token</dt>
    <dd>@await ViewContext.HttpContext.GetTokenAsync("access_token")</dd>

    <dt>refresh token</dt>
    <dd>@await ViewContext.HttpContext.GetTokenAsync("refresh_token")</dd>

    <br />

    <h1>Claims:</h1>
    <dl>
        @foreach (var claim in User.Claims)
        {
            <dt>@claim.Type : @claim.Value</dt>
        }
    </dl>
}

2)在第二个屏幕截图中,您可以看到身份服务器生成的访问令牌中包含的其他“声明”。例如,“权限”,“测试”,“角色”,“测试角色声明”和“赔率”。

enter image description here

除了一些零散的地方,大多数代码直接来自Identity Server 4文档的快速入门教程。根据我阅读的所有内容,为了包括自定义声明,您需要实现自己的IProfileService接口实例。我已经做到了,它似乎按预期工作。这是代码和屏幕截图,显示了在调试器中加载的“其他”声明:

enter image description here

以下是数据库表及其条目:

1)身份资源/身份声明:

enter image description here

2)ApiResources / ApiScopes / ApiScopeClaims

enter image description here

3)AspNetUsers / AspNetRoles / AspNetUserClaims / AspNetRoleClaims / etc

enter image description here

这是我的问题:

1)为什么不将加载到ProfileService :: GetProfileDataAsync方法中的声明包含在MVC显示的User.Claims列表中?

更新1:

1)我在mvc应用程序的客户端表上更新了AlwaysIncludeUserClaimsInIdToken = True。发生了以下事情:a)现在,MVC声明列表的输出中显示“ oddball”声明。 b)MVC应用程序中显示的声明现在不存在时现在包含在id_token中,但是它们仍然不包含“其他”声明。 enter image description here

更新2:

1)我想出了原始问题的答案。过滤列表的原因是因为下面的代码行将基于RequestedClaimsType属性中存在的声明的类型在内部进行过滤。现在,我需要了解为什么该列表中仅包含“名称”,“ given_name”和“ family_name”。该信息的来源:https://github.com/IdentityServer/IdentityServer4/blob/master/src/IdentityServer4/src/Extensions/ProfileDataRequestContextExtensions.cs

context.AddRequestedClaims(claims);

1 个答案:

答案 0 :(得分:1)

最后弄清楚了我所缺少的。客户端应用程序负责在连接Openid中间件时设置OpenIdConnect选项。选项对象上的属性之一称为“ ClaimActions”。这些声明操作允许客户端连接自定义映射属性。这是ClaimsActions.MapJsonKey属性/方法组合的文档:

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/additional-claims?view=aspnetcore-2.2#map-user-data-keys-and-create-claims

这是我添加到我的客户端启动类中的代码,以使它对于一组自动序列化的声明起作用。

services.AddAuthentication(options =>
{
   options.DefaultScheme = "Cookies";
   options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{                    
    options.SignInScheme = "Cookies";

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

    options.ClientId = "mvc";
    options.ClientSecret = "secret";
    options.ResponseType = "code id_token";

    options.SaveTokens = true;
    options.GetClaimsFromUserInfoEndpoint = true;

    options.Scope.Add("athlete.full");
    options.Scope.Add("rights");
    options.Scope.Add("email");
    options.Scope.Add("address");
    options.Scope.Add("phone");

    options.Scope.Add("offline_access");

    // These are what allowed the claims to be serialized for front-end consumption.
    options.ClaimActions.MapJsonKey(JwtClaimTypes.WebSite, "website");
    options.ClaimActions.MapJsonKey(JwtClaimTypes.Gender, "gender");
    options.ClaimActions.MapJsonKey(JwtClaimTypes.BirthDate, "birthdate");
});