16

我正在尝试设置 Thinktecture 的 Identity Server 3,但在交换授权代码时(或使用 ResourceOwner 流时,我似乎无法让它返回刷新令牌,但我将专注于授权代码因为它现在对我更重要)。我取回了访问令牌并可以很好地使用它们进行身份验证,但它似乎甚至没有生成我期望取回的刷新令牌。为了让 Identity Server 返回刷新令牌,我需要做些什么特别的事情吗?

我已经查看了文档,但没有看到我设置错误的任何内容,并且我没有做的关于刷新令牌的页面上唯一我没有做的事情是在发送用户时明确请求“offline_access”范围在那里进行身份验证,因为每当我尝试时,都会收到“无效范围”错误。因此,我将 Thinktecture 的“请求 offline_access 范围(通过代码或资源所有者流程)”的措辞表示,offline_access 范围是根据您使用的流程自动请求的。

我一直在尝试尽可能地遵循他们的示例应用程序(以及Katana Project中现有 Owin 中间件的源代码),我的设置如下:

  • 我使用他们的客户端类创建了一个客户端,手动指定以下内容:
    var 客户端 = 新客户端()
    {
        ClientId = "SomeId",
        ClientName = "具有身份验证代码流的客户端",
        RequireConsent = false, //将此设置为 true 没有帮助
        Flow = Flows.AuthorizationCode,
        ClientSecrets = 新列表() {
            新客户秘密(“秘密”)
        },
        RedirectUris = 新列表()
        {
            “本地主机:/特定重定向路径”
        }
    };
  • 我正在调用授权端点,如下所示:
    var 授权端点 =
        AuthorizationEndpointBase +
        "?client_id=" + Uri.EscapeDataString(Options.ClientId) +
        "&范围=默认" +
        "&response_type=代码" +
        "&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
        "&state=" + Uri.EscapeDataString(state);
    Response.Redirect(authorizationEndpoint);
    其中“默认”是我创建的范围。
  • 在我的回调中,我按如下方式调用令牌端点:
    IReadableStringCollection 查询 = Request.Query;
    string code = getValueFromQueryString("code", query);
    var tokenRequestParameters = 新列表>()
        {
            新的 KeyValuePair("client_id", Options.ClientId),
            新的 KeyValuePair("redirect_uri", GenerateRedirectUri()),
            新的 KeyValuePair("client_secret", Options.ClientSecret),
            新的 KeyValuePair(“代码”,代码),
            新的 KeyValuePair("grant_type", "authorization_code"),
        };
    var requestContent = new FormUrlEncodedContent(tokenRequestParameters);
    HttpResponseMessage 响应 = 等待 _httpClient.PostAsync(TokenEndpoint, requestContent, Request.CallCancelled);
    response.EnsureSuccessStatusCode();
    字符串 oauthTokenResponse = 等待 response.Content.ReadAsStringAsync();
    

当我调用令牌端点时,我在 Identity Server 上的登录会显示以下内容(在验证授权码之后):

    iisexpress.exe 信息:0 : [Thinktecture.IdentityServer.Core.Validation.TokenRequestValidator]: 7/13/2015 1:44:07 PM +00:00 -- 令牌请求验证成功
     {
      "ClientId": "SomeId",
      "ClientName": "具有身份验证代码流的客户端",
      "GrantType": "授权码",
      “授权码”:“f8f795e649044067ebd96a341c5af8c3”
    }
    iisexpress.exe 信息:0:[Thinktecture.IdentityServer.Core.ResponseHandling.TokenResponseGenerator]:7/13/2015 1:44:07 PM +00:00 -- 创建令牌响应
    iisexpress.exe 信息:0 : [Thinktecture.IdentityServer.Core.ResponseHandling.TokenResponseGenerator]: 7/13/2015 1:44:07 PM +00:00 -- 处理授权码请求
    调试:[Thinktecture.IdentityServer.Core.Services.Default.DefaultTokenService]:7/13/2015 1:44:07 PM +00:00 -- 创建访问令牌
    调试:[Thinktecture.IdentityServer.Core.Services.Default.DefaultTokenService]:7/13/2015 1:44:07 PM +00:00 -- 创建参考访问令牌
    iisexpress.exe 信息:0:[Thinktecture.IdentityServer.Core.Endpoints.TokenEndpointController]:7/13/2015 1:44:07 PM +00:00 -- 结束令牌请求
    iisexpress.exe 信息:0:[Thinktecture.IdentityServer.Core.Results.TokenResult]:7/13/2015 1:44:07 PM +00:00 -- 返回令牌响应。

我不确定还有什么相关的,所以我会根据需要提供更多信息。

4

2 回答 2

46

您必须在请求中明确要求“offline_access”。用空格分隔您请求的其他范围。(在下面的示例中,我将 'Default' 替换为 'MyApi' 以明确我们正在谈论您的应用程序定义的范围。)

&scope=MyApi offline_access 

但是,您还必须授予该客户端获取刷新令牌的权利,这不仅仅取决于您选择的流程:

var client = new Client()
{
    ... //All the stuff you were doing before

    ScopeRestrictions = new List<string>
    { 
        "MyApi",
        StandardScopes.OfflineAccess.Name, //"offline_access" -for refresh tokens
        //Other commonly requested scopes:
        //StandardScopes.OpenId.Name, //"openid"
        //StandardScopes.Email.Name,  //"email"

    },
}

您可能还需要将“offline_access”添加到您的范围存储。范围存储是 Identity Server 知道的范围列表。您的问题没有提到您的范围存储是如何在您的项目中设置的,因此您可能已经拥有它。但是,如果上述方法不能立即为您工作,您可能需要在您正在使用的示例中四处寻找类似的代码并添加 OfflineAccess。

var scopeStore = new InMemoryScopeStore(new Scope[]{
    StandardScopes.OpenId,
    StandardScopes.Profile,
    StandardScopes.Email,
    StandardScopes.OfflineAccess,  //<--- ensure this is here to allow refresh tokens
    new Scope{
        Enabled = true,
        Name = "MyApi"
    },
}
于 2015-07-14T17:12:32.937 回答
2

发送令牌请求时在范围内添加 offline_access 值

new Client
            {
                ClientId = "ro.angular",
                AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,

                ClientSecrets =
                {
                    new Secret("secret".Sha256())
                },
                AllowedScopes = {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
                    IdentityServerConstants.StandardScopes.Email,
                    IdentityServerConstants.StandardScopes.Address,
                    "api1",
                    IdentityServerConstants.StandardScopes.OfflineAccess
                },
                AllowOfflineAccess = true,
                RefreshTokenUsage = TokenUsage.ReUse,
                RefreshTokenExpiration = TokenExpiration.Sliding

            }

获取刷新令牌

使用刷新令牌获取新的访问令牌

于 2019-12-05T07:57:11.937 回答