Как реализовать проверку подлинности Windows с помощью IdentityServer 4

Как правильно реализовать проверку подлинности Windows с помощью сервера идентификации 4? Есть ли образцы для этого?

Я посмотрел исходный код IdentityServer 4 и в проекте Host в AccountController. Я заметил, что есть проверки подлинности Windows, и они реализованы как внешний поставщик. Но я не могу работать с конфигурацией. Кто-нибудь успешно реализовал проверку подлинности Windows с помощью idsrv4 и как?

Ответ 1

Скоро будет больше документации:

https://identityserver4.readthedocs.io

Но короче - да с точки зрения IdentityServer Аутентификация Windows является внешним провайдером (в отличие от основного файла cookie аутентификации IS).

Нет ничего, что вам нужно сделать для реализации проверки подлинности Windows - просто используйте хост, который его поддерживает.

Это либо

  • Kestrel с интеграцией IIS
  • Weblistener

В обоих случаях вы вызываете машину Windows, бросая вызов схеме Negotiate или NTLM. Это не специфично для IS, а как работает ASP.NET Core.

Наш пользовательский интерфейс быстрого запуска показывает, как это сделать - проверьте AccountController.

https://github.com/IdentityServer/IdentityServer4.Quickstart.UI

Ответ 2

Для тех, кто сталкивается с этим в результатах поиска, у которых возникает проблема с запуском быстрого запуска с быстрым стартом ASPNET Identity, вот недостающие части.

По большей части вы хотите использовать код ASPNET Identity, используя SignInManager для тяжелого подъема. Как только вы доберетесь туда и добавите код auth в окне быстрого запуска, вы должны дойти до точки, где все выглядит так, как будто оно работает, но вы получаете нуль в этой строке в обратном вызове:

 ExternalLoginInfo info = await _signInManager.GetExternalLoginInfoAsync();

Чтобы Windows рассматривалась как реальный внешний провайдер, вместо добавления "схемы" к свойствам auth вокруг строки 163, вы хотите изменить ключ на "LoginProvider":

properties.Items.Add("LoginProvider", AccountOptions.WindowsAuthenticationSchemeName);

Я использую запрос домена для получения дополнительной информации о моих пользователях, выглядит примерно так:

using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, domain))
using (UserPrincipal up = UserPrincipal.FindByIdentity(pc, wp.Identity.Name))
{
    if (up == null)
    {
        throw new NullReferenceException($"Unable to find user: {wp.Identity.Name}");
    }

    id.AddClaim(new Claim(ClaimTypes.NameIdentifier, up.Sid.Value));
    id.AddClaim(new Claim(JwtClaimTypes.Subject, wp.Identity.Name));
    id.AddClaim(new Claim(JwtClaimTypes.Name, wp.Identity.Name));
    id.AddClaim(new Claim(JwtClaimTypes.Email, up.EmailAddress));
    id.AddClaim(new Claim(Constants.ClaimTypes.Upn, up.UserPrincipalName));
    id.AddClaim(new Claim(JwtClaimTypes.GivenName, up.GivenName));
    id.AddClaim(new Claim(JwtClaimTypes.FamilyName, up.Surname));
}

Какие претензии вы добавляете, зависит от вас, но вам нужен один из типов ClaimTypes.NameIdentifier для поиска SigninManager. SID кажется лучшим для меня. Последнее, что нужно изменить, - вызов SignInAsync для использования правильной схемы по строке 178-181:

await HttpContext.SignInAsync(IdentityConstants.ExternalScheme, new ClaimsPrincipal(id), properties);

Если вы не переопределяете схемы по умолчанию, которые IdentityServer4 использует в .net core 2, это правильная схема по умолчанию. И теперь ваш вызов GetExternalLoginInfoAsync в обратном вызове будет работать, и вы можете продолжить!

Ответ 3

В AccountOptions.cs вашего Identity Server убедитесь, что public static bool WindowsAuthenticationEnabled = true;, я думаю, что у quickstart это по умолчанию было false

Убедитесь, что ваш пул приложений для сервера идентификации использует учетную запись с надлежащими учетными данными (я предполагаю учетную запись, которая может запрашивать AD). Я не мог использовать встроенные учетные записи AppPoolIdentity, LocalService или Network. LocalSystem почти сработала, но через другую ошибку.

Войдите как минимум один раз на этот веб-сервер с учетной записью, созданной выше для пула приложений. Эта учетная запись не должна быть каким-либо администратором. Задайте дополнительные параметры в пуле приложений, чтобы загрузить профиль.

Используйте анонимные и учетные данные Windows, установленные в IIS в корневом каталоге вашего удостоверения, вам не нужны дайджест или базовые.

Ответ 4

Выпуск:

Как и я, вы, вероятно, попали сюда после того, как вы выполнили все краткие руководства и учебные пособия по ASP.NET IdentityServer 4, которые вы можете найти в надежде на то, что ваша аутентификация Windows будет работать, но не получится, за исключением:

Exception: External authentication error
    Host.Quickstart.Account.ExternalController.Callback() in ExternalController.cs, line 89

Тогда вы, возможно, обнаружили этот result?.Succeeded имеет значение false после вызова HttpContext.AuthenticateAsync(...) в функции Callback а остальные свойства результатов имеют значение null...


Объяснение:

Причина этого заключается в том, что схема аутентификации, проверяемая во время обратного вызова, является IdentityConstants.ExternalScheme...

Однако во время функции ProcessWindowsLoginAsync вызов HttpContext.SignInAsync настроен на использование схемы проверки подлинности IdentityServerConstants.ExternalCookieAuthenticationScheme, которая не соответствует ProcessWindowsLoginAsync вызову и, в свою очередь, приводит к неудачной попытке проверки подлинности Windows.


Решение:

Поэтому все, что нам нужно сделать, чтобы решить эту проблему, это изменить вызов HttpContext.SignInAsync чтобы он соответствовал схеме, ожидаемой обратным вызовом:

await HttpContext.SignInAsync(IdentityConstants.ExternalScheme, new ClaimsPrincipal(id), props);

После этого ваш вход в систему с использованием аутентификации Windows будет успешным, и ваш " танец победы " может начаться !!!


Большое спасибо Дэну за его ответ!

Без его решения я, вероятно, все равно буду рвать на себе волосы.

Дэн также упоминает, что вы должны изменить Properties.Items["scheme"] на "LoginProvider"...

Однако это не является необходимым и приведет к FindUserFromExternalProviderAsync функции FindUserFromExternalProviderAsync, так как она ожидает, что поставщик входа будет указан в свойстве "scheme".

Источник быстрого запуска IdentityServer, по-видимому, был обновлен с тех пор, как Дэн опубликовал свой ответ, поэтому я подумал, что лучше всего опубликовать обновление для тех из вас, кто столкнулся с той же проблемой.