IdentityServer4声明不属于混合流令牌的一部分 [英] IdentityServer4 claims are not part of the token on hybrid flow

查看:84
本文介绍了IdentityServer4声明不属于混合流令牌的一部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试构建混合流,并使用IdentityServer4对返回的访问令牌进行声明.我正在使用 QuickStart UI 控件.

I'm trying to build a hybrid flow, and have claims on the returned access token with IdentityServer4. I'm using the QuickStart UI controlles.

在我的AccountController中,该用户成功通过身份验证之后,我有以下代码可以使他登录:

In my AccountController after the user was authenticated successfully, I have the following code which signs him in:

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

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

In the MVC website that is causing this flow, on the page I want to "protect" I have the following code:

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

成功登录后,调试器会将此代码正常运行,并且我获得了访问令牌.

After a successful login, the debugger hits this code fine and I'm getting the access token.

问题在于,如果我解码访问令牌(我正在使用 https://jwt.io/)我看到了名称和主题,但没有看到我定义的MyName声明.

The problem is that if I decode my access token (I'm using https://jwt.io/) I see the name and subject, but I do not see the MyName claim that I have defined.

(我的系统中还有另一个针对client_credentials的流程,该流程确实返回了对令牌的声明-但它使用了不同的代码流程).

(I have another flow in my system for client_credentials which does return the claims on the token - but it uses a different code flow).

如何为混合流程返回代币上的声明?

How do I return the claims on the token for the hybrid flow?

解决此问题是两件事的结合:

Solving this problem was a combination of 2 things:

  1. 按照(选定)答案的建议实施IProfileService.这是我的实现:
  1. Implementing IProfileService as suggested in (selected) answer. here's my implementation:

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);
    }
}

这将添加令牌上尚未存在的所有声明.

This will add any claim that isn't already on the token.

  1. 调用HttpContext.SignInAsync时,您必须传递声明列表,否则context.Subject.Claims集合中将没有其他声明.
  1. When calling HttpContext.SignInAsync you must pass the list of claims, otherwise no additional claims will be in the context.Subject.Claims collection.

推荐答案

如果要向令牌添加自定义声明,则可以实现自定义IProfileService.

You can implement custom IProfileService if you want to add custom claims to the token.

您可以在 Identity Server 4文档中找到更多信息.

You can find more info in Identity Server 4 docs.

简单的自定义配置文件服务的示例为:

An example of simple custom profile service would be:

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:

Once you have this, just register it to the DI:

services.AddTransient<IProfileService, CustomProfileService>();

每当请求access_tokenid_token时,它将被调用.如果您只想要某些类型的令牌中的额外声明,则需要按照Ruard的注释检查context.Caller.

It will get called whenever an access_token or id_token is requested. You would need to check context.Caller as per Ruard's comment if you only wanted the extra claims in certain type of token.

另外,也可以按照

Also alternatively, you can add the claims directly to the user configuration as per example in one of the Identity Server 4 quickstarts:

            new TestUser
            {
                SubjectId = "1",
                Username = "alice",
                Password = "password",

                Claims = new []
                {
                    new Claim("MyName", "Ophir")
                }
            },

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

If you end up not implementing custom IProfileService and keep using DefaultProfileService, then you would also need add a custom IdentityResource in your configuration:

return new List<IdentityResource>
{
    //..Your other configured identity resources

    new IdentityResource(
    name: "custom.name",
    displayName: "Custom Name",
    claimTypes: new[] { "MyName" });
};

任何希望在令牌中添加此声明的客户都需要请求custom.name范围.

Any clients wanting to have this claim added in the token would need request for custom.name scope.

这篇关于IdentityServer4声明不属于混合流令牌的一部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆