IdentityServer4声称不是混合流程中令牌的一部分



我正在尝试构建混合流,并在带有IdentityServer4的返回访问令牌上索赔。我正在使用Quickstart UI控制。

在我的AccountController中成功验证后,我有以下代码签名他:

await HttpContext.SignInAsync("anon@nymous.com", "anon@nymous.com", null, new Claim("MyName", "Ophir"));

在导致此流程的MVC网站上,我想"保护"的页面上有以下代码:

[Authorize]
public IActionResult RestrictedMvcResource()
{
       var token = _httpContext.HttpContext.GetTokenAsync("access_token").Result;
       var identity = User.Identity;
       return View();
}

成功登录后,调试器命中了此代码,我将获得访问令牌。

问题是,如果我解码访问令牌(我正在使用https://jwt.io/),我会看到名称和主题,但是我看不到我已经定义的MyName声称。

(我的client_credentials系统中有另一个流程,它确实返回令牌上的索赔 - 但它使用了不同的代码流)。

如何返回混合流的令牌上的索赔?

编辑:

解决这个问题是两件事的组合:

  1. 如(选定)答案中建议的IProfileService。这是我的实施:
public class ProfileService : IProfileService
{
    public Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        context.AddRequestedClaims(context.Subject.Claims);
        foreach (Claim claim in context.Subject.Claims)
        {
            if (context.IssuedClaims.Contains(claim))
                continue;
            context.IssuedClaims.Add(claim);
        }
        return Task.FromResult(0);
    }
    public Task IsActiveAsync(IsActiveContext context)
    {
        context.IsActive = true;
        return Task.FromResult(0);
    }
}

这将添加所有尚未在令牌上的主张。

  1. 拨打HttpContext.SignInAsync时,您必须通过索赔列表,否则不会在context.Subject.Claims集合中进行其他索赔。

如果要在令牌中添加自定义索赔,则可以实现自定义IProfileService

您可以在身份服务器4个文档中找到更多信息。

简单的自定义个人资料服务的一个示例是:

public class CustomProfileService : IProfileService
{
    public Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        context.AddRequestedClaims(context.Subject.Claims);
        context.IssuedClaims.Add(new Claim("MyName", "Ophir"));
        return Task.FromResult(0);
    }
    public Task IsActiveAsync(IsActiveContext context)
    {
        context.IsActive = true;    
        return Task.FromResult(0);
    }
}

一旦有了,只需将其注册到DI:

services.AddTransient<IProfileService, CustomProfileService>();

每当请求access_tokenid_token时,它都会被调用。如果您只想要某些类型的令牌索赔,则需要根据Ruard的评论来检查context.Caller

编辑:另外,您可以按照"身份服务器" 4 Quickstarts中的示例直接将权利要求直接添加到用户配置:

            new TestUser
            {
                SubjectId = "1",
                Username = "alice",
                Password = "password",
                Claims = new []
                {
                    new Claim("MyName", "Ophir")
                }
            },

如果您最终不实现自定义IProfileService并继续使用DefaultProfileService,则您还需要在配置中添加自定义IdentityResource

return new List<IdentityResource>
{
    //..Your other configured identity resources
    new IdentityResource(
    name: "custom.name",
    displayName: "Custom Name",
    claimTypes: new[] { "MyName" });
};

任何想要在令牌中添加此主张的客户都需要custom.name范围的请求。

aspnet.security.openidconnect.server不会序列化没有目的地的索赔。我在使用OpenIddict时遇到了这个。

尝试以下操作:

var claim = new Claim("MyName", "Ophir");
claim.SetDestinations(OpenIdConnectConstants.Destinations.AccessToken);
await HttpContext.SignInAsync("anon@nymous.com", "anon@nymous.com", null, claim);

您可能需要添加以下名称空间:

using AspNet.Security.OpenIdConnect.Extensions;
using AspNet.Security.OpenIdConnect.Primitives;

有两个步骤,我为我们的身份服务器添加了索赔。

通过像其他答案之一一样,通过自定义个人资料服务,您可以为用户定义自己的主张。

然后可以通过UserInfo端点请求这些主张。

或创建一个api(资源),例如,如果您要求该API作为示波器,则默认为访问令牌添加名称索赔。

相关内容

  • 没有找到相关文章