Sdílet prostřednictvím


Vícefaktorové ověřování v ASP.NET Core

Poznámka:

Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

Upozorňující

Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v tématu .NET a .NET Core Zásady podpory. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

Důležité

Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.

Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

Autor: Damien Bowden

Zobrazení nebo stažení ukázkového kódu (úložiště GitHub damienbod/AspNetCoreHybridFlowWithApi)

Vícefaktorové ověřování (MFA) je proces, při kterém se uživatel během přihlašovací události žádá o další formy identifikace. Tato výzva může být zadání kódu z mobilního telefonu, použití klíče FIDO2 nebo poskytnutí otisku prstu. Pokud potřebujete druhou formu ověřování, zabezpečení se zlepšuje. Další faktor není snadno získán nebo duplikován útočníkem.

Tento článek se zabývá následujícími oblastmi:

  • Co je vícefaktorové ověřování a jaké toky vícefaktorového ověřování se doporučují
  • Konfigurace vícefaktorového ověřování pro stránky správy pomocí ASP.NET Core Identity
  • Odeslání požadavku na přihlášení MFA na server OpenID Connect
  • Vynucení ASP.NET klienta Core OpenID Connect k vyžadování vícefaktorového ověřování

MFA, 2FA

Vícefaktorové ověřování vyžaduje alespoň dva nebo více typů ověření identity, jako je něco, co víte, něco, co máte, nebo biometrické ověření, aby se uživatel mohl ověřit.

Dvojúrovňové ověřování (2FA) je jako podmnožina vícefaktorového ověřování, ale rozdíl spočívá v tom, že vícefaktorové ověřování může vyžadovat dva nebo více faktorů k prokázání identity.

Při použití ASP.NET Core Identityse ve výchozím nastavení podporuje 2FA. Pokud chcete pro konkrétního uživatele povolit nebo zakázat 2FA, nastavte IdentityUser<TKey>.TwoFactorEnabled vlastnost. Výchozí uživatelské rozhraní ASP.NET Core Identity obsahuje stránky pro konfiguraci 2FA.

MFA TOTP (jednorázový algoritmus hesel založený na čase)

Vícefaktorové ověřování využívající TOTP je ve výchozím nastavení podporováno při použití ASP.NET Core Identity. Tento přístup je možné použít společně s libovolnou vyhovující ověřovací aplikací, včetně:

  • Microsoft Authenticator
  • Google Authenticator

Podrobnosti o implementaci najdete v tématu Povolení generování kódu QR pro ověřovací aplikace TOTP v ASP.NET Core.

Pokud chcete zakázat podporu vícefaktorového AddDefaultIdentityhesla, nakonfigurujte ověřování místo AddIdentity . AddDefaultIdentity volání AddDefaultTokenProviders interně, která registruje více zprostředkovatelů tokenů, včetně jednoho pro MFA TOTP. Pokud chcete zaregistrovat pouze konkrétní poskytovatele tokenů, zavolejte AddTokenProvider pro každého požadovaného zprostředkovatele. Další informace o dostupných poskytovatelích tokenů najdete ve zdroji AddDefaultTokenProviders na GitHubu.

Klíče vícefaktorového ověřování / FIDO2 nebo bez hesla

klíč/FIDO2 je aktuálně:

  • Nejbezpečnější způsob dosažení vícefaktorového ověřování.
  • Vícefaktorové ověřování, které chrání před útoky phishing. (stejně jako ověřování certifikátů a Windows pro firmy)

V současné době ASP.NET Core nepodporuje přímo klíče nebo FIDO2. Přístupové klíče/FIDO2 se dají použít pro MFA nebo bez hesla.

Microsoft Entra ID poskytuje podporu pro přístupové klíče/FIDO2 a toky bez hesel. Další informace najdete v tématu Možnosti ověřování bez hesla.

Jiné formy vícefaktorového ověřování bez hesla se nedají chránit před útoky phishing.

MFA SMS

Vícefaktorové ověřování se službou SMS výrazně zvyšuje zabezpečení v porovnání s ověřováním heslem (jednofaktorové ověřování). Použití sms jako druhého faktoru se ale už nedoporučuje. Pro tento typ implementace existuje příliš mnoho známých vektorů útoku.

Pokyny pro NIST

Konfigurace vícefaktorového ověřování pro stránky správy pomocí ASP.NET Core Identity

Vícefaktorové ověřování může být vynuceno, aby uživatelé měli přístup k citlivým stránkám v aplikaci ASP.NET Core Identity . To může být užitečné pro aplikace, ve kterých existují různé úrovně přístupu pro různé identity. Uživatelé můžou například zobrazit data profilu pomocí přihlášení pomocí hesla, ale správce bude muset pro přístup ke stránkám pro správu použít vícefaktorové ověřování.

Rozšíření přihlášení pomocí deklarace vícefaktorového ověřování

Ukázkový kód je nastaven pomocí ASP.NET Core s Identity a Razor Pages. Metoda AddIdentity se používá místo AddDefaultIdentity jedné, takže IUserClaimsPrincipalFactory implementaci lze použít k přidání deklarací identity do identity po úspěšném přihlášení.

builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlite(
        Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddIdentity<IdentityUser, IdentityRole>(options =>
		options.SignIn.RequireConfirmedAccount = false)
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

builder.Services.AddSingleton<IEmailSender, EmailSender>();
builder.Services.AddScoped<IUserClaimsPrincipalFactory<IdentityUser>, 
    AdditionalUserClaimsPrincipalFactory>();

builder.Services.AddAuthorization(options =>
    options.AddPolicy("TwoFactorEnabled", x => x.RequireClaim("amr", "mfa")));

builder.Services.AddRazorPages();

Třída AdditionalUserClaimsPrincipalFactory přidá amr deklaraci identity do deklarací identity uživatele až po úspěšném přihlášení. Hodnota deklarace identity se načítá z databáze. Deklarace identity se tady přidá, protože uživatel by měl přistupovat pouze k vyššímu chráněnému zobrazení, pokud se identita přihlásila pomocí vícefaktorového ověřování. Pokud se zobrazení databáze načítá přímo z databáze místo deklarace identity, je možné k zobrazení přistupovat bez vícefaktorového ověřování přímo po aktivaci vícefaktorového ověřování.

using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;

namespace IdentityStandaloneMfa
{
    public class AdditionalUserClaimsPrincipalFactory : 
        UserClaimsPrincipalFactory<IdentityUser, IdentityRole>
    {
        public AdditionalUserClaimsPrincipalFactory( 
            UserManager<IdentityUser> userManager,
            RoleManager<IdentityRole> roleManager, 
            IOptions<IdentityOptions> optionsAccessor) 
            : base(userManager, roleManager, optionsAccessor)
        {
        }

        public async override Task<ClaimsPrincipal> CreateAsync(IdentityUser user)
        {
            var principal = await base.CreateAsync(user);
            var identity = (ClaimsIdentity)principal.Identity;

            var claims = new List<Claim>();

            if (user.TwoFactorEnabled)
            {
                claims.Add(new Claim("amr", "mfa"));
            }
            else
            {
                claims.Add(new Claim("amr", "pwd"));
            }

            identity.AddClaims(claims);
            return principal;
        }
    }
}

Vzhledem k tomu, že Identity se nastavení služby změnilo ve Startup třídě, musí být aktualizována Identity rozložení. Vygenerujte Identity stránky do aplikace. Definujte rozložení v Identity/Account/Manage/_Layout.cshtml souboru.

@{
    Layout = "/Pages/Shared/_Layout.cshtml";
}

Také přiřaďte rozložení pro všechny stránky pro správu ze Identity stránek:

@{
    Layout = "_Layout.cshtml";
}

Ověření požadavku vícefaktorového ověřování na stránce správy

Stránka pro správu Razor ověří, že se uživatel přihlásil pomocí vícefaktorového ověřování. OnGet V metodě se identita používá pro přístup k deklarace identity uživatele. Deklarace amr identity je zkontrolována pro hodnotu mfa. Pokud identitě chybí tato deklarace identity nebo je false, stránka se přesměruje na stránku Povolit vícefaktorové ověřování. To je možné, protože uživatel se už přihlásil, ale bez vícefaktorového ověřování.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace IdentityStandaloneMfa
{
    public class AdminModel : PageModel
    {
        public IActionResult OnGet()
        {
            var claimTwoFactorEnabled = 
                User.Claims.FirstOrDefault(t => t.Type == "amr");

            if (claimTwoFactorEnabled != null && 
                "mfa".Equals(claimTwoFactorEnabled.Value))
            {
                // You logged in with MFA, do the administrative stuff
            }
            else
            {
                return Redirect(
                    "/Identity/Account/Manage/TwoFactorAuthentication");
            }

            return Page();
        }
    }
}

Logika uživatelského rozhraní pro přepínání přihlašovacích údajů uživatele

Při spuštění se přidala zásada autorizace. Zásada vyžaduje amr deklaraci identity s hodnotou mfa.

services.AddAuthorization(options =>
    options.AddPolicy("TwoFactorEnabled",
        x => x.RequireClaim("amr", "mfa")));

Tuto zásadu _Layout pak můžete použít v zobrazení k zobrazení nebo skrytí nabídky Správce s upozorněním:

@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager
@inject IAuthorizationService AuthorizationService

Pokud se identita přihlásila pomocí vícefaktorového ověřování, zobrazí se nabídka Správce bez upozornění na popis. Když se uživatel přihlásí bez vícefaktorového ověřování, zobrazí se nabídka Správce (nepovoleno) spolu s popisem, který uživatele informuje (vysvětluje upozornění).

@if (SignInManager.IsSignedIn(User))
{
    @if ((AuthorizationService.AuthorizeAsync(User, "TwoFactorEnabled")).Result.Succeeded)
    {
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="" asp-page="/Admin">Admin</a>
        </li>
    }
    else
    {
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="" asp-page="/Admin" 
               id="tooltip-demo"  
               data-toggle="tooltip" 
               data-placement="bottom" 
               title="MFA is NOT enabled. This is required for the Admin Page. If you have activated MFA, then logout, login again.">
                Admin (Not Enabled)
            </a>
        </li>
    }
}

Pokud se uživatel přihlásí bez vícefaktorového ověřování, zobrazí se upozornění:

Ověřování vícefaktorového ověřování správce

Uživatel se přesměruje do zobrazení povolení vícefaktorového ověřování po kliknutí na odkaz Správce :

Správce aktivuje vícefaktorové ověřování.

Odeslání požadavku na přihlášení MFA na server OpenID Connect

Parametr acr_values lze použít k předání mfa požadované hodnoty z klienta na server v žádosti o ověření.

Poznámka:

Aby acr_values to fungovalo, musí být parametr zpracován na serveru OpenID Connect.

Klient OpenID Connect ASP.NET Core

Klientská aplikace ASP.NET Core Razor Pages OpenID Connect používá metodu AddOpenIdConnect pro přihlášení k serveru OpenID Connect. Parametr acr_values se nastaví s mfa hodnotou a odešle se s žádostí o ověření. Slouží OpenIdConnectEvents k přidání.

acr_values Doporučené hodnoty parametrů najdete v tématu Referenční hodnoty metody ověřování.

build.Services.AddAuthentication(options =>
{
	options.DefaultScheme =
		CookieAuthenticationDefaults.AuthenticationScheme;
	options.DefaultChallengeScheme =
		OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
	options.SignInScheme =
		CookieAuthenticationDefaults.AuthenticationScheme;
	options.Authority = "<OpenID Connect server URL>";
	options.RequireHttpsMetadata = true;
	options.ClientId = "<OpenID Connect client ID>";
	options.ClientSecret = "<>";
	options.ResponseType = "code";
	options.UsePkce = true;	
	options.Scope.Add("profile");
	options.Scope.Add("offline_access");
	options.SaveTokens = true;
	options.AdditionalAuthorizationParameters.Add("acr_values", "mfa");
});

Příklad serveru OpenID Connect Duende Identitys ASP.NET Core Identity

Na serveru OpenID Connect, který se implementuje pomocí ASP.NET Core Identity se stránkami Razor , se vytvoří nová stránka s názvem ErrorEnable2FA.cshtml . Zobrazení:

  • Zobrazí, jestli Identity pochází z aplikace, která vyžaduje vícefaktorové ověřování, ale uživatel ho Identityneaktivoval.
  • Informuje uživatele a přidá odkaz k aktivaci.
@{
    ViewData["Title"] = "ErrorEnable2FA";
}

<h1>The client application requires you to have MFA enabled. Enable this, try login again.</h1>

<br />

You can enable MFA to login here:

<br />

<a href="~/Identity/Account/Manage/TwoFactorAuthentication">Enable MFA</a>

Login V metodě se IIdentityServerInteractionService implementace _interaction rozhraní používá pro přístup k parametrům požadavku OpenID Connect. K acr_values parametru AcrValues se přistupuje pomocí vlastnosti. Když klient odeslal tuto mfa sadu, můžete to zkontrolovat.

Pokud se vyžaduje vícefaktorové ověřování a uživatel v ASP.NET Core Identity má povolené vícefaktorové ověřování, přihlášení bude pokračovat. Pokud uživatel nemá povolené vícefaktorové ověřování, uživatel se přesměruje do vlastního zobrazení ErrorEnable2FA.cshtml. Pak ASP.NET Core Identity uživatele přihlásí.

Fido2Store slouží ke kontrole, jestli uživatel aktivoval vícefaktorové ověřování pomocí vlastního zprostředkovatele tokenů FIDO2.

public async Task<IActionResult> OnPost()
{
	// check if we are in the context of an authorization request
	var context = await _interaction.GetAuthorizationContextAsync(Input.ReturnUrl);

	var requires2Fa = context?.AcrValues.Count(t => t.Contains("mfa")) >= 1;

	var user = await _userManager.FindByNameAsync(Input.Username);
	if (user != null && !user.TwoFactorEnabled && requires2Fa)
	{
		return RedirectToPage("/Home/ErrorEnable2FA/Index");
	}

	// code omitted for brevity

	if (ModelState.IsValid)
	{
		var result = await _signInManager.PasswordSignInAsync(Input.Username, Input.Password, Input.RememberLogin, lockoutOnFailure: true);
		if (result.Succeeded)
		{
			// code omitted for brevity
		}
		if (result.RequiresTwoFactor)
		{
			var fido2ItemExistsForUser = await _fido2Store.GetCredentialsByUserNameAsync(user.UserName);
			if (fido2ItemExistsForUser.Count > 0)
			{
				return RedirectToPage("/Account/LoginFido2Mfa", new { area = "Identity", Input.ReturnUrl, Input.RememberLogin });
			}

			return RedirectToPage("/Account/LoginWith2fa", new { area = "Identity", Input.ReturnUrl, RememberMe = Input.RememberLogin });
		}

		await _events.RaiseAsync(new UserLoginFailureEvent(Input.Username, "invalid credentials", clientId: context?.Client.ClientId));
		ModelState.AddModelError(string.Empty, LoginOptions.InvalidCredentialsErrorMessage);
	}

	// something went wrong, show form with error
	await BuildModelAsync(Input.ReturnUrl);
	return Page();
}

Pokud už je uživatel přihlášený, klientská aplikace:

  • Stále ověří amr deklaraci identity.
  • MFA můžete nastavit pomocí odkazu na zobrazení ASP.NET Core Identity .

obrázek acr_values-1

Vynucení ASP.NET klienta Core OpenID Connect k vyžadování vícefaktorového ověřování

Tento příklad ukazuje, jak aplikace ASP.NET Core Razor Page, která k přihlášení používá OpenID Connect, může vyžadovat ověření uživatelů pomocí vícefaktorového ověřování.

K ověření požadavku IAuthorizationRequirement na vícefaktorové ověřování se vytvoří požadavek. Tato možnost se přidá na stránky pomocí zásady, která vyžaduje vícefaktorové ověřování.

using Microsoft.AspNetCore.Authorization;

namespace AspNetCoreRequireMfaOidc;

public class RequireMfa : IAuthorizationRequirement{}

Implementuje AuthorizationHandler se, která použije amr deklaraci identity a zkontroluje hodnotu mfa. Vrátí amr se v id_token úspěšném ověření a může mít mnoho různých hodnot definovaných ve specifikaci referenčních hodnot metody ověřování.

Vrácená hodnota závisí na tom, jak se identita ověřila, a na implementaci serveru OpenID Connect.

RequireMfa Použije AuthorizationHandler požadavek a ověří amr deklaraci identity. Server OpenID Connect lze implementovat pomocí duende Identity Serveru s ASP.NET Core Identity. Když se uživatel přihlásí pomocí toTP, amr deklarace identity se vrátí s hodnotou vícefaktorového ověřování. Pokud používáte jinou implementaci serveru OpenID Connect nebo jiný typ MFA, amr deklarace identity bude nebo může mít jinou hodnotu. Kód musí být rozšířen, aby ho také přijal.

public class RequireMfaHandler : AuthorizationHandler<RequireMfa>
{
	protected override Task HandleRequirementAsync(
		AuthorizationHandlerContext context, 
		RequireMfa requirement)
	{
		if (context == null)
			throw new ArgumentNullException(nameof(context));
		if (requirement == null)
			throw new ArgumentNullException(nameof(requirement));

		var amrClaim =
			context.User.Claims.FirstOrDefault(t => t.Type == "amr");

		if (amrClaim != null && amrClaim.Value == Amr.Mfa)
		{
			context.Succeed(requirement);
		}

		return Task.CompletedTask;
	}
}

V souboru programu se AddOpenIdConnect metoda používá jako výchozí schéma výzvy. Obslužná rutina autorizace, která se používá ke kontrole amr deklarace identity, se přidá do kontejneru Inversion of Control. Pak se vytvoří zásada, která požadavek přidá RequireMfa .

builder.Services.ConfigureApplicationCookie(options =>
        options.Cookie.SecurePolicy =
            CookieSecurePolicy.Always);

builder.Services.AddSingleton<IAuthorizationHandler, RequireMfaHandler>();

builder.Services.AddAuthentication(options =>
{
	options.DefaultScheme =
		CookieAuthenticationDefaults.AuthenticationScheme;
	options.DefaultChallengeScheme =
		OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
	options.SignInScheme =
		CookieAuthenticationDefaults.AuthenticationScheme;
	options.Authority = "https://localhost:44352";
	options.RequireHttpsMetadata = true;
	options.ClientId = "AspNetCoreRequireMfaOidc";
	options.ClientSecret = "AspNetCoreRequireMfaOidcSecret";
	options.ResponseType = "code";
	options.UsePkce = true;	
	options.Scope.Add("profile");
	options.Scope.Add("offline_access");
	options.SaveTokens = true;
});

builder.Services.AddAuthorization(options =>
{
	options.AddPolicy("RequireMfa", policyIsAdminRequirement =>
	{
		policyIsAdminRequirement.Requirements.Add(new RequireMfa());
	});
});

builder.Services.AddRazorPages();

Tato zásada se pak použije na Razor stránce podle potřeby. Zásady je možné přidat globálně i pro celou aplikaci.

[Authorize(Policy= "RequireMfa")]
public class IndexModel : PageModel
{
    public void OnGet()
    {
    }
}

Pokud se uživatel ověří bez vícefaktorového pwd ověřování, amr deklarace identity bude pravděpodobně mít hodnotu. Žádost nebude mít oprávnění pro přístup k této stránce. Pomocí výchozích hodnot se uživatel přesměruje na stránku Account/AccessDenied . Toto chování můžete změnit nebo můžete zde implementovat vlastní logiku. V tomto příkladu se přidá odkaz, aby platný uživatel mohl pro svůj účet nastavit vícefaktorové ověřování.

@page
@model AspNetCoreRequireMfaOidc.AccessDeniedModel
@{
    ViewData["Title"] = "AccessDenied";
    Layout = "~/Pages/Shared/_Layout.cshtml";
}

<h1>AccessDenied</h1>

You require MFA to login here

<a href="https://localhost:44352/Manage/TwoFactorAuthentication">Enable MFA</a>

Teď k stránce nebo webu mají přístup jenom uživatelé, kteří se ověřují pomocí vícefaktorového ověřování. Pokud se použijí různé typy vícefaktorového ověřování nebo pokud je 2FA v pořádku, amr deklarace identity bude mít různé hodnoty a musí se správně zpracovat. Různé servery OpenID Connect také vracejí různé hodnoty pro tuto deklaraci identity a nemusí dodržovat specifikaci referenčních hodnot metody ověřování.

Při přihlašování bez vícefaktorového ověřování (například pomocí hesla):

  • pwdamr hodnotu:

    Amr má hodnotu pwd.

  • Přístup byl odepřen:

    Přístup byl odepřen.

Další možností je přihlášení pomocí jednorázového hesla Identity:

Přihlášení pomocí jednorázového hesla s využitím Identity

Další materiály

Autor: Damien Bowden

Zobrazení nebo stažení ukázkového kódu (úložiště GitHub damienbod/AspNetCoreHybridFlowWithApi)

Vícefaktorové ověřování (MFA) je proces, při kterém se uživatel během přihlašovací události žádá o další formy identifikace. Tato výzva může být zadání kódu z mobilního telefonu, použití klíče FIDO2 nebo poskytnutí otisku prstu. Pokud potřebujete druhou formu ověřování, zabezpečení se zlepšuje. Další faktor není snadno získán nebo duplikován útočníkem.

Tento článek se zabývá následujícími oblastmi:

  • Co je vícefaktorové ověřování a jaké toky vícefaktorového ověřování se doporučují
  • Konfigurace vícefaktorového ověřování pro stránky správy pomocí ASP.NET Core Identity
  • Odeslání požadavku na přihlášení MFA na server OpenID Connect
  • Vynucení ASP.NET klienta Core OpenID Connect k vyžadování vícefaktorového ověřování

MFA, 2FA

Vícefaktorové ověřování vyžaduje alespoň dva nebo více typů ověření identity, jako je něco, co víte, něco, co máte, nebo biometrické ověření, aby se uživatel mohl ověřit.

Dvojúrovňové ověřování (2FA) je jako podmnožina vícefaktorového ověřování, ale rozdíl spočívá v tom, že vícefaktorové ověřování může vyžadovat dva nebo více faktorů k prokázání identity.

Při použití ASP.NET Core Identityse ve výchozím nastavení podporuje 2FA. Pokud chcete pro konkrétního uživatele povolit nebo zakázat 2FA, nastavte IdentityUser<TKey>.TwoFactorEnabled vlastnost. Výchozí uživatelské rozhraní ASP.NET Core Identity obsahuje stránky pro konfiguraci 2FA.

MFA TOTP (jednorázový algoritmus hesel založený na čase)

Vícefaktorové ověřování využívající TOTP je ve výchozím nastavení podporováno při použití ASP.NET Core Identity. Tento přístup je možné použít společně s libovolnou vyhovující ověřovací aplikací, včetně:

  • Microsoft Authenticator
  • Google Authenticator

Podrobnosti o implementaci najdete v tématu Povolení generování kódu QR pro ověřovací aplikace TOTP v ASP.NET Core.

Pokud chcete zakázat podporu vícefaktorového AddDefaultIdentityhesla, nakonfigurujte ověřování místo AddIdentity . AddDefaultIdentity volání AddDefaultTokenProviders interně, která registruje více zprostředkovatelů tokenů, včetně jednoho pro MFA TOTP. Pokud chcete zaregistrovat pouze konkrétní poskytovatele tokenů, zavolejte AddTokenProvider pro každého požadovaného zprostředkovatele. Další informace o dostupných poskytovatelích tokenů najdete ve zdroji AddDefaultTokenProviders na GitHubu.

Klíče vícefaktorového ověřování / FIDO2 nebo bez hesla

klíč/FIDO2 je aktuálně:

  • Nejbezpečnější způsob dosažení vícefaktorového ověřování.
  • Vícefaktorové ověřování, které chrání před útoky phishing. (stejně jako ověřování certifikátů a Windows pro firmy)

V současné době ASP.NET Core nepodporuje přímo klíče nebo FIDO2. Přístupové klíče/FIDO2 se dají použít pro MFA nebo bez hesla.

Microsoft Entra ID poskytuje podporu pro přístupové klíče/FIDO2 a toky bez hesel. Další informace najdete v tématu Možnosti ověřování bez hesla.

Jiné formy vícefaktorového ověřování bez hesla se nedají chránit před útoky phishing.

MFA SMS

Vícefaktorové ověřování se službou SMS výrazně zvyšuje zabezpečení v porovnání s ověřováním heslem (jednofaktorové ověřování). Použití sms jako druhého faktoru se ale už nedoporučuje. Pro tento typ implementace existuje příliš mnoho známých vektorů útoku.

Pokyny pro NIST

Konfigurace vícefaktorového ověřování pro stránky správy pomocí ASP.NET Core Identity

Vícefaktorové ověřování může být vynuceno, aby uživatelé měli přístup k citlivým stránkám v aplikaci ASP.NET Core Identity . To může být užitečné pro aplikace, ve kterých existují různé úrovně přístupu pro různé identity. Uživatelé můžou například zobrazit data profilu pomocí přihlášení pomocí hesla, ale správce bude muset pro přístup ke stránkám pro správu použít vícefaktorové ověřování.

Rozšíření přihlášení pomocí deklarace vícefaktorového ověřování

Ukázkový kód je nastaven pomocí ASP.NET Core s Identity a Razor Pages. Metoda AddIdentity se používá místo AddDefaultIdentity jedné, takže IUserClaimsPrincipalFactory implementaci lze použít k přidání deklarací identity do identity po úspěšném přihlášení.

builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlite(
        Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddIdentity<IdentityUser, IdentityRole>(options =>
		options.SignIn.RequireConfirmedAccount = false)
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

builder.Services.AddSingleton<IEmailSender, EmailSender>();
builder.Services.AddScoped<IUserClaimsPrincipalFactory<IdentityUser>, 
    AdditionalUserClaimsPrincipalFactory>();

builder.Services.AddAuthorization(options =>
    options.AddPolicy("TwoFactorEnabled", x => x.RequireClaim("amr", "mfa")));

builder.Services.AddRazorPages();

Třída AdditionalUserClaimsPrincipalFactory přidá amr deklaraci identity do deklarací identity uživatele až po úspěšném přihlášení. Hodnota deklarace identity se načítá z databáze. Deklarace identity se tady přidá, protože uživatel by měl přistupovat pouze k vyššímu chráněnému zobrazení, pokud se identita přihlásila pomocí vícefaktorového ověřování. Pokud se zobrazení databáze načítá přímo z databáze místo deklarace identity, je možné k zobrazení přistupovat bez vícefaktorového ověřování přímo po aktivaci vícefaktorového ověřování.

using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;

namespace IdentityStandaloneMfa
{
    public class AdditionalUserClaimsPrincipalFactory : 
        UserClaimsPrincipalFactory<IdentityUser, IdentityRole>
    {
        public AdditionalUserClaimsPrincipalFactory( 
            UserManager<IdentityUser> userManager,
            RoleManager<IdentityRole> roleManager, 
            IOptions<IdentityOptions> optionsAccessor) 
            : base(userManager, roleManager, optionsAccessor)
        {
        }

        public async override Task<ClaimsPrincipal> CreateAsync(IdentityUser user)
        {
            var principal = await base.CreateAsync(user);
            var identity = (ClaimsIdentity)principal.Identity;

            var claims = new List<Claim>();

            if (user.TwoFactorEnabled)
            {
                claims.Add(new Claim("amr", "mfa"));
            }
            else
            {
                claims.Add(new Claim("amr", "pwd"));
            }

            identity.AddClaims(claims);
            return principal;
        }
    }
}

Vzhledem k tomu, že Identity se nastavení služby změnilo ve Startup třídě, musí být aktualizována Identity rozložení. Vygenerujte Identity stránky do aplikace. Definujte rozložení v Identity/Account/Manage/_Layout.cshtml souboru.

@{
    Layout = "/Pages/Shared/_Layout.cshtml";
}

Také přiřaďte rozložení pro všechny stránky pro správu ze Identity stránek:

@{
    Layout = "_Layout.cshtml";
}

Ověření požadavku vícefaktorového ověřování na stránce správy

Stránka pro správu Razor ověří, že se uživatel přihlásil pomocí vícefaktorového ověřování. OnGet V metodě se identita používá pro přístup k deklarace identity uživatele. Deklarace amr identity je zkontrolována pro hodnotu mfa. Pokud identitě chybí tato deklarace identity nebo je false, stránka se přesměruje na stránku Povolit vícefaktorové ověřování. To je možné, protože uživatel se už přihlásil, ale bez vícefaktorového ověřování.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace IdentityStandaloneMfa
{
    public class AdminModel : PageModel
    {
        public IActionResult OnGet()
        {
            var claimTwoFactorEnabled = 
                User.Claims.FirstOrDefault(t => t.Type == "amr");

            if (claimTwoFactorEnabled != null && 
                "mfa".Equals(claimTwoFactorEnabled.Value))
            {
                // You logged in with MFA, do the administrative stuff
            }
            else
            {
                return Redirect(
                    "/Identity/Account/Manage/TwoFactorAuthentication");
            }

            return Page();
        }
    }
}

Logika uživatelského rozhraní pro přepínání přihlašovacích údajů uživatele

Při spuštění se přidala zásada autorizace. Zásada vyžaduje amr deklaraci identity s hodnotou mfa.

services.AddAuthorization(options =>
    options.AddPolicy("TwoFactorEnabled",
        x => x.RequireClaim("amr", "mfa")));

Tuto zásadu _Layout pak můžete použít v zobrazení k zobrazení nebo skrytí nabídky Správce s upozorněním:

@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager
@inject IAuthorizationService AuthorizationService

Pokud se identita přihlásila pomocí vícefaktorového ověřování, zobrazí se nabídka Správce bez upozornění na popis. Když se uživatel přihlásí bez vícefaktorového ověřování, zobrazí se nabídka Správce (nepovoleno) spolu s popisem, který uživatele informuje (vysvětluje upozornění).

@if (SignInManager.IsSignedIn(User))
{
    @if ((AuthorizationService.AuthorizeAsync(User, "TwoFactorEnabled")).Result.Succeeded)
    {
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="" asp-page="/Admin">Admin</a>
        </li>
    }
    else
    {
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="" asp-page="/Admin" 
               id="tooltip-demo"  
               data-toggle="tooltip" 
               data-placement="bottom" 
               title="MFA is NOT enabled. This is required for the Admin Page. If you have activated MFA, then logout, login again.">
                Admin (Not Enabled)
            </a>
        </li>
    }
}

Pokud se uživatel přihlásí bez vícefaktorového ověřování, zobrazí se upozornění:

Ověřování vícefaktorového ověřování správce

Uživatel se přesměruje do zobrazení povolení vícefaktorového ověřování po kliknutí na odkaz Správce :

Správce aktivuje vícefaktorové ověřování.

Odeslání požadavku na přihlášení MFA na server OpenID Connect

Parametr acr_values lze použít k předání mfa požadované hodnoty z klienta na server v žádosti o ověření.

Poznámka:

Aby acr_values to fungovalo, musí být parametr zpracován na serveru OpenID Connect.

Klient OpenID Connect ASP.NET Core

Klientská aplikace ASP.NET Core Razor Pages OpenID Connect používá metodu AddOpenIdConnect pro přihlášení k serveru OpenID Connect. Parametr acr_values se nastaví s mfa hodnotou a odešle se s žádostí o ověření. Slouží OpenIdConnectEvents k přidání.

acr_values Doporučené hodnoty parametrů najdete v tématu Referenční hodnoty metody ověřování.

build.Services.AddAuthentication(options =>
{
	options.DefaultScheme =
		CookieAuthenticationDefaults.AuthenticationScheme;
	options.DefaultChallengeScheme =
		OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
	options.SignInScheme =
		CookieAuthenticationDefaults.AuthenticationScheme;
	options.Authority = "<OpenID Connect server URL>";
	options.RequireHttpsMetadata = true;
	options.ClientId = "<OpenID Connect client ID>";
	options.ClientSecret = "<>";
	options.ResponseType = "code";
	options.UsePkce = true;	
	options.Scope.Add("profile");
	options.Scope.Add("offline_access");
	options.SaveTokens = true;
	options.Events = new OpenIdConnectEvents
	{
		OnRedirectToIdentityProvider = context =>
		{
			context.ProtocolMessage.SetParameter("acr_values", "mfa");
			return Task.FromResult(0);
		}
	};
});

Příklad serveru OpenID Connect Duende Identitys ASP.NET Core Identity

Na serveru OpenID Connect, který se implementuje pomocí ASP.NET Core Identity se stránkami Razor , se vytvoří nová stránka s názvem ErrorEnable2FA.cshtml . Zobrazení:

  • Zobrazí, jestli Identity pochází z aplikace, která vyžaduje vícefaktorové ověřování, ale uživatel ho Identityneaktivoval.
  • Informuje uživatele a přidá odkaz k aktivaci.
@{
    ViewData["Title"] = "ErrorEnable2FA";
}

<h1>The client application requires you to have MFA enabled. Enable this, try login again.</h1>

<br />

You can enable MFA to login here:

<br />

<a href="~/Identity/Account/Manage/TwoFactorAuthentication">Enable MFA</a>

Login V metodě se IIdentityServerInteractionService implementace _interaction rozhraní používá pro přístup k parametrům požadavku OpenID Connect. K acr_values parametru AcrValues se přistupuje pomocí vlastnosti. Když klient odeslal tuto mfa sadu, můžete to zkontrolovat.

Pokud se vyžaduje vícefaktorové ověřování a uživatel v ASP.NET Core Identity má povolené vícefaktorové ověřování, přihlášení bude pokračovat. Pokud uživatel nemá povolené vícefaktorové ověřování, uživatel se přesměruje do vlastního zobrazení ErrorEnable2FA.cshtml. Pak ASP.NET Core Identity uživatele přihlásí.

Fido2Store slouží ke kontrole, jestli uživatel aktivoval vícefaktorové ověřování pomocí vlastního zprostředkovatele tokenů FIDO2.

public async Task<IActionResult> OnPost()
{
	// check if we are in the context of an authorization request
	var context = await _interaction.GetAuthorizationContextAsync(Input.ReturnUrl);

	var requires2Fa = context?.AcrValues.Count(t => t.Contains("mfa")) >= 1;

	var user = await _userManager.FindByNameAsync(Input.Username);
	if (user != null && !user.TwoFactorEnabled && requires2Fa)
	{
		return RedirectToPage("/Home/ErrorEnable2FA/Index");
	}

	// code omitted for brevity

	if (ModelState.IsValid)
	{
		var result = await _signInManager.PasswordSignInAsync(Input.Username, Input.Password, Input.RememberLogin, lockoutOnFailure: true);
		if (result.Succeeded)
		{
			// code omitted for brevity
		}
		if (result.RequiresTwoFactor)
		{
			var fido2ItemExistsForUser = await _fido2Store.GetCredentialsByUserNameAsync(user.UserName);
			if (fido2ItemExistsForUser.Count > 0)
			{
				return RedirectToPage("/Account/LoginFido2Mfa", new { area = "Identity", Input.ReturnUrl, Input.RememberLogin });
			}

			return RedirectToPage("/Account/LoginWith2fa", new { area = "Identity", Input.ReturnUrl, RememberMe = Input.RememberLogin });
		}

		await _events.RaiseAsync(new UserLoginFailureEvent(Input.Username, "invalid credentials", clientId: context?.Client.ClientId));
		ModelState.AddModelError(string.Empty, LoginOptions.InvalidCredentialsErrorMessage);
	}

	// something went wrong, show form with error
	await BuildModelAsync(Input.ReturnUrl);
	return Page();
}

Pokud už je uživatel přihlášený, klientská aplikace:

  • Stále ověří amr deklaraci identity.
  • MFA můžete nastavit pomocí odkazu na zobrazení ASP.NET Core Identity .

obrázek acr_values-1

Vynucení ASP.NET klienta Core OpenID Connect k vyžadování vícefaktorového ověřování

Tento příklad ukazuje, jak aplikace ASP.NET Core Razor Page, která k přihlášení používá OpenID Connect, může vyžadovat ověření uživatelů pomocí vícefaktorového ověřování.

K ověření požadavku IAuthorizationRequirement na vícefaktorové ověřování se vytvoří požadavek. Tato možnost se přidá na stránky pomocí zásady, která vyžaduje vícefaktorové ověřování.

using Microsoft.AspNetCore.Authorization;

namespace AspNetCoreRequireMfaOidc;

public class RequireMfa : IAuthorizationRequirement{}

Implementuje AuthorizationHandler se, která použije amr deklaraci identity a zkontroluje hodnotu mfa. Vrátí amr se v id_token úspěšném ověření a může mít mnoho různých hodnot definovaných ve specifikaci referenčních hodnot metody ověřování.

Vrácená hodnota závisí na tom, jak se identita ověřila, a na implementaci serveru OpenID Connect.

RequireMfa Použije AuthorizationHandler požadavek a ověří amr deklaraci identity. Server OpenID Connect lze implementovat pomocí duende Identity Serveru s ASP.NET Core Identity. Když se uživatel přihlásí pomocí toTP, amr deklarace identity se vrátí s hodnotou vícefaktorového ověřování. Pokud používáte jinou implementaci serveru OpenID Connect nebo jiný typ MFA, amr deklarace identity bude nebo může mít jinou hodnotu. Kód musí být rozšířen, aby ho také přijal.

public class RequireMfaHandler : AuthorizationHandler<RequireMfa>
{
	protected override Task HandleRequirementAsync(
		AuthorizationHandlerContext context, 
		RequireMfa requirement)
	{
		if (context == null)
			throw new ArgumentNullException(nameof(context));
		if (requirement == null)
			throw new ArgumentNullException(nameof(requirement));

		var amrClaim =
			context.User.Claims.FirstOrDefault(t => t.Type == "amr");

		if (amrClaim != null && amrClaim.Value == Amr.Mfa)
		{
			context.Succeed(requirement);
		}

		return Task.CompletedTask;
	}
}

V souboru programu se AddOpenIdConnect metoda používá jako výchozí schéma výzvy. Obslužná rutina autorizace, která se používá ke kontrole amr deklarace identity, se přidá do kontejneru Inversion of Control. Pak se vytvoří zásada, která požadavek přidá RequireMfa .

builder.Services.ConfigureApplicationCookie(options =>
        options.Cookie.SecurePolicy =
            CookieSecurePolicy.Always);

builder.Services.AddSingleton<IAuthorizationHandler, RequireMfaHandler>();

builder.Services.AddAuthentication(options =>
{
	options.DefaultScheme =
		CookieAuthenticationDefaults.AuthenticationScheme;
	options.DefaultChallengeScheme =
		OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
	options.SignInScheme =
		CookieAuthenticationDefaults.AuthenticationScheme;
	options.Authority = "https://localhost:44352";
	options.RequireHttpsMetadata = true;
	options.ClientId = "AspNetCoreRequireMfaOidc";
	options.ClientSecret = "AspNetCoreRequireMfaOidcSecret";
	options.ResponseType = "code";
	options.UsePkce = true;	
	options.Scope.Add("profile");
	options.Scope.Add("offline_access");
	options.SaveTokens = true;
});

builder.Services.AddAuthorization(options =>
{
	options.AddPolicy("RequireMfa", policyIsAdminRequirement =>
	{
		policyIsAdminRequirement.Requirements.Add(new RequireMfa());
	});
});

builder.Services.AddRazorPages();

Tato zásada se pak použije na Razor stránce podle potřeby. Zásady je možné přidat globálně i pro celou aplikaci.

[Authorize(Policy= "RequireMfa")]
public class IndexModel : PageModel
{
    public void OnGet()
    {
    }
}

Pokud se uživatel ověří bez vícefaktorového pwd ověřování, amr deklarace identity bude pravděpodobně mít hodnotu. Žádost nebude mít oprávnění pro přístup k této stránce. Pomocí výchozích hodnot se uživatel přesměruje na stránku Account/AccessDenied . Toto chování můžete změnit nebo můžete zde implementovat vlastní logiku. V tomto příkladu se přidá odkaz, aby platný uživatel mohl pro svůj účet nastavit vícefaktorové ověřování.

@page
@model AspNetCoreRequireMfaOidc.AccessDeniedModel
@{
    ViewData["Title"] = "AccessDenied";
    Layout = "~/Pages/Shared/_Layout.cshtml";
}

<h1>AccessDenied</h1>

You require MFA to login here

<a href="https://localhost:44352/Manage/TwoFactorAuthentication">Enable MFA</a>

Teď k stránce nebo webu mají přístup jenom uživatelé, kteří se ověřují pomocí vícefaktorového ověřování. Pokud se použijí různé typy vícefaktorového ověřování nebo pokud je 2FA v pořádku, amr deklarace identity bude mít různé hodnoty a musí se správně zpracovat. Různé servery OpenID Connect také vracejí různé hodnoty pro tuto deklaraci identity a nemusí dodržovat specifikaci referenčních hodnot metody ověřování.

Při přihlašování bez vícefaktorového ověřování (například pomocí hesla):

  • pwdamr hodnotu:

    Amr má hodnotu pwd.

  • Přístup byl odepřen:

    Přístup byl odepřen.

Další možností je přihlášení pomocí jednorázového hesla Identity:

Přihlášení pomocí jednorázového hesla s využitím Identity

Další materiály

Autor: Damien Bowden

Zobrazení nebo stažení ukázkového kódu (úložiště GitHub damienbod/AspNetCoreHybridFlowWithApi)

Vícefaktorové ověřování (MFA) je proces, při kterém se uživatel během přihlašovací události žádá o další formy identifikace. Tato výzva může být zadání kódu z mobilního telefonu, použití klíče FIDO2 nebo poskytnutí otisku prstu. Pokud potřebujete druhou formu ověřování, zabezpečení se zlepšuje. Další faktor není snadno získán nebo duplikován útočníkem.

Tento článek se zabývá následujícími oblastmi:

  • Co je vícefaktorové ověřování a jaké toky vícefaktorového ověřování se doporučují
  • Konfigurace vícefaktorového ověřování pro stránky správy pomocí ASP.NET Core Identity
  • Odeslání požadavku na přihlášení MFA na server OpenID Connect
  • Vynucení ASP.NET klienta Core OpenID Connect k vyžadování vícefaktorového ověřování

MFA, 2FA

Vícefaktorové ověřování vyžaduje alespoň dva nebo více typů ověření identity, jako je něco, co víte, něco, co máte, nebo biometrické ověření, aby se uživatel mohl ověřit.

Dvojúrovňové ověřování (2FA) je jako podmnožina vícefaktorového ověřování, ale rozdíl spočívá v tom, že vícefaktorové ověřování může vyžadovat dva nebo více faktorů k prokázání identity.

MFA TOTP (jednorázový algoritmus hesel založený na čase)

Vícefaktorové ověřování využívající TOTP je podporovaná implementace pomocí ASP.NET Core Identity. Můžete ho použít společně s libovolnou vyhovující ověřovací aplikací, včetně:

  • Aplikace Microsoft Authenticator
  • Aplikace Google Authenticator

Podrobnosti o implementaci najdete na následujícím odkazu:

Povolení generování QR kódu pro ověřovací aplikace TOTP v ASP.NET Core

Klíče vícefaktorového ověřování / FIDO2 nebo bez hesla

klíč/FIDO2 je aktuálně:

  • Nejbezpečnější způsob dosažení vícefaktorového ověřování.
  • Vícefaktorové ověřování, které chrání před útoky phishing. (stejně jako ověřování certifikátů a Windows pro firmy)

V současné době ASP.NET Core nepodporuje přímo klíče nebo FIDO2. Přístupové klíče/FIDO2 se dají použít pro MFA nebo bez hesla.

Microsoft Entra ID poskytuje podporu pro přístupové klíče/FIDO2 a toky bez hesel. Další informace najdete v tématu Možnosti ověřování bez hesla.

Jiné formy vícefaktorového ověřování bez hesla se nedají chránit před útoky phishing.

MFA SMS

Vícefaktorové ověřování se službou SMS výrazně zvyšuje zabezpečení v porovnání s ověřováním heslem (jednofaktorové ověřování). Použití sms jako druhého faktoru se ale už nedoporučuje. Pro tento typ implementace existuje příliš mnoho známých vektorů útoku.

Pokyny pro NIST

Konfigurace vícefaktorového ověřování pro stránky správy pomocí ASP.NET Core Identity

Vícefaktorové ověřování může být vynuceno, aby uživatelé měli přístup k citlivým stránkám v aplikaci ASP.NET Core Identity . To může být užitečné pro aplikace, ve kterých existují různé úrovně přístupu pro různé identity. Uživatelé můžou například zobrazit data profilu pomocí přihlášení pomocí hesla, ale správce bude muset pro přístup ke stránkám pro správu použít vícefaktorové ověřování.

Rozšíření přihlášení pomocí deklarace vícefaktorového ověřování

Ukázkový kód je nastaven pomocí ASP.NET Core s Identity a Razor Pages. Metoda AddIdentity se používá místo AddDefaultIdentity jedné, takže IUserClaimsPrincipalFactory implementaci lze použít k přidání deklarací identity do identity po úspěšném přihlášení.

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlite(
            Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<IdentityUser, IdentityRole>(
            options => options.SignIn.RequireConfirmedAccount = false)
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.AddSingleton<IEmailSender, EmailSender>();
    services.AddScoped<IUserClaimsPrincipalFactory<IdentityUser>, 
        AdditionalUserClaimsPrincipalFactory>();

    services.AddAuthorization(options =>
        options.AddPolicy("TwoFactorEnabled",
            x => x.RequireClaim("amr", "mfa")));

    services.AddRazorPages();
}

Třída AdditionalUserClaimsPrincipalFactory přidá amr deklaraci identity do deklarací identity uživatele až po úspěšném přihlášení. Hodnota deklarace identity se načítá z databáze. Deklarace identity se tady přidá, protože uživatel by měl přistupovat pouze k vyššímu chráněnému zobrazení, pokud se identita přihlásila pomocí vícefaktorového ověřování. Pokud se zobrazení databáze načítá přímo z databáze místo deklarace identity, je možné k zobrazení přistupovat bez vícefaktorového ověřování přímo po aktivaci vícefaktorového ověřování.

using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;

namespace IdentityStandaloneMfa
{
    public class AdditionalUserClaimsPrincipalFactory : 
        UserClaimsPrincipalFactory<IdentityUser, IdentityRole>
    {
        public AdditionalUserClaimsPrincipalFactory( 
            UserManager<IdentityUser> userManager,
            RoleManager<IdentityRole> roleManager, 
            IOptions<IdentityOptions> optionsAccessor) 
            : base(userManager, roleManager, optionsAccessor)
        {
        }

        public async override Task<ClaimsPrincipal> CreateAsync(IdentityUser user)
        {
            var principal = await base.CreateAsync(user);
            var identity = (ClaimsIdentity)principal.Identity;

            var claims = new List<Claim>();

            if (user.TwoFactorEnabled)
            {
                claims.Add(new Claim("amr", "mfa"));
            }
            else
            {
                claims.Add(new Claim("amr", "pwd"));
            }

            identity.AddClaims(claims);
            return principal;
        }
    }
}

Vzhledem k tomu, že Identity se nastavení služby změnilo ve Startup třídě, musí být aktualizována Identity rozložení. Vygenerujte Identity stránky do aplikace. Definujte rozložení v Identity/Account/Manage/_Layout.cshtml souboru.

@{
    Layout = "/Pages/Shared/_Layout.cshtml";
}

Také přiřaďte rozložení pro všechny stránky pro správu ze Identity stránek:

@{
    Layout = "_Layout.cshtml";
}

Ověření požadavku vícefaktorového ověřování na stránce správy

Stránka pro správu Razor ověří, že se uživatel přihlásil pomocí vícefaktorového ověřování. OnGet V metodě se identita používá pro přístup k deklarace identity uživatele. Deklarace amr identity je zkontrolována pro hodnotu mfa. Pokud identitě chybí tato deklarace identity nebo je false, stránka se přesměruje na stránku Povolit vícefaktorové ověřování. To je možné, protože uživatel se už přihlásil, ale bez vícefaktorového ověřování.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace IdentityStandaloneMfa
{
    public class AdminModel : PageModel
    {
        public IActionResult OnGet()
        {
            var claimTwoFactorEnabled = 
                User.Claims.FirstOrDefault(t => t.Type == "amr");

            if (claimTwoFactorEnabled != null && 
                "mfa".Equals(claimTwoFactorEnabled.Value))
            {
                // You logged in with MFA, do the administrative stuff
            }
            else
            {
                return Redirect(
                    "/Identity/Account/Manage/TwoFactorAuthentication");
            }

            return Page();
        }
    }
}

Logika uživatelského rozhraní pro přepínání přihlašovacích údajů uživatele

Do souboru programu byla přidána zásada autorizace. Zásada vyžaduje amr deklaraci identity s hodnotou mfa.

builder.Services.AddAuthorization(options =>
    options.AddPolicy("TwoFactorEnabled",
        x => x.RequireClaim("amr", "mfa")));

Tuto zásadu _Layout pak můžete použít v zobrazení k zobrazení nebo skrytí nabídky Správce s upozorněním:

@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager
@inject IAuthorizationService AuthorizationService

Pokud se identita přihlásila pomocí vícefaktorového ověřování, zobrazí se nabídka Správce bez upozornění na popis. Když se uživatel přihlásí bez vícefaktorového ověřování, zobrazí se nabídka Správce (nepovoleno) spolu s popisem, který uživatele informuje (vysvětluje upozornění).

@if (SignInManager.IsSignedIn(User))
{
    @if ((AuthorizationService.AuthorizeAsync(User, "TwoFactorEnabled")).Result.Succeeded)
    {
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="" asp-page="/Admin">Admin</a>
        </li>
    }
    else
    {
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="" asp-page="/Admin" 
               id="tooltip-demo"  
               data-toggle="tooltip" 
               data-placement="bottom" 
               title="MFA is NOT enabled. This is required for the Admin Page. If you have activated MFA, then logout, login again.">
                Admin (Not Enabled)
            </a>
        </li>
    }
}

Pokud se uživatel přihlásí bez vícefaktorového ověřování, zobrazí se upozornění:

Ověřování vícefaktorového ověřování správce

Uživatel se přesměruje do zobrazení povolení vícefaktorového ověřování po kliknutí na odkaz Správce :

Správce aktivuje vícefaktorové ověřování.

Odeslání požadavku na přihlášení MFA na server OpenID Connect

Parametr acr_values lze použít k předání mfa požadované hodnoty z klienta na server v žádosti o ověření.

Poznámka:

Aby acr_values to fungovalo, musí být parametr zpracován na serveru OpenID Connect.

Klient OpenID Connect ASP.NET Core

Klientská aplikace ASP.NET Core Razor Pages OpenID Connect používá metodu AddOpenIdConnect pro přihlášení k serveru OpenID Connect. Parametr acr_values se nastaví s mfa hodnotou a odešle se s žádostí o ověření. Slouží OpenIdConnectEvents k přidání.

acr_values Doporučené hodnoty parametrů najdete v tématu Referenční hodnoty metody ověřování.

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(options =>
    {
        options.DefaultScheme =
            CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme =
            OpenIdConnectDefaults.AuthenticationScheme;
    })
    .AddCookie()
    .AddOpenIdConnect(options =>
    {
        options.SignInScheme =
            CookieAuthenticationDefaults.AuthenticationScheme;
        options.Authority = "<OpenID Connect server URL>";
        options.RequireHttpsMetadata = true;
        options.ClientId = "<OpenID Connect client ID>";
        options.ClientSecret = "<>";
        options.ResponseType = "code";
        options.UsePkce = true;	
        options.Scope.Add("profile");
        options.Scope.Add("offline_access");
        options.SaveTokens = true;
        options.Events = new OpenIdConnectEvents
        {
            OnRedirectToIdentityProvider = context =>
            {
                context.ProtocolMessage.SetParameter("acr_values", "mfa");
                return Task.FromResult(0);
            }
        };
    });

Příklad serveru OpenID Connect IdentityServer 4 s ASP.NET Core Identity

Na serveru OpenID Connect, který se implementuje pomocí ASP.NET Core Identity se zobrazeními MVC, se vytvoří nové pojmenované ErrorEnable2FA.cshtml zobrazení. Zobrazení:

  • Zobrazí, jestli Identity pochází z aplikace, která vyžaduje vícefaktorové ověřování, ale uživatel ho Identityneaktivoval.
  • Informuje uživatele a přidá odkaz k aktivaci.
@{
    ViewData["Title"] = "ErrorEnable2FA";
}

<h1>The client application requires you to have MFA enabled. Enable this, try login again.</h1>

<br />

You can enable MFA to login here:

<br />

<a asp-controller="Manage" asp-action="TwoFactorAuthentication">Enable MFA</a>

Login V metodě se IIdentityServerInteractionService implementace _interaction rozhraní používá pro přístup k parametrům požadavku OpenID Connect. K acr_values parametru AcrValues se přistupuje pomocí vlastnosti. Když klient odeslal tuto mfa sadu, můžete to zkontrolovat.

Pokud se vyžaduje vícefaktorové ověřování a uživatel v ASP.NET Core Identity má povolené vícefaktorové ověřování, přihlášení bude pokračovat. Pokud uživatel nemá povolené vícefaktorové ověřování, uživatel se přesměruje do vlastního zobrazení ErrorEnable2FA.cshtml. Pak ASP.NET Core Identity uživatele přihlásí.

//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginInputModel model)
{
    var returnUrl = model.ReturnUrl;
    var context = 
        await _interaction.GetAuthorizationContextAsync(returnUrl);
    var requires2Fa = 
        context?.AcrValues.Count(t => t.Contains("mfa")) >= 1;

    var user = await _userManager.FindByNameAsync(model.Email);
    if (user != null && !user.TwoFactorEnabled && requires2Fa)
    {
        return RedirectToAction(nameof(ErrorEnable2FA));
    }

    // code omitted for brevity

Metoda ExternalLoginCallback funguje jako místní Identity přihlášení. Vlastnost AcrValues je zkontrolována pro mfa hodnotu. Pokud je hodnota mfa k dispozici, vícefaktorové ověřování je vynucené před dokončením přihlášení (například přesměrováno do ErrorEnable2FA zobrazení).

//
// GET: /Account/ExternalLoginCallback
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(
    string returnUrl = null,
    string remoteError = null)
{
    var context =
        await _interaction.GetAuthorizationContextAsync(returnUrl);
    var requires2Fa =
        context?.AcrValues.Count(t => t.Contains("mfa")) >= 1;

    if (remoteError != null)
    {
        ModelState.AddModelError(
            string.Empty,
            _sharedLocalizer["EXTERNAL_PROVIDER_ERROR", 
            remoteError]);
        return View(nameof(Login));
    }
    var info = await _signInManager.GetExternalLoginInfoAsync();

    if (info == null)
    {
        return RedirectToAction(nameof(Login));
    }

    var email = info.Principal.FindFirstValue(ClaimTypes.Email);

    if (!string.IsNullOrEmpty(email))
    {
        var user = await _userManager.FindByNameAsync(email);
        if (user != null && !user.TwoFactorEnabled && requires2Fa)
        {
            return RedirectToAction(nameof(ErrorEnable2FA));
        }
    }

    // Sign in the user with this external login provider if the user already has a login.
    var result = await _signInManager
        .ExternalLoginSignInAsync(
            info.LoginProvider, 
            info.ProviderKey, 
            isPersistent: 
            false);

    // code omitted for brevity

Pokud už je uživatel přihlášený, klientská aplikace:

  • Stále ověří amr deklaraci identity.
  • MFA můžete nastavit pomocí odkazu na zobrazení ASP.NET Core Identity .

obrázek acr_values-1

Vynucení ASP.NET klienta Core OpenID Connect k vyžadování vícefaktorového ověřování

Tento příklad ukazuje, jak aplikace ASP.NET Core Razor Page, která k přihlášení používá OpenID Connect, může vyžadovat ověření uživatelů pomocí vícefaktorového ověřování.

K ověření požadavku IAuthorizationRequirement na vícefaktorové ověřování se vytvoří požadavek. Tato možnost se přidá na stránky pomocí zásady, která vyžaduje vícefaktorové ověřování.

using Microsoft.AspNetCore.Authorization;

namespace AspNetCoreRequireMfaOidc
{
    public class RequireMfa : IAuthorizationRequirement{}
}

Implementuje AuthorizationHandler se, která použije amr deklaraci identity a zkontroluje hodnotu mfa. Vrátí amr se v id_token úspěšném ověření a může mít mnoho různých hodnot definovaných ve specifikaci referenčních hodnot metody ověřování.

Vrácená hodnota závisí na tom, jak se identita ověřila, a na implementaci serveru OpenID Connect.

RequireMfa Použije AuthorizationHandler požadavek a ověří amr deklaraci identity. Server OpenID Connect lze implementovat pomocí Identityserveru Server4 s ASP.NET Core Identity. Když se uživatel přihlásí pomocí toTP, amr deklarace identity se vrátí s hodnotou vícefaktorového ověřování. Pokud používáte jinou implementaci serveru OpenID Connect nebo jiný typ MFA, amr deklarace identity bude nebo může mít jinou hodnotu. Kód musí být rozšířen, aby ho také přijal.

public class RequireMfaHandler : AuthorizationHandler<RequireMfa>
{
	protected override Task HandleRequirementAsync(
		AuthorizationHandlerContext context, 
		RequireMfa requirement)
	{
		if (context == null)
			throw new ArgumentNullException(nameof(context));
		if (requirement == null)
			throw new ArgumentNullException(nameof(requirement));

		var amrClaim =
			context.User.Claims.FirstOrDefault(t => t.Type == "amr");

		if (amrClaim != null && amrClaim.Value == Amr.Mfa)
		{
			context.Succeed(requirement);
		}

		return Task.CompletedTask;
	}
}

Startup.ConfigureServices V metodě se AddOpenIdConnect metoda používá jako výchozí schéma výzvy. Obslužná rutina autorizace, která se používá ke kontrole amr deklarace identity, se přidá do kontejneru Inversion of Control. Pak se vytvoří zásada, která požadavek přidá RequireMfa .

public void ConfigureServices(IServiceCollection services)
{
    services.ConfigureApplicationCookie(options =>
        options.Cookie.SecurePolicy =
            CookieSecurePolicy.Always);

    services.AddSingleton<IAuthorizationHandler, RequireMfaHandler>();

    services.AddAuthentication(options =>
    {
        options.DefaultScheme =
            CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme =
            OpenIdConnectDefaults.AuthenticationScheme;
    })
    .AddCookie()
    .AddOpenIdConnect(options =>
    {
        options.SignInScheme =
            CookieAuthenticationDefaults.AuthenticationScheme;
        options.Authority = "https://localhost:44352";
        options.RequireHttpsMetadata = true;
        options.ClientId = "AspNetCoreRequireMfaOidc";
        options.ClientSecret = "AspNetCoreRequireMfaOidcSecret";
        options.ResponseType = "code";
        options.UsePkce = true;	
        options.Scope.Add("profile");
        options.Scope.Add("offline_access");
        options.SaveTokens = true;
    });

    services.AddAuthorization(options =>
    {
        options.AddPolicy("RequireMfa", policyIsAdminRequirement =>
        {
            policyIsAdminRequirement.Requirements.Add(new RequireMfa());
        });
    });

    services.AddRazorPages();
}

Tato zásada se pak použije na Razor stránce podle potřeby. Zásady je možné přidat globálně i pro celou aplikaci.

[Authorize(Policy= "RequireMfa")]
public class IndexModel : PageModel
{
    public void OnGet()
    {
    }
}

Pokud se uživatel ověří bez vícefaktorového pwd ověřování, amr deklarace identity bude pravděpodobně mít hodnotu. Žádost nebude mít oprávnění pro přístup k této stránce. Pomocí výchozích hodnot se uživatel přesměruje na stránku Account/AccessDenied . Toto chování můžete změnit nebo můžete zde implementovat vlastní logiku. V tomto příkladu se přidá odkaz, aby platný uživatel mohl pro svůj účet nastavit vícefaktorové ověřování.

@page
@model AspNetCoreRequireMfaOidc.AccessDeniedModel
@{
    ViewData["Title"] = "AccessDenied";
    Layout = "~/Pages/Shared/_Layout.cshtml";
}

<h1>AccessDenied</h1>

You require MFA to login here

<a href="https://localhost:44352/Manage/TwoFactorAuthentication">Enable MFA</a>

Teď k stránce nebo webu mají přístup jenom uživatelé, kteří se ověřují pomocí vícefaktorového ověřování. Pokud se použijí různé typy vícefaktorového ověřování nebo pokud je 2FA v pořádku, amr deklarace identity bude mít různé hodnoty a musí se správně zpracovat. Různé servery OpenID Connect také vracejí různé hodnoty pro tuto deklaraci identity a nemusí dodržovat specifikaci referenčních hodnot metody ověřování.

Při přihlašování bez vícefaktorového ověřování (například pomocí hesla):

  • pwdamr hodnotu:

    Amr má hodnotu pwd.

  • Přístup byl odepřen:

    Přístup byl odepřen.

Další možností je přihlášení pomocí jednorázového hesla Identity:

Přihlášení pomocí jednorázového hesla s využitím Identity

Další materiály