Sdílet prostřednictvím


Jak použít Identity k zabezpečení backendu API pro jednostránkové aplikace

Poznámka:

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

Varování

Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v zásadách podpory .NET a .NET Core. Aktuální verzi tohoto článku najdete 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 tohoto článku najdete ve verzi .NET 9.

ASP.NET Core Identity poskytuje rozhraní API, která zpracovávají ověřování, autorizaci a správu identit. Rozhraní API umožňují zabezpečit koncové body back-end webového rozhraní API pomocí ověřování na základě cookie. Možnost založená na tokenech je dostupná pro klienty, kteří nemůžou používat soubory cookie, ale za zajištění zabezpečení tokenů zodpovídáte. Doporučujeme používat soubory cookie pro aplikace založené na prohlížeči, protože ve výchozím nastavení je prohlížeč automaticky zpracovává, aniž by je zpřístupňuje JavaScriptu.

Tento článek ukazuje, jak pomocí Identity zabezpečit backend webového rozhraní API pro jednostránkové aplikace (SPA), jako jsou aplikace Angular, React a Vue. Stejná back-endová rozhraní API je možné použít k zabezpečení Blazor WebAssembly aplikací.

Požadavky

Kroky uvedené v tomto článku přidávají ověřování a autorizaci do aplikace ASP.NET Core Web API, která:

  • Není nakonfigurovaná pro ověřování.
  • Cíle net8.0 nebo novější.
  • Může to být buď minimální rozhraní API, nebo rozhraní API založené na kontroleru.

Některé pokyny k testování v tomto článku používají uživatelské rozhraní Swagger, které je součástí šablony projektu. Uživatelské rozhraní Swagger není nutné pro použití Identity se zázemím webového rozhraní API.

Instalace balíčků NuGet

Nainstalujte následující balíčky NuGet:

Pro nejrychlejší způsob, jak začít, použijte databázi v paměti.

Později změňte databázi na SQLite nebo SQL Server, aby se při testování nebo použití v produkčním prostředí uložila uživatelská data mezi relacemi. To představuje určitou složitost v porovnání s pamětí, protože vyžaduje vytvoření databáze prostřednictvím migrací, jak je znázorněno v úvodním EF Core kurzu.

Nainstalujte tyto balíčky pomocí správce balíčků NuGet v sadě Visual Studio nebo příkazu dotnet add package CLI.

Vytvořte IdentityDbContext

Přidejte třídu s názvem ApplicationDbContext , která dědí z IdentityDbContext<TUser>:

using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;

public class ApplicationDbContext : IdentityDbContext<IdentityUser>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) :
        base(options)
    { }
}

Zobrazený kód poskytuje speciální konstruktor, který umožňuje konfigurovat databázi pro různá prostředí.

Při přidávání kódu uvedeného v tomto postupu přidejte jednu nebo více následujících using direktiv podle potřeby.

using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

Konfigurujte EF Core kontext

Jak už jsme uvedli dříve, nejjednodušší způsob, jak začít, je použít databázi v paměti. Při použití databáze v paměti každé spuštění začíná s čistou databází, a není nutné používat migrace. Po volání WebApplication.CreateBuilder(args)přidejte následující kód, který nakonfiguruje Identity použití databáze v paměti:

builder.Services.AddDbContext<ApplicationDbContext>(
    options => options.UseInMemoryDatabase("AppDb"));

Pokud chcete uložit uživatelská data mezi relacemi při testování nebo použití v produkčním prostředí, změňte databázi později na SQLite nebo SQL Server.

Přidání Identity služeb do kontejneru

Po zavolání WebApplication.CreateBuilder(args) použijte AddAuthorization pro přidání služeb do kontejneru pro vkládání závislostí (DI):

builder.Services.AddAuthorization();

Aktivace Identity rozhraní API

Po volání WebApplication.CreateBuilder(args) volejte AddIdentityApiEndpoints<TUser>(IServiceCollection) a AddEntityFrameworkStores<TContext>(IdentityBuilder).

builder.Services.AddIdentityApiEndpoints<IdentityUser>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

Ve výchozím nastavení se aktivují soubory cookie i proprietární tokeny. Soubory cookie a tokeny se vydávají při přihlášení, pokud je parametr řetězce dotazu useCookies v koncovém bodu přihlášení true.

Mapování Identity tras

Po volání builder.Build() volejte MapIdentityApi<TUser>(IEndpointRouteBuilder) a namapujte koncové body Identity.

app.MapIdentityApi<IdentityUser>();

Zabezpečení vybraných koncových bodů

K zabezpečení koncového bodu použijte metodu rozšíření RequireAuthorization na volání Map{Method}, které definuje trasu. Příklad:

app.MapGet("/weatherforecast", (HttpContext httpContext) =>
{
    var forecast = Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        {
            Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = summaries[Random.Shared.Next(summaries.Length)]
        })
        .ToArray();
    return forecast;
})
.WithName("GetWeatherForecast")
.WithOpenApi()
.RequireAuthorization();

Metodu RequireAuthorization lze použít také k:

  • Zabezpečení koncových bodů uživatelského rozhraní Swagger, jak je znázorněno v následujícím příkladu:

    app.MapSwagger().RequireAuthorization();
    
  • Zabezpečení pomocí konkrétního nároku nebo oprávnění, jak je znázorněno v následujícím příkladu:

    .RequireAuthorization("Admin");
    

V projektu webového rozhraní API založeném na kontroleru zabezpečte koncové body použitím atributu [Authorize] na kontroler nebo akci.

Testování rozhraní API

Rychlý způsob, jak otestovat ověřování, je použít databázi v paměti a uživatelské rozhraní Swagger, které je součástí šablony projektu. Následující kroky ukazují, jak otestovat rozhraní API pomocí uživatelského rozhraní Swagger. Ujistěte se, že koncové body uživatelského rozhraní Swagger nejsou zabezpečené.

Pokus o přístup k zabezpečenému koncovému bodu

  • Spusťte aplikaci a přejděte do uživatelského rozhraní Swaggeru.
  • Rozšiřte zabezpečený koncový bod, například /weatherforecast v projektu vytvořeném pomocí šablony webového rozhraní API.
  • Vyberte Vyzkoušet.
  • Vyberte Provést. Odpověď je 401 - not authorized.

Test registrace

  • Rozbalte /register a vyberte Vyzkoušet.

  • V části Parametry uživatelského rozhraní se zobrazí text ukázkového požadavku:

    {
      "email": "string",
      "password": "string"
    }
    
  • Nahraďte "string" platnou e-mailovou adresou a heslem, poté zvolte Spustit.

    Aby bylo možné dodržovat výchozí ověřovací pravidla hesla, musí mít heslo alespoň šest znaků a musí obsahovat alespoň jeden z následujících znaků:

    • Velké písmeno
    • Malá písmena
    • Číselná číslice
    • Nealfanumerický znak

    Pokud zadáte neplatnou e-mailovou adresu nebo chybné heslo, výsledek bude obsahovat chyby ověření. Tady je příklad textu odpovědi s chybami ověření:

    {
      "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
      "title": "One or more validation errors occurred.",
      "status": 400,
      "errors": {
        "PasswordTooShort": [
          "Passwords must be at least 6 characters."
        ],
        "PasswordRequiresNonAlphanumeric": [
          "Passwords must have at least one non alphanumeric character."
        ],
        "PasswordRequiresDigit": [
          "Passwords must have at least one digit ('0'-'9')."
        ],
        "PasswordRequiresLower": [
          "Passwords must have at least one lowercase ('a'-'z')."
        ]
      }
    }
    

    Chyby se vrátí ve formátu ProblemDetails , aby je klient mohl parsovat a zobrazovat chyby ověření podle potřeby.

    Výsledkem úspěšné registrace je odpověď 200 - OK.

Testovací přihlášení

  • Rozbalte /login a vyberte Vyzkoušet. Příklad textu požadavku ukazuje dva další parametry:

    {
      "email": "string",
      "password": "string",
      "twoFactorCode": "string",
      "twoFactorRecoveryCode": "string"
    }
    

    V tomto příkladu nejsou potřeba další vlastnosti JSON a je možné je odstranit. Nastavte useCookies na hodnotu true.

  • Nahraďte řetězec e-mailovou adresou a heslem, které jste použili k registraci, a pak vyberte Spustit.

    Úspěšné přihlášení má za následek 200 - OK odpověď s cookie v hlavičce odpovědi.

Opětovné otestování zabezpečeného koncového bodu

Po úspěšném přihlášení spusťte zabezpečený koncový bod znovu. cookie Ověřování se automaticky odešle s požadavkem a koncový bod je autorizovaný. CookieOvěřování založené na je bezpečně integrované v prohlížeči a funguje bez problémů.

Testování s neprohlížečovými klienty

Někteří weboví klienti nemusí ve výchozím nastavení do hlavičky zahrnout soubory cookie:

  • Pokud používáte nástroj pro testování rozhraní API, možná budete muset v nastavení povolit soubory cookie.

  • Rozhraní JAVAScript fetch API ve výchozím nastavení neobsahuje soubory cookie. Povolte je nastavením credentials na hodnotu include v možnostech.

  • Provozování HttpClient v aplikaci Blazor WebAssembly potřebuje, aby HttpRequestMessage obsahoval přihlašovací údaje, jako v následujícím příkladu:

    request.SetBrowserRequestCredential(BrowserRequestCredentials.Include);
    

Použití ověřování na základě tokenů

Doporučujeme používat soubory cookie v aplikacích založených na prohlížeči, protože ve výchozím nastavení je prohlížeč automaticky zpracovává, aniž by je zpřístupňuje JavaScriptu.

Vystavil se vlastní token (který je proprietární pro platformu identit ASP.NET Core), který se dá použít k ověřování následných požadavků. Token se předá v hlavičce Authorization jako nosný token. K dispozici je také obnovovací token. Tento token umožňuje aplikaci požádat o nový token, když vyprší platnost starého tokenu, aniž by ho vynutíte, aby se znovu přihlásil.

Tokeny nejsou standardní webové tokeny JSON (JWT). Použití vlastních tokenů je záměrné, protože integrované Identity rozhraní API je určené především pro jednoduché scénáře. Možnost tokenu není určená jako plnohodnotný zprostředkovatel služby identity nebo server tokenů, ale alternativou k možnosti cookie pro klienty, kteří nemůžou používat soubory cookie.

Pokud chcete použít ověřování na základě tokenu, nastavte useCookies parametr řetězce dotazu na false při volání koncového /login bodu. Tokeny používají schéma ověřování typu bearer. Při použití tokenu, který je vrácen z volání /login, by následná volání chráněných koncových bodů měla přidat hlavičku Authorization: Bearer <token>, kde <token> je přístupový token. Další informace najdete v části Použití koncového POST /login bodu dále v tomto článku.

Odhlásit se

Pokud chcete uživateli poskytnout způsob, jak se odhlásit, definujte /logout koncový bod jako v následujícím příkladu:

app.MapPost("/logout", async (SignInManager<IdentityUser> signInManager,
    [FromBody] object empty) =>
{
    if (empty != null)
    {
        await signInManager.SignOutAsync();
        return Results.Ok();
    }
    return Results.Unauthorized();
})
.WithOpenApi()
.RequireAuthorization();

Při volání tohoto koncového bodu zadejte prázdný objekt JSON ({}) v textu požadavku. Následující kód je příkladem volání koncového bodu odhlášení:

public signOut() {
  return this.http.post('/logout', {}, {
    withCredentials: true,
    observe: 'response',
    responseType: 'text'

Koncové MapIdentityApi<TUser> body

Volání k MapIdentityApi<TUser> přidání následujících koncových bodů do aplikace:

Použijte POST /register koncový bod

Text požadavku musí mít Email a Password vlastnosti:

{
  "email": "string",
  "password": "string",
}

Další informace naleznete v tématu:

Použijte POST /login koncový bod

V těle požadavku jsou Email a Password povinné. Pokud je povolené dvojúrovňové ověřování (2FA), buď TwoFactorCode nebo TwoFactorRecoveryCode je povinné. Pokud 2FA není povolená, vynecháte obojí twoFactorCode i twoFactorRecoveryCode. Další informace najdete v části Použití koncového POST /manage/2fa bodu dále v tomto článku.

Tady je příklad textu požadavku s nepovoleným 2FA:

{
  "email": "string",
  "password": "string"
}

Tady jsou příklady textu požadavku s povoleným 2FA:

  • {
      "email": "string",
      "password": "string",
      "twoFactorCode": "string",
    }
    
  • {
      "email": "string",
      "password": "string",
      "twoFactorRecoveryCode": "string"
    }
    

Koncový bod očekává parametr řetězce dotazu:

  • useCookies – Nastavte na true pro ověřování na základě cookie. Nastavte na false nebo vynechejte pro ověřování na základě tokenu.

Další informace o cookieověřování naleznete v části Test přihlášení dříve v tomto článku.

Ověřování na základě tokenů

Pokud je useCookies nebo false vynecháno, je povolené ověřování na základě tokenu. Text odpovědi obsahuje následující vlastnosti:

{
  "tokenType": "string",
  "accessToken": "string",
  "expiresIn": 0,
  "refreshToken": "string"
}

Další informace o těchto vlastnostech naleznete v tématu AccessTokenResponse.

Vložte přístupový token do hlavičky pro provedení ověřených požadavků, jak je znázorněno v následujícím příkladu.

Authorization: Bearer {access token}

Když má přístupový token brzy vypršet, zavolejte na koncový bod /refresh.

Použijte POST /refresh koncový bod

Pro použití pouze s ověřováním na základě tokenu. Získá nový přístupový token bez vynucení opětovného přihlášení uživatele. Zavolejte tento koncový bod, když se platnost přístupového tokenu chýlí ke konci.

Text požadavku obsahuje pouze RefreshToken. Tady je příklad textu požadavku:

{
  "refreshToken": "string"
}

Pokud je volání úspěšné, text odpovědi je nový AccessTokenResponse, jak je znázorněno v následujícím příkladu:

{
  "tokenType": "string",
  "accessToken": "string",
  "expiresIn": 0,
  "refreshToken": "string"
}

Použijte GET /confirmEmail koncový bod

Pokud je Identity nastaveno pro potvrzení e-mailu, úspěšné volání na koncový bod /register odešle e-mail obsahující odkaz na koncový bod /confirmEmail. Odkaz obsahuje následující parametry řetězce dotazu:

  • userId
  • code
  • changedEmail – Zahrnuta pouze v případě, že uživatel během registrace změnil e-mailovou adresu.

Identity poskytuje výchozí text pro potvrzovací e-mail. Předmět e-mailu je ve výchozím nastavení "Potvrdit e-mail" a text e-mailu vypadá jako v následujícím příkladu:

 Please confirm your account by <a href='https://contoso.com/confirmEmail?userId={user ID}&code={generated code}&changedEmail={new email address}'>clicking here</a>.

RequireConfirmedEmail Pokud je vlastnost nastavená na true, uživatel se nemůže přihlásit, dokud se e-mailová adresa nepotvrdí kliknutím na odkaz v e-mailu. Koncový /confirmEmail bod:

  • Potvrdí e-mailovou adresu a povolí uživateli přihlášení.
  • Vrátí text "Děkujeme vám za potvrzení e-mailu" v textu odpovědi.

Pro nastavení Identity pro potvrzení e-mailu přidejte kód v Program.cs, který nastaví RequireConfirmedEmail na true a přidejte třídu, která implementuje IEmailSender do kontejneru DI. Příklad:

builder.Services.Configure<IdentityOptions>(options =>
{
    options.SignIn.RequireConfirmedEmail = true;
});

builder.Services.AddTransient<IEmailSender, EmailSender>();

Další informace najdete v tématu Potvrzení účtu a obnovení hesla v ASP.NET Core.

Identity poskytuje výchozí text pro ostatní e-maily, které je potřeba odeslat, například pro 2FA a resetování hesla. Pokud chcete tyto e-maily přizpůsobit, zadejte vlastní implementaci IEmailSender rozhraní. V předchozím příkladu je třída, EmailSender která implementuje IEmailSender. Další informace, včetně příkladu třídy, která implementuje IEmailSender, naleznete v tématu Potvrzení účtu a obnovení hesla v ASP.NET Core.

Použijte POST /resendConfirmationEmail koncový bod

Odešle e-mail pouze v případě, že je adresa platná pro registrovaného uživatele.

Text požadavku obsahuje pouze Email. Tady je příklad textu požadavku:

{
  "email": "string"
}

Další informace najdete v tématu Použití koncového GET /confirmEmail bodu výše v tomto článku.

Použijte POST /forgotPassword koncový bod

Vygeneruje e-mail, který obsahuje kód pro resetování hesla. Odešlete tento kód /resetPassword s novým heslem.

Text požadavku obsahuje pouze Email. Tady je příklad:

{
  "email": "string"
}

Informace o tom, jak povolit Identity odesílání e-mailů, najdete v tématu Použití koncového GET /confirmEmail bodu.

Použijte POST /resetPassword koncový bod

Zavolejte tento koncový bod poté, co získáte kód pro resetování voláním koncového bodu /forgotPassword.

Text požadavku vyžaduje Email, ResetCodea NewPassword. Tady je příklad:

{
  "email": "string",
  "resetCode": "string",
  "newPassword": "string"
}

Použijte POST /manage/2fa koncový bod

Konfiguruje dvoufaktorové ověřování (2FA) pro uživatele. Pokud je povolené 2FA, vyžaduje úspěšné přihlášení kromě e-mailové adresy a hesla kód vytvořený ověřovací aplikací.

Aktivujte 2FA

Povolení 2FA pro aktuálně ověřeného uživatele:

  • Volání koncového /manage/2fa bodu, odeslání prázdného objektu JSON ({}) v textu požadavku

  • Tělo odpovědi poskytuje SharedKey spolu s některými dalšími vlastnostmi, které nejsou v tomto okamžiku potřeba. Sdílený klíč slouží k nastavení ověřovací aplikace. Příklad textu odpovědi:

    {
      "sharedKey": "string",
      "recoveryCodesLeft": 0,
      "recoveryCodes": null,
      "isTwoFactorEnabled": false,
      "isMachineRemembered": false
    }
    
  • Sdílený klíč použijte k získání jednorázového hesla založeného na čase (TOTP). Další informace najdete v tématu Povolení generování kódu QR pro ověřovací aplikace TOTP v ASP.NET Core.

  • Zavolejte koncový bod /manage/2fa a odešlete TOTP a "enable": true v textu požadavku. Příklad:

    {
      "enable": true,
      "twoFactorCode": "string"
    }
    
  • Tělo odpovědi potvrzuje, že IsTwoFactorEnabled je pravdivé a poskytuje RecoveryCodes. Kódy obnovení se používají k přihlášení, když ověřovací aplikace není dostupná. Příklad textu odpovědi po úspěšném povolení 2FA:

    {
      "sharedKey": "string",
      "recoveryCodesLeft": 10,
      "recoveryCodes": [
        "string",
        "string",
        "string",
        "string",
        "string",
        "string",
        "string",
        "string",
        "string",
        "string"
      ],
      "isTwoFactorEnabled": true,
      "isMachineRemembered": false
    }
    

Přihlášení pomocí 2FA

Zavolejte koncový bod /login a do textu požadavku odešlete e-mailovou adresu, heslo a TOTP. Příklad:

{
  "email": "string",
  "password": "string",
  "twoFactorCode": "string"
}

Pokud uživatel nemá přístup k ověřovací aplikaci, přihlaste se voláním /login koncového bodu pomocí jednoho z kódů obnovení, které byly poskytnuty při povolení 2FA. Text požadavku vypadá jako v následujícím příkladu:

{
  "email": "string",
  "password": "string",
  "twoFactorRecoveryCode": "string"
}

Obnovit kódy pro obnovení

Pokud chcete získat novou kolekci kódů obnovení, zavolejte tento koncový bod s nastaveným ResetRecoveryCodes na true. Tady je příklad textu požadavku:

{
  "resetRecoveryCodes": true
}

Resetování sdíleného klíče

Pokud chcete získat nový náhodný sdílený klíč, zavolejte tento koncový bod a nastavte ResetSharedKey na true. Tady je příklad textu požadavku:

{
  "resetSharedKey": true
}

Resetováním klíče se automaticky zakáže požadavek na dvoufaktorové přihlášení ověřeného uživatele, dokud ho později nepovolíte.

Zapomeňte na počítač.

Pokud chcete vymazat cookie příznak "pamatovat si mě", pokud je přítomen, zavolejte tento koncový bod a nastavte ForgetMachine na true. Tady je příklad textu požadavku:

{
  "forgetMachine": true
}

Tento koncový bod nemá žádný vliv na ověřování založené na tokenech.

Použijte GET /manage/info koncový bod

Získá e-mailovou adresu a stav potvrzení e-mailu přihlášeného uživatele. Požadavky byly z tohoto bodu vynechány z bezpečnostních důvodů. Pokud jsou deklarace identity potřeba, pomocí rozhraní API na straně serveru nastavte koncový bod pro deklarace identity. Nebo místo sdílení všech deklarací identity uživatelů zadejte ověřovací koncový bod, který přijímá deklaraci identity a odpovídá na to, jestli ho uživatel má.

Požadavek nevyžaduje žádné parametry. Tělo odpovědi obsahuje vlastnosti Email a IsEmailConfirmed, jak je znázorněno v následujícím příkladu:

{
  "email": "string",
  "isEmailConfirmed": true
}

Použijte POST /manage/info koncový bod

Aktualizuje e-mailovou adresu a heslo přihlášeného uživatele. Odeslat NewEmail, NewPassworda OldPassword v textu požadavku, jak je znázorněno v následujícím příkladu:

{
  "newEmail": "string",
  "newPassword": "string",
  "oldPassword": "string"
}

Tady je příklad textu odpovědi:

{
  "email": "string",
  "isEmailConfirmed": false
}

Viz také

Další informace naleznete v následujících zdrojích:

Šablony ASP.NET Core nabízejí ověřování v jednostráňových aplikacích (SPA) s využitím podpory autorizace rozhraní API. ASP.NET Core Identity pro ověřování a ukládání uživatelů se kombinuje s Duende Identity Serverem pro implementaci OpenID Connect.

Důležité

Duende Software může vyžadovat, abyste zaplatili licenční poplatek za produkční využití serveru Duende Identity Server. Další informace najdete v tématu Migrace z ASP.NET Core v .NET 5 na .NET 6.

Do šablon projektů Angular a React byl přidán ověřovací parametr, který je podobný ověřovacímu parametru v šablonách projektů Webová aplikace (Model-View-Controller) (MVC) a Webová aplikace (Razor Stránky). Povolené hodnoty parametrů jsou None a Individual. Šablona projektu React.js a Redux v tuto chvíli nepodporuje ověřovací parametr.

Vytvoření aplikace s podporou autorizace rozhraní API

Ověřování a autorizace uživatelů lze použít jak s aplikacemi Angular, tak i s aplikacemi React SPA. Otevřete příkazové prostředí a spusťte následující příkaz:

Angular:

dotnet new angular -au Individual

React:

dotnet new react -au Individual

Předchozí příkaz vytvoří aplikaci ASP.NET Core s adresářem ClientApp obsahujícím SPA.

Obecný popis komponent aplikace ASP.NET Core

Následující části popisují doplňky k projektu, pokud je zahrnuta podpora ověřování:

Program.cs

Následující příklady kódu spoléhají na balíček NuGet Microsoft.AspNetCore.ApiAuthorization.IdentityServer . Příklady nakonfigurují ověřování a autorizaci rozhraní API pomocí rozšiřujících metod AddApiAuthorization a AddIdentityServerJwt. Projekty využívající šablony projektů React nebo Angular SPA s ověřováním obsahují odkaz na tento balíček.

dotnet new angular -au Individual vygeneruje následující Program.cs soubor:

using Microsoft.AspNetCore.Authentication;
using Microsoft.EntityFrameworkCore;
using output_directory_name.Data;
using output_directory_name.Models;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();

builder.Services.AddIdentityServer()
    .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();

builder.Services.AddAuthentication()
    .AddIdentityServerJwt();

builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

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

app.MapControllerRoute(
    name: "default",
    pattern: "{controller}/{action=Index}/{id?}");
app.MapRazorPages();

app.MapFallbackToFile("index.html");

app.Run();

Předchozí kód konfiguruje:

  • Identity s výchozím uživatelským rozhraním:

    builder.Services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlite(connectionString));
    builder.Services.AddDatabaseDeveloperPageExceptionFilter();
    
    builder.Services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();
    
  • IdentityServer s další AddApiAuthorization pomocnou metodou, která nastavuje některé výchozí konvence ASP.NET Core nad IdentityServer:

    builder.Services.AddIdentityServer()
        .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
    
  • Ověřování pomocí další AddIdentityServerJwt pomocné metody, která konfiguruje aplikaci tak, aby ověřila tokeny JWT vytvořené serverem IdentityServer:

    builder.Services.AddAuthentication()
    .AddIdentityServerJwt();
    
  • Ověřovací middleware, který je zodpovědný za ověření přihlašovacích údajů žádosti a nastavení uživatele v kontextu žádosti:

    app.UseAuthentication();
    
  • Middleware IdentityServer, které zveřejňuje koncové body OpenID Connect:

    app.UseIdentityServer();
    

Varování

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í.

Aplikace Azure Service v Linuxu

Pro nasazení Azure App Service na Linuxu explicitně zadejte vystavitele.

builder.Services.Configure<JwtBearerOptions>(
    IdentityServerJwtConstants.IdentityServerJwtBearerScheme, 
    options =>
    {
        options.Authority = "{AUTHORITY}";
    });

V předchozím kódu {AUTHORITY} je Authority zástupný symbol, který se má použít při volání OpenID Connect.

Příklad:

options.Authority = "https://contoso-service.azurewebsites.net";

AddApiAuthorization

Tato pomocná metoda konfiguruje IdentityServer tak, aby používala naši podporovanou konfiguraci. IdentityServer je výkonná a rozšiřitelná architektura pro zpracování problémů se zabezpečením aplikací. Zároveň to odhaluje zbytečnou složitost v případě nejběžnějších scénářů. V důsledku toho je k dispozici sada konvencí a možností konfigurace, které jsou považovány za dobrý výchozí bod. Jakmile se vaše potřeby ověřování změní, veškeré možnosti IdentityServeru zůstávají dostupné, což vám umožní přizpůsobit ověřování tak, aby vyhovovalo vašim potřebám.

AddIdentityServerJwt

Tato pomocná metoda nakonfiguruje schéma zásad pro aplikaci jako výchozí obslužnou rutinu ověřování. Zásada je nakonfigurovaná tak, aby zpracovávala Identity všechny požadavky směrované na jakoukoli dílčí cestu v Identity prostoru adresy URL /Identity. JwtBearerHandler zpracovává všechny ostatní požadavky. Kromě toho tato metoda zaregistruje <<ApplicationName>>API prostředek rozhraní API u IdentityServer s výchozím oborem <<ApplicationName>>API a nakonfiguruje middleware tokenu JWT Bearer k ověření tokenů vydaných serverem IdentityServer pro aplikaci.

WeatherForecastController

V souboru si všimněte atributu [Authorize] použitého u třídy, který indikuje, že uživatel musí být autorizovaný na základě výchozí zásady pro přístup k prostředku. Výchozí politika autorizace je náhodou nakonfigurována tak, aby používala výchozí schéma ověřování. Toto schéma je nastaveno pomocí AddIdentityServerJwt podle výše zmíněného schématu politiky, díky čemuž JwtBearerHandler nakonfiguruje pomocná metoda jako výchozí obslužnou rutinu pro požadavky na aplikaci.

ApplicationDbContext

V souboru se stejná DbContext používá v Identity, s výjimkou, že rozšiřuje ApiAuthorizationDbContext (odvozenější třídu z IdentityDbContext), aby zahrnovala schéma pro IdentityServer.

Pokud chcete získat úplnou kontrolu nad schématem databáze, měli byste dědit z jedné z dostupných IdentityDbContext tříd a nakonfigurovat kontext tak, aby zahrnoval Identity schéma voláním builder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value) na metodu OnModelCreating.

OidcConfigurationController

V souboru si všimněte koncového bodu, který je zřízený tak, aby sloužil parametrům OIDC, které klient potřebuje použít.

appsettings.json

appsettings.json V souboru kořenového adresáře projektu je nový IdentityServer oddíl, který popisuje seznam nakonfigurovaných klientů. V následujícím příkladu je jeden klient. Název klienta odpovídá názvu aplikace a mapuje se konvencí na parametr OAuth ClientId . Profil označuje typ aplikace, který se konfiguruje. Používá se interně k řízení konvencí, které zjednodušují proces konfigurace serveru. K dispozici je několik profilů, jak je vysvětleno v části Profily aplikací.

"IdentityServer": {
  "Clients": {
    "angularindividualpreview3final": {
      "Profile": "IdentityServerSPA"
    }
  }
}

appsettings.Development.json

appsettings.Development.json V souboru kořenového adresáře projektu je IdentityServer oddíl, který popisuje klíč použitý k podepisování tokenů. Při nasazování do produkčního prostředí je potřeba zřídit a nasadit klíč společně s aplikací, jak je vysvětleno v části Nasazení do produkčního prostředí .

"IdentityServer": {
  "Key": {
    "Type": "Development"
  }
}

Obecný popis aplikace Angular

Podpora ověřování a autorizace rozhraní API v šabloně Angular se nachází ve vlastním modulu Angular v adresáři ClientApp/src/api-authorization . Modul se skládá z následujících prvků:

  • 3 komponenty:
    • login.component.ts: Zpracovává tok přihlášení aplikace.
    • logout.component.ts: Zpracovává tok odhlášení aplikace.
    • login-menu.component.ts: Widget, který zobrazuje jednu z následujících sad odkazů:
      • Správa profilů uživatelů a odkazy pro odhlášení, když je uživatel ověřen.
      • Odkazy pro registraci a přihlášení, když uživatel není přihlášen.
  • Ochrana AuthorizeGuard tras, která se dá přidat do tras a vyžaduje ověření uživatele před návštěvou trasy.
  • Zachycovač AuthorizeInterceptor HTTP, který připojí přístupový token k odchozím požadavkům HTTP, které cílí na rozhraní API, když je uživatel ověřen.
  • Služba AuthorizeService, která zpracovává podrobnosti procesu ověřování na nižší úrovni a zpřístupňuje informace o ověřeném uživateli pro zbytek aplikace pro použití.
  • Modul Angular, který definuje trasy přidružené k ověřovacím částem aplikace. Zpřístupňuje komponentu nabídky přihlášení, zachytávač, ochranu a službu k použití zbytkem aplikace.

Obecný popis aplikace React

Podpora ověřování a autorizace rozhraní API v šabloně React se nachází v adresáři ClientApp/src/components/api-authorization . Skládá se z následujících prvků:

  • 4 komponenty:
    • Login.js: Zpracovává tok přihlášení aplikace.
    • Logout.js: Zpracovává tok odhlášení aplikace.
    • LoginMenu.js: Widget, který zobrazuje jednu z následujících sad odkazů:
      • Správa profilů uživatelů a odkazy pro odhlášení, když je uživatel ověřen.
      • Odkazy pro registraci a přihlášení, když uživatel není přihlášen.
    • AuthorizeRoute.js: Komponenta trasy, která vyžaduje ověření uživatele před vykreslením komponenty uvedené v parametru Component .
  • Exportovaná authService instance třídy AuthorizeService, která zpracovává podrobnosti procesu ověřování na nižší úrovni a zveřejňuje informace o ověřeném uživateli pro zbytek aplikace za účelem použití.

Teď, když jste viděli hlavní komponenty řešení, můžete se podrobněji podívat na jednotlivé scénáře aplikace.

Vyžadování autorizace v novém rozhraní API

Ve výchozím nastavení je systém nakonfigurovaný tak, aby snadno vyžadoval autorizaci pro nová rozhraní API. Uděláte to tak, že vytvoříte nový kontroler a přidáte [Authorize] atribut do třídy kontroleru nebo k jakékoli akci v rámci kontroleru.

Přizpůsobení obslužné rutiny ověřování rozhraní API

Pokud chcete přizpůsobit konfiguraci obslužné rutiny JWT rozhraní API, nakonfigurujte její JwtBearerOptions instanci:

builder.Services.AddAuthentication()
    .AddIdentityServerJwt();

builder.Services.Configure<JwtBearerOptions>(
    IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
    options =>
    {
        ...
    });

Obslužná rutina JWT rozhraní API vyvolává události, které umožňují kontrolu nad procesem ověřování pomocí JwtBearerEvents. Pro zajištění podpory autorizace API AddIdentityServerJwt registruje vlastní obslužné rutiny událostí.

Pokud chcete přizpůsobit zpracování události, zabalte existující obslužnou rutinu události s další logikou podle potřeby. Příklad:

builder.Services.Configure<JwtBearerOptions>(
    IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
    options =>
    {
        var onTokenValidated = options.Events.OnTokenValidated;       

        options.Events.OnTokenValidated = async context =>
        {
            await onTokenValidated(context);
            ...
        }
    });

V předchozím kódu je obslužná rutina události OnTokenValidated nahrazena vlastní implementací. Tato implementace:

  1. Volá původní implementaci poskytnutou podporou autorizace rozhraní API.
  2. Spusťte vlastní nastavenou logiku.

Ochrana trasy na straně klienta (Angular)

Ochrana trasy na straně klienta se provádí přidáním autorizaci ochrany do seznamu ochranných opatření, která se mají spustit při konfiguraci trasy. Například můžete vidět, jak je trasa fetch-data nakonfigurovaná v hlavním modulu aplikace Angular.

RouterModule.forRoot([
  // ...
  { path: 'fetch-data', component: FetchDataComponent, canActivate: [AuthorizeGuard] },
])

Je důležité zmínit, že ochrana trasy nechrání skutečný koncový bod (který stále vyžaduje [Authorize] atribut použitý na něj), ale že zabrání uživateli v přechodu na danou trasu na straně klienta, když se neověří.

Ověřování požadavků rozhraní API (Angular)

Ověřování požadavků na rozhraní API hostovaná společně s aplikací se provádí automaticky prostřednictvím HTTP klientského interceptoru definovaného aplikací.

Ochrana trasy na straně klienta (React)

Chraňte trasu na straně klienta pomocí AuthorizeRoute komponenty místo prosté Route komponenty. Například si všimněte, jak je trasa fetch-data nakonfigurována v komponentě App.

<AuthorizeRoute path='/fetch-data' component={FetchData} />

Ochrana trasy:

  • Nechrání skutečný koncový bod (který stále vyžaduje použití atributu [Authorize] ).
  • Zabrání uživateli pouze v přechodu na danou trasu na straně klienta, pokud není autentizovaný.

Ověřování požadavků rozhraní API (React)

Ověřování požadavků pomocí Reactu se provádí tak, že nejprve naimportujete authService instanci z objektu AuthorizeService. Přístupový token se načte z authService a poté se připojí k žádosti, jak je znázorněno níže. V komponentách Reactu se tato práce obvykle provádí v componentDidMount metodě životního cyklu nebo v důsledku určité interakce uživatele.

Importujte authService do komponenty

import authService from './api-authorization/AuthorizeService'

Načtení a připojení přístupového tokenu k odpovědi

async populateWeatherData() {
  const token = await authService.getAccessToken();
  const response = await fetch('api/SampleData/WeatherForecasts', {
    headers: !token ? {} : { 'Authorization': `Bearer ${token}` }
  });
  const data = await response.json();
  this.setState({ forecasts: data, loading: false });
}

Nasadit do produkce

Pokud chcete nasadit aplikaci do produkčního prostředí, je potřeba zřídit následující prostředky:

  • Databáze ke ukládání uživatelských Identity účtů a povolení IdentityServeru.
  • Produkční certifikát, který se použije pro podpisové tokeny.
    • Pro tento certifikát neexistují žádné specifické požadavky. Může to být svépodpisový certifikát nebo certifikát zřízený prostřednictvím certifikační autority.
    • Dá se vygenerovat prostřednictvím standardních nástrojů, jako je PowerShell nebo OpenSSL.
    • Dá se nainstalovat do úložiště certifikátů na cílových počítačích nebo nasadit jako soubor .pfx se silným heslem.

Příklad: Nasazení do poskytovatele webového hostingu mimo Azure

Na panelu hostování webu vytvořte nebo načtěte certifikát. Potom v souboru aplikace appsettings.json upravte IdentityServer oddíl tak, aby obsahoval podrobnosti o klíči. Příklad:

"IdentityServer": {
  "Key": {
    "Type": "Store",
    "StoreName": "WebHosting",
    "StoreLocation": "CurrentUser",
    "Name": "CN=MyApplication"
  }
}

V předchozím příkladu:

  • StoreName představuje název úložiště certifikátů, ve kterém je certifikát uložený. V tomto případě odkazuje na úložiště pro hostování webu.
  • StoreLocation představuje, odkud se má certifikát načíst (CurrentUser v tomto případě).
  • Name odpovídá rozlišujícímu předmětu certifikátu.

Příklad: Nasazení do služby Aplikace Azure

Tato část popisuje nasazení aplikace do služby Aplikace Azure Service pomocí certifikátu uloženého v úložišti certifikátů. Pokud chcete aplikaci upravit tak, aby načetla certifikát z úložiště certifikátů, vyžaduje se při konfiguraci aplikace na webu Azure Portal v pozdějším kroku plán služby úrovně Standard nebo lepší.

V souboru aplikace appsettings.json upravte IdentityServer oddíl tak, aby obsahoval podrobnosti o klíči:

"IdentityServer": {
  "Key": {
    "Type": "Store",
    "StoreName": "My",
    "StoreLocation": "CurrentUser",
    "Name": "CN=MyApplication"
  }
}
  • Název úložiště představuje název úložiště certifikátů, ve kterém je certifikát uložený. V tomto případě odkazuje na osobní úložiště uživatelů.
  • Umístění úložiště představuje, odkud se má certifikát načíst (CurrentUser nebo LocalMachine).
  • Vlastnost název certifikátu odpovídá rozlišujícímu předmětu certifikátu.

Pokud chcete nasadit službu Aplikace Azure Service, postupujte podle kroků v tématu Nasazení aplikace do Azure, který vysvětluje, jak vytvořit potřebné prostředky Azure a nasadit aplikaci do produkčního prostředí.

Po provedení předchozích pokynů se aplikace nasadí do Azure, ale ještě není funkční. Certifikát používaný aplikací musí být nakonfigurovaný na webu Azure Portal. Vyhledejte kryptografický otisk certifikátu a postupujte podle kroků popsaných v tématu Načtení certifikátů.

I když tyto kroky zmiňují PROTOKOL SSL, na webu Azure Portal je část Privátní certifikáty , kde můžete nahrát zřízený certifikát, který se má s aplikací používat.

Po nakonfigurování aplikace a nastavení aplikace na webu Azure Portal restartujte aplikaci na portálu.

Další možnosti konfigurace

Podpora autorizace rozhraní API vychází z IdentityServeru se sadou konvencí, výchozích hodnot a vylepšení, které zjednodušují prostředí pro služby SPA. Bez nutnosti říct, že plný výkon IdentityServeru je k dispozici na pozadí, pokud integrace ASP.NET Core nepokrývají váš scénář. Podpora ASP.NET Core se zaměřuje na aplikace typu "první strana", kde se všechny aplikace vytvářejí a nasazují naší organizací. Podpora se proto nenabízí pro věci, jako je souhlas nebo federace. V těchto scénářích použijte IdentityServer a postupujte podle jejich dokumentace.

Profily aplikací

Profily aplikací jsou předdefinované konfigurace pro aplikace, které dále definují jejich parametry. V tuto chvíli jsou podporovány následující profily:

  • IdentityServerSPA: Představuje SPA hostované společně s IdentityServerem jako jedinou jednotkou.
    • Výchozí redirect_uri je /authentication/login-callback.
    • Výchozí post_logout_redirect_uri je /authentication/logout-callback.
    • Sada oborů zahrnuje openidprofilea každý obor definovaný pro rozhraní API v aplikaci.
    • Sada povolených typů odpovědí OIDC je id_token token nebo každá z nich jednotlivě (id_token, token).
    • Povolený režim odezvy je fragment.
  • SPA: Představuje SPA, které není hostováno se serverem IdentityServer.
    • Sada oborů zahrnuje openidprofilea každý obor definovaný pro rozhraní API v aplikaci.
    • Sada povolených typů odpovědí OIDC je id_token token nebo každá z nich jednotlivě (id_token, token).
    • Povolený režim odezvy je fragment.
  • IdentityServerJwt: Představuje rozhraní API hostované společně s IdentityServerem.
    • Aplikace je nakonfigurovaná tak, aby měla jeden obor, který má výchozí název aplikace.
  • API: Představuje rozhraní API, které není hostované pomocí IdentityServeru.
    • Aplikace je nakonfigurovaná tak, aby měla jeden obor, který má výchozí název aplikace.

Konfigurace prostřednictvím AppSettings

Nakonfigurujte aplikace prostřednictvím konfiguračního systému tak, že je přidáte do seznamu Clients nebo Resources.

Nakonfigurujte vlastnost redirect_uri a post_logout_redirect_uri jednotlivých klientů, jak je znázorněno v následujícím příkladu:

"IdentityServer": {
  "Clients": {
    "MySPA": {
      "Profile": "SPA",
      "RedirectUri": "https://www.example.com/authentication/login-callback",
      "LogoutUri": "https://www.example.com/authentication/logout-callback"
    }
  }
}

Při konfiguraci prostředků můžete nakonfigurovat obory pro prostředek, jak je znázorněno níže:

"IdentityServer": {
  "Resources": {
    "MyExternalApi": {
      "Profile": "API",
      "Scopes": "a b c"
    }
  }
}

Konfigurace prostřednictvím kódu

Klienty a prostředky můžete také nakonfigurovat prostřednictvím kódu pomocí přetížení AddApiAuthorization , které provede akci ke konfiguraci možností.

AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
{
    options.Clients.AddSPA(
        "My SPA", spa =>
        spa.WithRedirectUri("http://www.example.com/authentication/login-callback")
           .WithLogoutRedirectUri(
               "http://www.example.com/authentication/logout-callback"));

    options.ApiResources.AddApiResource("MyExternalApi", resource =>
        resource.WithScopes("a", "b", "c"));
});

Další materiály

Šablony ASP.NET Core 3.1 nebo novější nabízejí ověřování v jednostráňových aplikacích (SPA) s využitím podpory autorizace rozhraní API. ASP.NET Core Identity pro ověřování a ukládání uživatelů se kombinuje s IdentityServerem pro implementaci OpenID Connect.

Do šablon projektů Angular a React byl přidán ověřovací parametr, který je podobný ověřovacímu parametru v šablonách projektů Webová aplikace (Model-View-Controller) (MVC) a Webová aplikace (Razor Stránky). Povolené hodnoty parametrů jsou None a Individual. Šablona projektu React.js a Redux v tuto chvíli nepodporuje ověřovací parametr.

Vytvoření aplikace s podporou autorizace rozhraní API

Ověřování a autorizace uživatelů lze použít jak s aplikacemi Angular, tak i s aplikacemi React SPA. Otevřete příkazové prostředí a spusťte následující příkaz:

Angular:

dotnet new angular -o <output_directory_name> 

React:

dotnet new react -o <output_directory_name> -au Individual

Předchozí příkaz vytvoří aplikaci ASP.NET Core s adresářem ClientApp obsahujícím SPA.

Obecný popis komponent aplikace ASP.NET Core

Následující části popisují doplňky k projektu, pokud je zahrnuta podpora ověřování:

Třída Startup

Následující příklady kódu spoléhají na balíček NuGet Microsoft.AspNetCore.ApiAuthorization.IdentityServer . Příklady nakonfigurují ověřování a autorizaci rozhraní API pomocí rozšiřujících metod AddApiAuthorization a AddIdentityServerJwt. Projekty využívající šablony projektů React nebo Angular SPA s ověřováním obsahují odkaz na tento balíček.

Třída Startup obsahuje následující doplňky:

  • Startup.ConfigureServices Uvnitř metody:

    • Identity s výchozím uživatelským rozhraním:

      services.AddDbContext<ApplicationDbContext>(options =>
          options.UseSqlite(Configuration.GetConnectionString("DefaultConnection")));
      
      services.AddDefaultIdentity<ApplicationUser>()
          .AddEntityFrameworkStores<ApplicationDbContext>();
      
    • IdentityServer s další AddApiAuthorization pomocnou metodou, která nastavuje některé výchozí konvence ASP.NET Core nad IdentityServer:

      services.AddIdentityServer()
          .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
      
    • Ověřování pomocí další AddIdentityServerJwt pomocné metody, která konfiguruje aplikaci tak, aby ověřila tokeny JWT vytvořené serverem IdentityServer:

      services.AddAuthentication()
          .AddIdentityServerJwt();
      
  • Startup.Configure Uvnitř metody:

    • Ověřovací middleware, který je zodpovědný za ověření přihlašovacích údajů žádosti a nastavení uživatele v kontextu žádosti:

      app.UseAuthentication();
      
    • Middleware IdentityServer, které zveřejňuje koncové body OpenID Connect:

      app.UseIdentityServer();
      

Varování

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í.

Aplikace Azure Service v Linuxu

Pro nasazení služby Aplikace Azure na Linuxu zadejte vystavitele explicitně v Startup.ConfigureServices:

services.Configure<JwtBearerOptions>(
    IdentityServerJwtConstants.IdentityServerJwtBearerScheme, 
    options =>
    {
        options.Authority = "{AUTHORITY}";
    });

V předchozím kódu {AUTHORITY} je Authority zástupný symbol, který se má použít při volání OpenID Connect.

Příklad:

options.Authority = "https://contoso-service.azurewebsites.net";

AddApiAuthorization

Tato pomocná metoda konfiguruje IdentityServer tak, aby používala naši podporovanou konfiguraci. IdentityServer je výkonná a rozšiřitelná architektura pro zpracování problémů se zabezpečením aplikací. Zároveň to odhaluje zbytečnou složitost v případě nejběžnějších scénářů. V důsledku toho je k dispozici sada konvencí a možností konfigurace, které jsou považovány za dobrý výchozí bod. Jakmile se vaše potřeby ověřování změní, veškeré možnosti IdentityServeru zůstávají dostupné, což vám umožní přizpůsobit ověřování tak, aby vyhovovalo vašim potřebám.

AddIdentityServerJwt

Tato pomocná metoda nakonfiguruje schéma zásad pro aplikaci jako výchozí obslužnou rutinu ověřování. Zásada je nakonfigurovaná tak, aby zpracovávala Identity všechny požadavky směrované na jakoukoli dílčí cestu v Identity prostoru adresy URL /Identity. JwtBearerHandler zpracovává všechny ostatní požadavky. Kromě toho tato metoda zaregistruje <<ApplicationName>>API prostředek rozhraní API u IdentityServer s výchozím oborem <<ApplicationName>>API a nakonfiguruje middleware tokenu JWT Bearer k ověření tokenů vydaných serverem IdentityServer pro aplikaci.

WeatherForecastController

V souboru si všimněte atributu [Authorize] použitého u třídy, který indikuje, že uživatel musí být autorizovaný na základě výchozí zásady pro přístup k prostředku. Výchozí politika autorizace je náhodou nakonfigurována tak, aby používala výchozí schéma ověřování. Toto schéma je nastaveno pomocí AddIdentityServerJwt podle výše zmíněného schématu politiky, díky čemuž JwtBearerHandler nakonfiguruje pomocná metoda jako výchozí obslužnou rutinu pro požadavky na aplikaci.

ApplicationDbContext

V souboru se stejná DbContext používá v Identity, s výjimkou, že rozšiřuje ApiAuthorizationDbContext (odvozenější třídu z IdentityDbContext), aby zahrnovala schéma pro IdentityServer.

Pokud chcete získat úplnou kontrolu nad schématem databáze, měli byste dědit z jedné z dostupných IdentityDbContext tříd a nakonfigurovat kontext tak, aby zahrnoval Identity schéma voláním builder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value) na metodu OnModelCreating.

OidcConfigurationController

V souboru si všimněte koncového bodu, který je zřízený tak, aby sloužil parametrům OIDC, které klient potřebuje použít.

appsettings.json

appsettings.json V souboru kořenového adresáře projektu je nový IdentityServer oddíl, který popisuje seznam nakonfigurovaných klientů. V následujícím příkladu je jeden klient. Název klienta odpovídá názvu aplikace a mapuje se konvencí na parametr OAuth ClientId . Profil označuje typ aplikace, který se konfiguruje. Používá se interně k řízení konvencí, které zjednodušují proces konfigurace serveru. K dispozici je několik profilů, jak je vysvětleno v části Profily aplikací.

"IdentityServer": {
  "Clients": {
    "angularindividualpreview3final": {
      "Profile": "IdentityServerSPA"
    }
  }
}

appsettings.Development.json

appsettings.Development.json V souboru kořenového adresáře projektu je IdentityServer oddíl, který popisuje klíč použitý k podepisování tokenů. Při nasazování do produkčního prostředí je potřeba zřídit a nasadit klíč společně s aplikací, jak je vysvětleno v části Nasazení do produkčního prostředí .

"IdentityServer": {
  "Key": {
    "Type": "Development"
  }
}

Obecný popis aplikace Angular

Podpora ověřování a autorizace rozhraní API v šabloně Angular se nachází ve vlastním modulu Angular v adresáři ClientApp/src/api-authorization . Modul se skládá z následujících prvků:

  • 3 komponenty:
    • login.component.ts: Zpracovává tok přihlášení aplikace.
    • logout.component.ts: Zpracovává tok odhlášení aplikace.
    • login-menu.component.ts: Widget, který zobrazuje jednu z následujících sad odkazů:
      • Správa profilů uživatelů a odkazy pro odhlášení, když je uživatel ověřen.
      • Odkazy pro registraci a přihlášení, když uživatel není přihlášen.
  • Ochrana AuthorizeGuard tras, která se dá přidat do tras a vyžaduje ověření uživatele před návštěvou trasy.
  • Zachycovač AuthorizeInterceptor HTTP, který připojí přístupový token k odchozím požadavkům HTTP, které cílí na rozhraní API, když je uživatel ověřen.
  • Služba AuthorizeService, která zpracovává podrobnosti procesu ověřování na nižší úrovni a zpřístupňuje informace o ověřeném uživateli pro zbytek aplikace pro použití.
  • Modul Angular, který definuje trasy přidružené k ověřovacím částem aplikace. Zpřístupňuje komponentu nabídky přihlášení, zachytávač, ochranu a službu k použití zbytkem aplikace.

Obecný popis aplikace React

Podpora ověřování a autorizace rozhraní API v šabloně React se nachází v adresáři ClientApp/src/components/api-authorization . Skládá se z následujících prvků:

  • 4 komponenty:
    • Login.js: Zpracovává tok přihlášení aplikace.
    • Logout.js: Zpracovává tok odhlášení aplikace.
    • LoginMenu.js: Widget, který zobrazuje jednu z následujících sad odkazů:
      • Správa profilů uživatelů a odkazy pro odhlášení, když je uživatel ověřen.
      • Odkazy pro registraci a přihlášení, když uživatel není přihlášen.
    • AuthorizeRoute.js: Komponenta trasy, která vyžaduje ověření uživatele před vykreslením komponenty uvedené v parametru Component .
  • Exportovaná authService instance třídy AuthorizeService, která zpracovává podrobnosti procesu ověřování na nižší úrovni a zveřejňuje informace o ověřeném uživateli pro zbytek aplikace za účelem použití.

Teď, když jste viděli hlavní komponenty řešení, můžete se podrobněji podívat na jednotlivé scénáře aplikace.

Vyžadování autorizace v novém rozhraní API

Ve výchozím nastavení je systém nakonfigurovaný tak, aby snadno vyžadoval autorizaci pro nová rozhraní API. Uděláte to tak, že vytvoříte nový kontroler a přidáte [Authorize] atribut do třídy kontroleru nebo k jakékoli akci v rámci kontroleru.

Přizpůsobení obslužné rutiny ověřování rozhraní API

Pokud chcete přizpůsobit konfiguraci obslužné rutiny JWT rozhraní API, nakonfigurujte její JwtBearerOptions instanci:

services.AddAuthentication()
    .AddIdentityServerJwt();

services.Configure<JwtBearerOptions>(
    IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
    options =>
    {
        ...
    });

Obslužná rutina JWT rozhraní API vyvolává události, které umožňují kontrolu nad procesem ověřování pomocí JwtBearerEvents. Pro zajištění podpory autorizace API AddIdentityServerJwt registruje vlastní obslužné rutiny událostí.

Pokud chcete přizpůsobit zpracování události, zabalte existující obslužnou rutinu události s další logikou podle potřeby. Příklad:

services.Configure<JwtBearerOptions>(
    IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
    options =>
    {
        var onTokenValidated = options.Events.OnTokenValidated;       

        options.Events.OnTokenValidated = async context =>
        {
            await onTokenValidated(context);
            ...
        }
    });

V předchozím kódu je obslužná rutina události OnTokenValidated nahrazena vlastní implementací. Tato implementace:

  1. Volá původní implementaci poskytnutou podporou autorizace rozhraní API.
  2. Spusťte vlastní nastavenou logiku.

Ochrana trasy na straně klienta (Angular)

Ochrana trasy na straně klienta se provádí přidáním autorizaci ochrany do seznamu ochranných opatření, která se mají spustit při konfiguraci trasy. Například můžete vidět, jak je trasa fetch-data nakonfigurovaná v hlavním modulu aplikace Angular.

RouterModule.forRoot([
  // ...
  { path: 'fetch-data', component: FetchDataComponent, canActivate: [AuthorizeGuard] },
])

Je důležité zmínit, že ochrana trasy nechrání skutečný koncový bod (který stále vyžaduje [Authorize] atribut použitý na něj), ale že zabrání uživateli v přechodu na danou trasu na straně klienta, když se neověří.

Ověřování požadavků rozhraní API (Angular)

Ověřování požadavků na rozhraní API hostovaná společně s aplikací se provádí automaticky prostřednictvím HTTP klientského interceptoru definovaného aplikací.

Ochrana trasy na straně klienta (React)

Chraňte trasu na straně klienta pomocí AuthorizeRoute komponenty místo prosté Route komponenty. Například si všimněte, jak je trasa fetch-data nakonfigurována v komponentě App.

<AuthorizeRoute path='/fetch-data' component={FetchData} />

Ochrana trasy:

  • Nechrání skutečný koncový bod (který stále vyžaduje použití atributu [Authorize] ).
  • Zabrání uživateli pouze v přechodu na danou trasu na straně klienta, pokud není autentizovaný.

Ověřování požadavků rozhraní API (React)

Ověřování požadavků pomocí Reactu se provádí tak, že nejprve naimportujete authService instanci z objektu AuthorizeService. Přístupový token se načte z authService a poté se připojí k žádosti, jak je znázorněno níže. V komponentách Reactu se tato práce obvykle provádí v componentDidMount metodě životního cyklu nebo v důsledku určité interakce uživatele.

Importujte authService do komponenty

import authService from './api-authorization/AuthorizeService'

Načtení a připojení přístupového tokenu k odpovědi

async populateWeatherData() {
  const token = await authService.getAccessToken();
  const response = await fetch('api/SampleData/WeatherForecasts', {
    headers: !token ? {} : { 'Authorization': `Bearer ${token}` }
  });
  const data = await response.json();
  this.setState({ forecasts: data, loading: false });
}

Nasadit do produkce

Pokud chcete nasadit aplikaci do produkčního prostředí, je potřeba zřídit následující prostředky:

  • Databáze ke ukládání uživatelských Identity účtů a povolení IdentityServeru.
  • Produkční certifikát, který se použije pro podpisové tokeny.
    • Pro tento certifikát neexistují žádné specifické požadavky. Může to být svépodpisový certifikát nebo certifikát zřízený prostřednictvím certifikační autority.
    • Dá se vygenerovat prostřednictvím standardních nástrojů, jako je PowerShell nebo OpenSSL.
    • Dá se nainstalovat do úložiště certifikátů na cílových počítačích nebo nasadit jako soubor .pfx se silným heslem.

Příklad: Nasazení do poskytovatele webového hostingu mimo Azure

Na panelu hostování webu vytvořte nebo načtěte certifikát. Potom v souboru aplikace appsettings.json upravte IdentityServer oddíl tak, aby obsahoval podrobnosti o klíči. Příklad:

"IdentityServer": {
  "Key": {
    "Type": "Store",
    "StoreName": "WebHosting",
    "StoreLocation": "CurrentUser",
    "Name": "CN=MyApplication"
  }
}

V předchozím příkladu:

  • StoreName představuje název úložiště certifikátů, ve kterém je certifikát uložený. V tomto případě odkazuje na úložiště pro hostování webu.
  • StoreLocation představuje, odkud se má certifikát načíst (CurrentUser v tomto případě).
  • Name odpovídá rozlišujícímu předmětu certifikátu.

Příklad: Nasazení do služby Aplikace Azure

Tato část popisuje nasazení aplikace do služby Aplikace Azure Service pomocí certifikátu uloženého v úložišti certifikátů. Pokud chcete aplikaci upravit tak, aby načetla certifikát z úložiště certifikátů, vyžaduje se při konfiguraci aplikace na webu Azure Portal v pozdějším kroku plán služby úrovně Standard nebo lepší.

V souboru aplikace appsettings.json upravte IdentityServer oddíl tak, aby obsahoval podrobnosti o klíči:

"IdentityServer": {
  "Key": {
    "Type": "Store",
    "StoreName": "My",
    "StoreLocation": "CurrentUser",
    "Name": "CN=MyApplication"
  }
}
  • Název úložiště představuje název úložiště certifikátů, ve kterém je certifikát uložený. V tomto případě odkazuje na osobní úložiště uživatelů.
  • Umístění úložiště představuje, odkud se má certifikát načíst (CurrentUser nebo LocalMachine).
  • Vlastnost název certifikátu odpovídá rozlišujícímu předmětu certifikátu.

Pokud chcete nasadit službu Aplikace Azure Service, postupujte podle kroků v tématu Nasazení aplikace do Azure, který vysvětluje, jak vytvořit potřebné prostředky Azure a nasadit aplikaci do produkčního prostředí.

Po provedení předchozích pokynů se aplikace nasadí do Azure, ale ještě není funkční. Certifikát používaný aplikací musí být nakonfigurovaný na webu Azure Portal. Vyhledejte kryptografický otisk certifikátu a postupujte podle kroků popsaných v tématu Načtení certifikátů.

I když tyto kroky zmiňují PROTOKOL SSL, na webu Azure Portal je část Privátní certifikáty , kde můžete nahrát zřízený certifikát, který se má s aplikací používat.

Po nakonfigurování aplikace a nastavení aplikace na webu Azure Portal restartujte aplikaci na portálu.

Další možnosti konfigurace

Podpora autorizace rozhraní API vychází z IdentityServeru se sadou konvencí, výchozích hodnot a vylepšení, které zjednodušují prostředí pro služby SPA. Bez nutnosti říct, že plný výkon IdentityServeru je k dispozici na pozadí, pokud integrace ASP.NET Core nepokrývají váš scénář. Podpora ASP.NET Core se zaměřuje na aplikace typu "první strana", kde se všechny aplikace vytvářejí a nasazují naší organizací. Podpora se proto nenabízí pro věci, jako je souhlas nebo federace. V těchto scénářích použijte IdentityServer a postupujte podle jejich dokumentace.

Profily aplikací

Profily aplikací jsou předdefinované konfigurace pro aplikace, které dále definují jejich parametry. V tuto chvíli jsou podporovány následující profily:

  • IdentityServerSPA: Představuje SPA hostované společně s IdentityServerem jako jedinou jednotkou.
    • Výchozí redirect_uri je /authentication/login-callback.
    • Výchozí post_logout_redirect_uri je /authentication/logout-callback.
    • Sada oborů zahrnuje openidprofilea každý obor definovaný pro rozhraní API v aplikaci.
    • Sada povolených typů odpovědí OIDC je id_token token nebo každá z nich jednotlivě (id_token, token).
    • Povolený režim odezvy je fragment.
  • SPA: Představuje SPA, které není hostováno se serverem IdentityServer.
    • Sada oborů zahrnuje openidprofilea každý obor definovaný pro rozhraní API v aplikaci.
    • Sada povolených typů odpovědí OIDC je id_token token nebo každá z nich jednotlivě (id_token, token).
    • Povolený režim odezvy je fragment.
  • IdentityServerJwt: Představuje rozhraní API hostované společně s IdentityServerem.
    • Aplikace je nakonfigurovaná tak, aby měla jeden obor, který má výchozí název aplikace.
  • API: Představuje rozhraní API, které není hostované pomocí IdentityServeru.
    • Aplikace je nakonfigurovaná tak, aby měla jeden obor, který má výchozí název aplikace.

Konfigurace prostřednictvím AppSettings

Nakonfigurujte aplikace prostřednictvím konfiguračního systému tak, že je přidáte do seznamu Clients nebo Resources.

Nakonfigurujte vlastnost redirect_uri a post_logout_redirect_uri jednotlivých klientů, jak je znázorněno v následujícím příkladu:

"IdentityServer": {
  "Clients": {
    "MySPA": {
      "Profile": "SPA",
      "RedirectUri": "https://www.example.com/authentication/login-callback",
      "LogoutUri": "https://www.example.com/authentication/logout-callback"
    }
  }
}

Při konfiguraci prostředků můžete nakonfigurovat obory pro prostředek, jak je znázorněno níže:

"IdentityServer": {
  "Resources": {
    "MyExternalApi": {
      "Profile": "API",
      "Scopes": "a b c"
    }
  }
}

Konfigurace prostřednictvím kódu

Klienty a prostředky můžete také nakonfigurovat prostřednictvím kódu pomocí přetížení AddApiAuthorization , které provede akci ke konfiguraci možností.

AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
{
    options.Clients.AddSPA(
        "My SPA", spa =>
        spa.WithRedirectUri("http://www.example.com/authentication/login-callback")
           .WithLogoutRedirectUri(
               "http://www.example.com/authentication/logout-callback"));

    options.ApiResources.AddApiResource("MyExternalApi", resource =>
        resource.WithScopes("a", "b", "c"));
});

Další materiály