IdentityServer Вход в систему с внешним поставщиком не работает в течение длительного времени login_hint или acr_values - PullRequest
0 голосов
/ 14 мая 2018

В моем OpenIdConnectAuthenticationOptions я установил OpenIdConnectAuthenticationNotifications RedirectToIdentityProvider

Это выглядит так:

RedirectToIdentityProvider = n =>
{
    if (n.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnectRequestType.AuthenticationRequest)
    {
        n.ProtocolMessage.LoginHint = "LoginHint";
        n.ProtocolMessage.AcrValues = "idp:CustomIdProvider";
    }
    return Task.FromResult(0);
}

В этом примере я могу получить LoginHint, и все работает нормально.

Теперь, если я установлю LoginHint на что-то около 1000 символов (То же самое происходит для AcrValues), IdentityServer показывает сообщение об ошибке:

Произошла ошибка, определяющая, в какое приложение вы входите. Вернитесь в приложение и попробуйте снова.

и журналы показывают это сообщение:

Не найдено cookie, совпадающих с идентификатором входа

Это происходит только тогда, когда LoginHint (или AcrValues) достигает определенного размера

Кажется, существует проблема при хранении или чтении файлов cookie. может быть, они большие

Что я уже пробовал / настроил:

Web Config для клиента и сервера ( согласно этому ответу все эти значения должны быть достаточно высокими, я уменьшу их до соответствующих значений, когда он работает):

<system.web>
    <httpRuntime targetFramework="4.6.1" maxUrlLength="109990" maxQueryStringLength="100000" maxRequestLength="256000" />
</system.web>
<!--...-->
<requestFiltering>
    <requestLimits maxQueryString="100000" maxAllowedContentLength="1073741824" />
</requestFiltering>

InputLengthRestrictions в IdentityServerOptions (снова значения должны быть достаточными):

InputLengthRestrictions = new InputLengthRestrictions
{
    UserName = 51200,
    AcrValues = 51200,
    LoginHint = 51200
}

Это дополнительный вопрос для этого: Отправка пользовательского параметра внешнему провайдеру идентификации

EDIT:

Больше информации о моей структуре:

Мой клиент получает токен в качестве параметра запроса, который может быть очень длинным (около 900 символов).
Теперь клиент перенаправляет на IdentityServer, используя следующие параметры: app.UseOpenIdConnectAuthentication(options);

Клиенты Startup.cs:

RedirectToIdentityProvider = n =>
{
    if (n.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnectRequestType.AuthenticationRequest)
    {
        var token = n.Request.Query.Get("token");
        if (token != null)
        {
            n.ProtocolMessage.Parameters.Add("token", token);
            n.ProtocolMessage.AcrValues = "idp:CustomIdP";
        }

    }
    return Task.FromResult(0);
}

Остальные options довольно простые

На моем IdentityServer я настраиваю свойство AuthenticationOptions 'IdentityProviders, как вы можете видеть в этом отрывке из моей Конфигурации IdServer, и я также устанавливаю InputLengthRestrictions на высокое значение, просто для безопасности:

IdentityServer Startup.cs:

IdentityServerOptions options = new IdentityServerOptions
{
    InputLengthRestrictions = new InputLengthRestrictions
    {
        RedirectUri = 51200,
        AcrValues = 51200,
        LoginHint = 51200
    },
    AuthenticationOptions = new AuthenticationOptions {

        CookieOptions = new IdentityServer3.Core.Configuration.CookieOptions
        {
            SessionStoreProvider = new SessionStoreProvider()
        },
        IdentityProviders = ConfigureIdentityProviders,
    }
};
idsrvApp.UseIdentityServer(options);

Затем я настраиваю свои IdentityProviders, мой IdentityProvider использует токен из параметра, указанного в Clients Startup.cs Это работает отлично для короткого токена, все называется так, как должно быть.

Но , если токен слишком длинный, он даже не заходит так далеко. Я предполагаю, что корень проблемы лежит в OpenIdConnectAuthenticationHandler

РЕДАКТИРОВАТЬ 2

Почему предел достигнут так быстро:

Видимо, мой токен добавляется дважды в запрос к IdentityServer.

По этой причине предел для куки-файлов достигается довольно быстро.

Клиенты Startup.cs:

RedirectToIdentityProvider = n =>
{
    if (n.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnectRequestType.AuthenticationRequest)
    {
        var token = n.Request.Query.Get("token");
        if (token != null)
        {
            n.ProtocolMessage.Parameters.Add("token", token);
            n.ProtocolMessage.AcrValues = "idp:CustomIdP";
        }

    }
    return Task.FromResult(0);
}

Здесь я беру токен из QueryString. Но то, что я пропустил здесь, n.ProtocolMessage уже содержит RequestUri как параметр State, который содержит token . Таким образом, токен отправляется дважды на IdentityServer. Если я удаляю токен из state -Параметра (что правильно делать, так как он мне не нужен при перенаправлении назад) и добавляю его как AcrValue, он отправляет его в IdentityServer, как и ожидалось.

Но все же вопрос остается.

Что если токен действительно длинный?

1 Ответ

0 голосов
/ 18 июня 2018

Я не могу быть уверен, но, похоже, это может быть проблема максимального размера куки.
Куки могут хранить только 4096 байт в большинстве браузеров , и если куки хранятся в UTF-32, например, тогда 1024 символа займут все это пространство и ваш файл cookie будет обрезан.

Вы можете попробовать переопределить один из CookieOptions свойства в AuthenticationOptions .

В классе CookieOptions вы можете указать IAuthenticationSessionStoreProvider .Согласно комментарию к свойству, это может быть решение, которое вы ищете, по крайней мере, вы сможете отлаживать то, что идет не так.

/// <summary>
///   An optional container in which to store the identity across requests.
///   When used, only a session identifier is sent
///     to the client. This can be used to mitigate potential problems 
///     with very large identities.
/// </summary>
public IAuthenticationSessionStoreProvider SessionStoreProvider { get; set; }

Не существует реализации по умолчанию для IAuthenticationSessionStoreProvider, но выможно посмотреть, как он используется внутри AuthenticationSessionStoreWrapper

Он упакован в AuthenticationSessionStoreWrapper, если вы добавляете провайдера:

static IAuthenticationSessionStore GetSessionStore(IAuthenticationSessionStoreProvider provider)
{
    return provider != null ? new AuthenticationSessionStoreWrapper(provider) : null;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...