В пакете безопасности нет учетных данных при запросе билета Kerberos при олицетворении другого пользователя

Контекст: настраиваемый обратный прокси-сервер / шлюз API, встроенный в C# поверх IIS и правил перезаписи IIS, с использованием промежуточного программного обеспечения OWIN.

Цель: я бы хотел, чтобы прокси-сервер сначала аутентифицировал входящий запрос (это легко настроить в IIS). При наличии идентификатора промежуточное программное обеспечение OWIN должно утверждать некоторые вещи на основе аутентифицированного пользователя. Однако впоследствии запрос должен быть отправлен на внутренний API, который также проходит проверку подлинности Windows.

Мое попытанное решение: перед дальнейшей отправкой запроса промежуточное ПО OWIN должно выдать себя за аутентифицированную идентификационную информацию, запросить билет Kerberos и поместить его в заголовок авторизации (как Negotiate XXXXX.....).

Вот код, использующий стандартные библиотеки C#:

var identity = (WindowsIdentity) context.Request.User.Identity;
using (var impersonation = identity.Impersonate())
{
    var spn = "HTTP/" + backendHostname; // e.g. HTTP/myapi.mydomain.com
    var tokenProvider = new KerberosSecurityTokenProvider(spn, TokenImpersonationLevel.Impersonation);
    var token = tokenProvider.GetToken(TimeSpan.FromMinutes(1)) as KerberosRequestorSecurityToken;
    var ticketBytes = token.GetRequest();
    var ticket = Convert.ToBase64String(ticketBytes);
    context.Request.Headers.Append("Negotiate", ticket);
}

Вот альтернативная реализация, которую я попробовал, используя NSSPI:

var identity = (WindowsIdentity) context.Request.User.Identity;
using (var impersonation = identity.Impersonate())
{
    var clientCredentials = new ClientCurrentCredential(PackageNames.Kerberos);
    var client = new ClientContext(
        clientCredentials,
        "HTTP/" + backendHostname, // e.g. HTTP/myapi.mydomain.com
        ContextAttrib.MutualAuth |
        ContextAttrib.InitIdentify |
        ContextAttrib.Confidentiality |
        ContextAttrib.ReplayDetect |
        ContextAttrib.SequenceDetect |
        ContextAttrib.Connection |
        ContextAttrib.Delegate
    );
    var clientStatus = client.Init(null, out var tokenBytes);
    var token = Convert.ToBase64String(tokenBytes);
    context.Request.Headers.Append("Negotiate", token);
}

Обе реализации выдают исключение, которое сводится к следующей ошибке Win32:

В пакете безопасности отсутствуют учетные данные

Важная информация:

  • прокси-сервер размещен в IIS, работает под учетной записью службы (скажем, srv_ApiGateway
  • useAppPoolCredentials в IIS установлен на True (иначе IIS не сможет даже аутентифицировать первоначальный запрос, используя Kerberos)
  • учетная запись службы (srv_ApiGateway) настроен для делегирования в AD Trust this user for delegation to any service (Kerberos only)
  • В обеих реализациях удаление олицетворения и простой запрос билета в качестве учетной записи службы (только для справки)
  • И прокси-сервер, и бэкэнд-API имеют правильные имена участников-служб (прямые запросы проходят проверку подлинности с использованием Kerberos).
  • WindowsIdentity.GetCurrent().ImpersonationLevel внутри using возвращается ImpersonationLevel.Impersonation (это должно быть Delegation)

Кто-нибудь есть какие-либо предложения относительно того, что может быть причиной этого и как я могу исправить этот вариант использования обратного прокси-сервера двойного прыжка? Любая помощь приветствуется:)

1 ответ

Причина, по которой уровень олицетворения не был установлен Delegation из-за недействительного билета. По какой-то причине Google Chrome не будет запрашивать билет делегирования для пользователя, даже если домен находится в белом списке (согласно этим документам). Попытка с IE, а затем с использованием Chrome работала, хотя это не совсем решение.

Другие вопросы по тегам