Vícefaktorové ověřování v ASP.NET Core
Poznámka:
Toto není nejnovější verze tohoto článku. Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Upozorňující
Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v zásadách podpory .NET a .NET Core. Aktuální verzi najdete v tomto článku ve verzi .NET 9.
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 v tomto článku ve verzi .NET 9.
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 ani duplikován cyberattackerem.
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ů důkazů pro něco identity , co víte, něco, co máte, nebo biometrické ověření, aby se uživatel mohl ověřit.
Dvoufaktorové 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.
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 po identity úspěšném přihlášení.
Upozorňující
Tento článek ukazuje použití připojovací řetězec. U místní databáze nemusí být uživatel ověřený, ale v produkčním prostředí připojovací řetězec někdy obsahují heslo k ověření. Přihlašovací údaje vlastníka prostředku (ROPC) jsou bezpečnostní riziko, kterému byste se měli vyhnout v produkčních databázích. Produkční aplikace by měly používat nejbezpečnější dostupný tok ověřování. Další informace o ověřování pro aplikace nasazené do testovacího nebo produkčního prostředí najdete v tématu Zabezpečené toky ověřování.
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 sem přidá, protože uživatel by měl přistupovat pouze k vyššímu chráněnému zobrazení, pokud identity se přihlásil 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ě identity se používá pro přístup k deklarace identity uživatele. Deklarace amr
identity je zkontrolována pro hodnotu mfa
. identity Pokud tato deklarace identity chybí nebo jefalse
, 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
identity Pokud se uživatel přihlásil 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í:
Uživatel se přesměruje do zobrazení povolení vícefaktorového ověřování po kliknutí na odkaz Správce :
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 IdentityServer s 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 .
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 identity ověřená 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):
pwd
Máamr
hodnotu:Přístup byl odepřen:
Další možností je přihlášení pomocí jednorázového hesla Identity:
Přizpůsobení parametrů OIDC a OAuth
Možnost obslužných AdditionalAuthorizationParameters
rutin ověřování OAuth a OIDC umožňuje přizpůsobení parametrů autorizační zprávy, které jsou obvykle součástí řetězce dotazu přesměrování:
builder.Services.AddAuthentication().AddOpenIdConnect(options =>
{
options.AdditionalAuthorizationParameters.Add("prompt", "login");
options.AdditionalAuthorizationParameters.Add("audience", "https://api.example.com");
});
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 ani duplikován cyberattackerem.
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ů důkazů pro něco identity , co víte, něco, co máte, nebo biometrické ověření, aby se uživatel mohl ověřit.
Dvoufaktorové 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.
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 po identity úspěšném přihlášení.
Upozorňující
Tento článek ukazuje použití připojovací řetězec. U místní databáze nemusí být uživatel ověřený, ale v produkčním prostředí připojovací řetězec někdy obsahují heslo k ověření. Přihlašovací údaje vlastníka prostředku (ROPC) jsou bezpečnostní riziko, kterému byste se měli vyhnout v produkčních databázích. Produkční aplikace by měly používat nejbezpečnější dostupný tok ověřování. Další informace o ověřování pro aplikace nasazené do testovacího nebo produkčního prostředí najdete v tématu Zabezpečené toky ověřování.
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 sem přidá, protože uživatel by měl přistupovat pouze k vyššímu chráněnému zobrazení, pokud identity se přihlásil 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ě identity se používá pro přístup k deklarace identity uživatele. Deklarace amr
identity je zkontrolována pro hodnotu mfa
. identity Pokud tato deklarace identity chybí nebo jefalse
, 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
identity Pokud se uživatel přihlásil 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í:
Uživatel se přesměruje do zobrazení povolení vícefaktorového ověřování po kliknutí na odkaz Správce :
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 IdentityServer s 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 .
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 identity ověřená 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):
pwd
Máamr
hodnotu:Přístup byl odepřen:
Další možností je přihlášení pomocí jednorázového hesla 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 ani duplikován cyberattackerem.
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ů důkazů pro něco identity , co víte, něco, co máte, nebo biometrické ověření, aby se uživatel mohl ověřit.
Dvoufaktorové 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.
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 po identity úspěšném přihlášení.
Upozorňující
Tento článek ukazuje použití připojovací řetězec. U místní databáze nemusí být uživatel ověřený, ale v produkčním prostředí připojovací řetězec někdy obsahují heslo k ověření. Přihlašovací údaje vlastníka prostředku (ROPC) jsou bezpečnostní riziko, kterému byste se měli vyhnout v produkčních databázích. Produkční aplikace by měly používat nejbezpečnější dostupný tok ověřování. Další informace o ověřování pro aplikace nasazené do testovacího nebo produkčního prostředí najdete v tématu Zabezpečené toky ověřování.
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 sem přidá, protože uživatel by měl přistupovat pouze k vyššímu chráněnému zobrazení, pokud identity se přihlásil 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ě identity se používá pro přístup k deklarace identity uživatele. Deklarace amr
identity je zkontrolována pro hodnotu mfa
. identity Pokud tato deklarace identity chybí nebo jefalse
, 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
identity Pokud se uživatel přihlásil 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í:
Uživatel se přesměruje do zobrazení povolení vícefaktorového ověřování po kliknutí na odkaz Správce :
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 .
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 identity ověřená a na implementaci serveru OpenID Connect.
RequireMfa
Použije AuthorizationHandler
požadavek a ověří amr
deklaraci identity. Server OpenID Connect lze implementovat pomocí IdentityServer4 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):
pwd
Máamr
hodnotu:Přístup byl odepřen:
Další možností je přihlášení pomocí jednorázového hesla Identity: