IdentityServer Login с внешним провайдером, который не работает для long login_hint или acr_values

В моем 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 или чтении файлов 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
}

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

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

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

Мой клиент получает токен в качестве параметра запроса, который может быть очень длинным (около 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 -Property, как вы можете видеть в этом отрывке из моей 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

EDIT 2

Почему предел поражается так быстро:

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

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

Клиенты 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 as State, содержащий токен. Таким образом, токен отправляется дважды в IdentityServer. Если я удалю токен из state -Parameter (что правильно делать, поскольку он мне не нужен при перенаправлении назад) и добавьте его как AcrValue он отправит его на IdentityServer, как и ожидалось.

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

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

6
14 мая '18 в 16:45
источник поделиться
1 ответ

Я не могу быть уверен, но, похоже, это может быть проблема с размером файла cookie.
Куки файлы могут хранить только 4096 байт в большинстве браузеров, и если файлы cookie хранятся в 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;
}
1
18 июня '18 в 17:05
источник

Посмотрите другие вопросы по меткам или Задайте вопрос