Проверка подлинности пользователей с помощью WS-Federation в ASP.NET Core

В этом руководстве показано, как разрешить пользователям входить с помощью поставщика проверки подлинности WS-Federation, например службы федерации Active Directory (AD FS) (ADFS) или идентификатора Microsoft Entra. В нем используется пример приложения ASP.NET Core, описанного в Facebook, Google и внешней проверке подлинности поставщика.

Для приложений ASP.NET Core поддержка WS-Federation предоставляется Microsoft.AspNetCore.Authentication.WsFederation. Этот компонент переносится из Microsoft.Owin.Security.WsFederation и использует многие из механики этого компонента. Однако компоненты отличаются несколькими важными способами.

По умолчанию новое ПО промежуточного слоя:

  • Не разрешает незапрошенные имена входа. Эта функция протокола WS-Federation уязвима для атак XSRF. Однако его можно включить с AllowUnsolicitedLogins помощью параметра.
  • Не проверка каждую запись формы для сообщений о входе. Только запросы к ней CallbackPath проверка для входа. CallbackPath По умолчанию /signin-wsfed их можно изменить с помощью унаследованного RemoteAuthenticationOptions.CallbackPath свойства WsFederationOptions класса. Этот путь можно предоставить другим поставщикам проверки подлинности, включив SkipUnrecognizedRequests этот параметр.

Регистрация приложения в Active Directory

службы федерации Active Directory;

  • Откройте мастер добавления доверия проверяющей стороны сервера из консоли управления ADFS:

Add Relying Party Trust Wizard: Welcome

  • Выберите ввод данных вручную:

Add Relying Party Trust Wizard: Select Data Source

  • Введите отображаемое имя проверяющей стороны. Имя не важно для приложения ASP.NET Core.

  • Microsoft.AspNetCore.Authentication.WsFederation не поддерживает шифрование токенов, поэтому не настраивайте сертификат шифрования маркеров:

Add Relying Party Trust Wizard: Configure Certificate

  • Включите поддержку пассивного протокола WS-Federation с помощью URL-адреса приложения. Проверьте правильность порта для приложения:

Add Relying Party Trust Wizard: Configure URL

Примечание.

Это должен быть URL-адрес HTTPS. Служба IIS Express может предоставить самозаверяющий сертификат при размещении приложения во время разработки. Kestrel требуется настройка сертификата вручную. Дополнительные сведения см. в Kestrel документации .

  • Нажмите кнопку "Далее" остальной части мастера и "Закрыть " в конце.

  • ASP.NET Core Identity требует утверждения идентификатора имени . Добавьте его из диалогового окна "Изменение правил утверждений":

Edit Claim Rules

  • В мастере добавления правила утверждения преобразования оставьте выбранный шаблон "Отправить атрибуты LDAP" по умолчанию в качестве шаблона утверждений и нажмите кнопку "Далее". Добавьте правило, которое сопоставляет атрибут LDAP SAM-Account-Name с исходящим утверждением идентификатора имени:

Add Transform Claim Rule Wizard: Configure Claim Rule

  • Нажмите кнопку "Готово>ОК" в окне "Изменить правила утверждений".

Microsoft Entra ID

  • Перейдите в колонку регистрации приложений клиента Microsoft Entra ID. Нажмите кнопку " Создать регистрацию приложения":

Microsoft Entra ID: App registrations

  • Введите имя регистрации приложения. Это не важно для приложения ASP.NET Core.
  • Введите URL-адрес, который приложение прослушивает в качестве URL-адреса для входа:

Microsoft Entra ID: Create app registration

  • Щелкните конечные точки и запишите URL-адрес документа метаданных федерации. Это ПО промежуточного слоя MetadataAddressWS-Федерации:

Microsoft Entra ID: Endpoints

  • Перейдите к новой регистрации приложения. Щелкните "Предоставить API". Нажмите кнопку "Сохранить идентификатор приложения URI".> Запишите URI идентификатора приложения. Это ПО промежуточного слоя WtrealmWS-Федерации:

Microsoft Entra ID: App registration properties

Использование WS-Федерации без ASP.NET Core Identity

ПО промежуточного слоя WS-Федерации можно использовать без Identity. Например:

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(sharedOptions =>
    {
        sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
    })
     .AddWsFederation(options =>
     {
         options.Wtrealm = Configuration["wsfed:realm"];
         options.MetadataAddress = Configuration["wsfed:metadata"];
     })
     .AddCookie();

    services.AddControllersWithViews();
    services.AddRazorPages();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }
    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
        endpoints.MapRazorPages();
    });
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(sharedOptions =>
    {
        sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
    })
    .AddWsFederation(options =>
    {
        options.Wtrealm = Configuration["wsfed:realm"];
        options.MetadataAddress = Configuration["wsfed:metadata"];
    })
    .AddCookie();

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();

    app.UseAuthentication();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

Добавление WS-Federation в качестве внешнего поставщика входа для ASP.NET Core Identity

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();


    services.AddAuthentication()
        .AddWsFederation(options =>
        {
            // MetadataAddress represents the Active Directory instance used to authenticate users.
            options.MetadataAddress = "https://<ADFS FQDN or AAD tenant>/FederationMetadata/2007-06/FederationMetadata.xml";

            // Wtrealm is the app's identifier in the Active Directory instance.
            // For ADFS, use the relying party's identifier, its WS-Federation Passive protocol URL:
            options.Wtrealm = "https://localhost:44307/";

            // For AAD, use the Application ID URI from the app registration's Overview blade:
            options.Wtrealm = "api://bbd35166-7c13-49f3-8041-9551f2847b69";
        });

    services.AddControllersWithViews();
    services.AddRazorPages();
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>()
        .AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddAuthentication()
        .AddWsFederation(options =>
        {
            // MetadataAddress represents the Active Directory instance used to authenticate users.
            options.MetadataAddress = "https://<ADFS FQDN or AAD tenant>/FederationMetadata/2007-06/FederationMetadata.xml";

            // Wtrealm is the app's identifier in the Active Directory instance.
            // For ADFS, use the relying party's identifier, its WS-Federation Passive protocol URL:
            options.Wtrealm = "https://localhost:44307/";

            // For AAD, use the Application ID URI from the app registration's Overview blade:
            options.Wtrealm = "api://bbd35166-7c13-49f3-8041-9551f2847b69";
        });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

Перегрузка AddAuthentication(IServiceCollection, String) задает DefaultScheme свойство. Перегрузка AddAuthentication(IServiceCollection, Action<AuthenticationOptions>) позволяет настраивать параметры проверки подлинности, которые можно использовать для настройки схем проверки подлинности по умолчанию для различных целей. Последующие вызовы переопределения AddAuthentication ранее настроенных AuthenticationOptions свойств.

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

Вход с помощью WS-Federation

Перейдите к приложению и щелкните ссылку "Войти" в заголовке навигации. Существует возможность входа с помощью WsFederation: Log in page

При использовании ADFS в качестве поставщика кнопка перенаправляется на страницу входа ADFS: ADFS sign-in page

С идентификатором Microsoft Entra в качестве поставщика кнопка перенаправляется на страницу входа в Microsoft Entra ID: Microsoft Entra ID sign-in page

Успешный вход для нового пользователя перенаправляется на страницу регистрации пользователей приложения: Register page