本文介绍了如何使用资源所有者流和javascript客户端添加声明以访问IdentityServer3的令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将资源所有者流与IdentityServer3一起使用,并使用javascript中的用户名和密码将获取令牌请求发送到身份服务器令牌端点,如下所示:

I use the resource owner flow with IdentityServer3 and send get token request to identity server token endpoint with username and password in javascript as below:

        function getToken() {
        var uid = document.getElementById("username").value;
        var pwd = document.getElementById("password").value;
        var xhr = new XMLHttpRequest();
        xhr.onload = function (e) {
            console.log(xhr.status);
            console.log(xhr.response);
            var response_data = JSON.parse(xhr.response);
            if (xhr.status === 200 && response_data.access_token) {
                getUserInfo(response_data.access_token);
                getValue(response_data.access_token);
            }
        }
        xhr.open("POST", tokenUrl);
        var data = {
            username: uid,
            password: pwd,
            grant_type: "password",
            scope: "openid profile roles",
            client_id: 'client_id'
        };
        var body = "";
        for (var key in data) {
            if (body.length) {
                body += "&";
            }
            body += key + "=";
            body += encodeURIComponent(data[key]);
        }
        xhr.setRequestHeader("Authorization", "Basic " + btoa(client_id + ":" + client_secret));
        xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        xhr.send(body);
    }

从身份服务器返回访问令牌,并且对用户进行身份验证.然后,我使用此令牌将请求发送到我的Web Api.

The access token is returned from identity server and user is authenticated. Then I use this token to send request to my Web Api.

问题是,当我检查是否为用户分配了角色时,我发现声明不存在.

The problem is that when I check if the user is assigned a role, I find the claim doesn't exist.

    [Authorize]
    // GET api/values
    public IEnumerable<string> Get()
    {
        var id = RequestContext.Principal as ClaimsPrincipal;
        bool geek = id.HasClaim("role", "Geek");  // false here
        bool asset_mgr = id.HasClaim("role", "asset_manager"); // false here
        return new string[] { "value1", "value2" };
    }

这是在身份服务器中定义客户端的方式.

Here is how the client is defined in identity server.

new Client 
            {
                ClientName = "Client",
                ClientId = "client_id",
                Flow = Flows.ResourceOwner,
                RequireConsent = false,
                AllowRememberConsent = false,

                AllowedScopes = new List<string>
                {
                    "openid",
                    "profile",
                    "roles",
                    "sampleApi"
                },
                AbsoluteRefreshTokenLifetime = 86400,
                SlidingRefreshTokenLifetime = 43200,
                RefreshTokenUsage = TokenUsage.OneTimeOnly,
                RefreshTokenExpiration = TokenExpiration.Sliding,
                ClientSecrets = new List<Secret>
                {
                    new Secret("4C701024-0770-4794-B93D-52B5EB6487A0".Sha256())
                },
            },

这是定义用户的方式:

new InMemoryUser
            {
                Username = "bob",
                Password = "secret",
                Subject = "1",

                Claims = new[]
                {
                    new Claim(Constants.ClaimTypes.GivenName, "Bob"),
                    new Claim(Constants.ClaimTypes.FamilyName, "Smith"),
                    new Claim(Constants.ClaimTypes.Role, "Geek"),
                    new Claim(Constants.ClaimTypes.Role, "Foo")
                }
            }

在这种情况下,如何将声明添加到access_token?非常感谢!

How can I add claims to the access_token in this case? Thanks a lot!

推荐答案

我刚刚花了一段时间自己弄清楚了这一点. @leastprivilege对Yang答案的评论有一个线索,这个答案只是在扩展它.
这完全取决于oAuth和OIDC规范的演变方式,而不是IdentityServer的伪像(真棒).首先,这是关于身份令牌和访问令牌之间差异的相当不错的讨论: https://github.com/IdentityServer/IdentityServer3/issues/2015 ,值得一读.

I have just spent a while figuring this out myself. @leastprivilege's comment on Yang's answer had the clue, this answer is just expanding on it.
It's all down to how the oAuth and OIDC specs evolved, it's not an artefact of IdentityServer (which is awesome). Firstly, here is a fairly decent discussion of the differences between identity tokens and access tokens: https://github.com/IdentityServer/IdentityServer3/issues/2015 which is worth a read.

像您一样,通过资源所有者"流程,您将始终获得访问令牌.默认情况下,按照规范,您不应在该令牌中包含声明(原因请参见上面的链接).但是,实际上,如果可以的话,这是非常好的.这样可以节省您在客户端和服务器上的额外工作.

With Resource Owner flow, like you are doing, you will always get an Access Token. By default and per the spec, you shouldn't include claims in that token (see the above link for why). But, in practice, it is very nice when you can; it saves you extra effort on both client and server.

Leastprivilege指的是您需要创建一个范围,如下所示:

What Leastprivilege is referring to is that you need to create a scope, something like this:

new Scope
{
    Name = "member",
    DisplayName = "member",
    Type = ScopeType.Resource,

    Claims = new List<ScopeClaim>
        {
              new ScopeClaim("role"),
              new ScopeClaim(Constants.ClaimTypes.Name),
              new ScopeClaim(Constants.ClaimTypes.Email)
        },

    IncludeAllClaimsForUser = true
}

然后,当您要求令牌时,您需要请求该范围. IE.你的线scope: "openid profile roles",应该更改为scope: "member",(嗯,我说-就我所知,作用域在这里起着双重作用-它们也是一种控制形式,即客户端正在请求某些作用域并且可以被拒绝如果不允许的话,那是另一个话题.

And then you need to request that scope when you ask for the token. I.e. your linescope: "openid profile roles", should change to scope: "member", (well, I say that - scopes play a dual role here, as far as I can see - they are also a form of control, i.e. the client is asking for certain scopes and can be rejected if it is not allowed those but that is another topic).

请注意一段时间以来一直困扰着我的重要一行,即Type = ScopeType.Resource(因为访问令牌与控制对资源的访问有关).这意味着它将适用于访问令牌,并且指定的声明将包含在令牌中(我认为可能违反规范,但非常好).

Note the important line that eluded me for a while, which is Type = ScopeType.Resource (because Access Tokens are about controlling access to resources). This means it will apply to Access Tokens and the specified claims will be included in the token (I think, possibly, against spec but wonderfully).

最后,在我的示例中,我同时包含了一些特定的声明以及IncludeAllClaimsForUser,这显然很愚蠢,但只是想向您展示一些选择.

Finally, in my example I have included both some specific claims as well as IncludeAllClaimsForUser which is obviously silly, but just wanted to show you some options.

这篇关于如何使用资源所有者流和javascript客户端添加声明以访问IdentityServer3的令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-21 02:58