如何使IdentityServer将用户身份添加到访问令牌?

LOS*_*OST 11 access-token asp.net-web-api identityserver3 identityserver4

简短:我的客户端从IdentityServer示例服务器检索访问令牌,然后将其传递给我的WebApi.在我的控制器中,this.HttpContext.User.GetUserId()返回null(尽管用户有其他声明).我怀疑访问令牌中没有nameidentity声明.如何让IdentityServer包含它?

到目前为止我尝试过的:

  • 从混合切换到隐式流(随机尝试)
  • 在我添加的IdSvrHost范围定义中

    Claims = {new ScopeClaim(ClaimTypes.NameIdentifier,alwaysInclude:true)}

  • 在我添加的IdSvrHost客户端定义中

    Claims = {new Claim(ClaimTypes.NameIdentifier,"42")}

(也是随机尝试)

我还尝试了范围定义中的其他范围,但它们都没有出现.看来,这种名称通常包含在身份令牌中,但对于我所知道的大多数公共API,您不会向服务器提供身份令牌.

更多细节:IdSrvHost和Api位于不同的主机上.控制器有[授权].事实上,我可以看到其他声明即将到来.Api配置为

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

app.UseIdentityServerAuthentication(options => {
    options.Authority = "http://localhost:22530/";

    // TODO: how to use multiple optional scopes?
    options.ScopeName = "borrow.slave";
    options.AdditionalScopes = new[] { "borrow.receiver", "borrow.manager" };

    options.AutomaticAuthenticate = true;
    options.AutomaticChallenge = true;
});
Run Code Online (Sandbox Code Playgroud)

范围:

public static Scope Slave { get; } = new Scope {
    Name = "borrow.slave",
    DisplayName = "List assigned tasks",
    Type = ScopeType.Resource,

    Claims = {
        new ScopeClaim(ClaimTypes.NameIdentifier, alwaysInclude: true),
    },
};
Run Code Online (Sandbox Code Playgroud)

和客户:

new Client {
    ClientId = "borrow_node",
    ClientName = "Borrow Node",

    Flow = Flows.Implicit,

    RedirectUris = new List<string>
    {
        "borrow_node:redirect-target",
    },

    Claims = { new Claim(ClaimTypes.NameIdentifier, "42") },

    AllowedScopes = {
        StandardScopes.OpenId.Name,
        //StandardScopes.OfflineAccess.Name,
        BorrowScopes.Slave.Name,
    },
}
Run Code Online (Sandbox Code Playgroud)

验证URI:

request.CreateAuthorizeUrl(
            clientId: "borrow_node",
            responseType: "token",
            scope: "borrow.slave",
            redirectUri: "borrow_node:redirect-target",
            state: state,
            nonce: nonce);
Run Code Online (Sandbox Code Playgroud)

而且我也试过了

request.CreateAuthorizeUrl(
            clientId: "borrow_node",
            responseType: "id_token token",
            scope: "openid borrow.slave",
            redirectUri: "borrow_node:redirect-target",
            state: state,
            nonce: nonce);
Run Code Online (Sandbox Code Playgroud)

LOS*_*OST 8

万岁,当我偶然发现这个页面时,我找到了答案:https://github.com/IdentityServer/IdentityServer3.Samples/issues/173

显然,用户身份在访问令牌中的"子"声明中传递.因为我盲目复制了API样本,其配置包括在内

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
Run Code Online (Sandbox Code Playgroud)

这实际上阻止了我的API将"sub"声明映射到nameidentifier.删除此行后,经过身份验证的控制器的HttpContext.User.GetUserId()会正确返回用户ID.