Подтвердить что ты не робот

Identity Server не возвращает токен обновления

Я пытаюсь настроить Thinktecture Identity Server 3, но я не могу заставить его возвращать токен обновления при обмене кодом авторизации (или при использовании потока ResourceOwner, но я собираюсь сосредоточиться на код авторизации, поскольку это более важно для меня прямо сейчас). Я получаю токены доступа и могу использовать их для проверки подлинности только отлично, но, похоже, он даже не генерирует токены обновления, которые я ожидаю получить. Есть ли что-то особенное, что мне нужно сделать, чтобы заставить Identity Server возвращать токены обновления?

Я просмотрел документацию, но не видел ничего, что я настроил неправильно, и единственное, что на их странице на обновить токены, что я не делаю, явно запрашивает область "offline_access" при отправке пользователя там для аутентификации, потому что всякий раз, когда я пытаюсь, я получаю ошибку "недопустимый объем". Поэтому я беру выражение Thinktecture "Запросить область офлайн_access (через код или ресурс владельца ресурса)", чтобы означать, что область offline_access автоматически запрашивается на основе потока, который вы используете.

Я пытаюсь выполнить их примеры приложений (И исходный код для существующего промежуточного ПО Owin из Katana Project), насколько мне лучше может, и моя настройка выглядит следующим образом:

  • Я создал клиент, используя свой класс клиентов, вручную указав следующее:
    var client = new Client()
    {
        ClientId = "SomeId",
        ClientName = "Client with Authentication Code Flow",
        RequireConsent = false, //Setting this to true didn't help
        Flow = Flows.AuthorizationCode,
        ClientSecrets = new List() {
            new ClientSecret("secret")
        },
        RedirectUris = new List()
        {
            "localhost:/specific-redirect-path"
        }
    };
  • Я делаю вызов конечной точке авторизации следующим образом:
    var authorizationEndpoint =
        AuthorizationEndpointBase +
        "?client_id=" + Uri.EscapeDataString(Options.ClientId) +
        "&scope=Default" +
        "&response_type=code" +
        "&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
        "&state=" + Uri.EscapeDataString(state);
    Response.Redirect(authorizationEndpoint);
    где "По умолчанию" - это область, которую я создал.
  • В моем обратном вызове я вызываю конечную точку маркера следующим образом:
    IReadableStringCollection query = Request.Query;
    string code = getValueFromQueryString("code", query);
    var tokenRequestParameters = new List>()
        {
            new KeyValuePair("client_id", Options.ClientId),
            new KeyValuePair("redirect_uri", GenerateRedirectUri()),
            new KeyValuePair("client_secret", Options.ClientSecret),
            new KeyValuePair("code", code),
            new KeyValuePair("grant_type", "authorization_code"),
        };
    var requestContent = new FormUrlEncodedContent(tokenRequestParameters);
    HttpResponseMessage response = await _httpClient.PostAsync(TokenEndpoint, requestContent, Request.CallCancelled);
    response.EnsureSuccessStatusCode();
    string oauthTokenResponse = await response.Content.ReadAsStringAsync();
    

Когда я делаю вызов конечной точки маркера, мой журнал на Identity Server отображает следующее (после проверки кода авторизации):

    iisexpress.exe Information: 0 : [Thinktecture.IdentityServer.Core.Validation.TokenRequestValidator]: 7/13/2015 1:44:07 PM +00:00 -- Token request validation success
     {
      "ClientId": "SomeId",
      "ClientName": "Client with Authentication Code Flow",
      "GrantType": "authorization_code",
      "AuthorizationCode": "f8f795e649044067ebd96a341c5af8c3"
    }
    iisexpress.exe Information: 0 : [Thinktecture.IdentityServer.Core.ResponseHandling.TokenResponseGenerator]: 7/13/2015 1:44:07 PM +00:00 -- Creating token response
    iisexpress.exe Information: 0 : [Thinktecture.IdentityServer.Core.ResponseHandling.TokenResponseGenerator]: 7/13/2015 1:44:07 PM +00:00 -- Processing authorization code request
    Debug: [Thinktecture.IdentityServer.Core.Services.Default.DefaultTokenService]: 7/13/2015 1:44:07 PM +00:00 -- Creating access token
    Debug: [Thinktecture.IdentityServer.Core.Services.Default.DefaultTokenService]: 7/13/2015 1:44:07 PM +00:00 -- Creating reference access token
    iisexpress.exe Information: 0 : [Thinktecture.IdentityServer.Core.Endpoints.TokenEndpointController]: 7/13/2015 1:44:07 PM +00:00 -- End token request
    iisexpress.exe Information: 0 : [Thinktecture.IdentityServer.Core.Results.TokenResult]: 7/13/2015 1:44:07 PM +00:00 -- Returning token response.

Я не уверен, что еще будет уместно, поэтому я буду предоставлять дополнительную информацию по мере необходимости.

4b9b3361

Ответ 1

Вам нужно явно запросить "offline_access" в вашем запросе. Отделите другие области, которые вы запрашиваете, с пробелом. (В моих примерах ниже я заменяю "По умолчанию" на "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. В вашем вопросе не упоминается, как ваш магазин области настроен в вашем проекте, поэтому у вас его уже может быть. Но если вышеописанное не сразу работает для вас, вы можете посмотреть вокруг этого кода в примере, в котором вы работаете, и добавить автономный доступ.

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"
    },
}