В пакете безопасности нет учетных данных при запросе билета 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
) настроен для делегирования в ADTrust this user for delegation to any service (Kerberos only)
- В обеих реализациях удаление олицетворения и простой запрос билета в качестве учетной записи службы (только для справки)
- И прокси-сервер, и бэкэнд-API имеют правильные имена участников-служб (прямые запросы проходят проверку подлинности с использованием Kerberos).
WindowsIdentity.GetCurrent().ImpersonationLevel
внутриusing
возвращаетсяImpersonationLevel.Impersonation
(это должно бытьDelegation
)
Кто-нибудь есть какие-либо предложения относительно того, что может быть причиной этого и как я могу исправить этот вариант использования обратного прокси-сервера двойного прыжка? Любая помощь приветствуется:)
1 ответ
Причина, по которой уровень олицетворения не был установлен Delegation
из-за недействительного билета. По какой-то причине Google Chrome не будет запрашивать билет делегирования для пользователя, даже если домен находится в белом списке (согласно этим документам). Попытка с IE, а затем с использованием Chrome работала, хотя это не совсем решение.