Identity Použití k zabezpečení back-endu webového rozhraní API pro služby SPA

Poznámka:

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

Důležité

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

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

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-endu webového rozhraní API pomocí cookieověřování na základě. Existuje možnost založená na tokenech pro klienty, kteří nemůžou používat cookie.

Tento článek ukazuje, jak zabezpečit Identity back-end webového rozhraní API pro služby 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é používat Identity s back-endem 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ření 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;

EF Core Konfigurace kontextu

Jak už jsme uvedli dříve, nejjednodušší způsob, jak začít, je použít databázi v paměti. Při každém spuštění v paměti začíná nová databáze 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 volání WebApplication.CreateBuilder(args)volání volání AddAuthorization přidat služby do kontejneru injektáž závislostí (DI):

builder.Services.AddAuthorization();

Aktivace Identity rozhraní API

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

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

Ve výchozím nastavení se aktivují tokeny i cookieproprietární tokeny. CookieTokeny a tokeny se vydávají při přihlášení, pokud useCookies je trueparametr řetězce dotazu v koncovém bodu přihlášení .

Mapování Identity tras

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

app.MapIdentityApi<IdentityUser>();

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

K zabezpečení koncového bodu použijte metodu RequireAuthorization rozšíření pro Map{Method} volání, 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í deklarace identity 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.
  • Rozbalte zabezpečený koncový bod, například /weatherforecast v projektu vytvořeném šablonou 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 řetězec platnou e-mailovou adresou a heslem a pak vyberte 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
    • Nonalphanumeric character

    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 200 - OK odpověď.

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ší JSvlastnosti ON 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í způsobí 200 - OK odpověď s hlavičkou cookie 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 základě je bezpečně integrované v prohlížeči a "funguje".

Testování s využitím nepobrojených klientů

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

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

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

  • Spuštění HttpClient v Blazor WebAssembly aplikaci musí HttpRequestMessage obsahovat přihlašovací údaje, jako je následující příklad:

    request.SetBrowserRequestCredential(BrowserRequestCredentials.Include);
    

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

Pro klienty, kteří nepodporují cookiepřihlášení, poskytuje rozhraní API pro přihlášení parametr pro vyžádání tokenů. 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í JSna webových tokenech (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 cookie k možnosti pro klienty, kteří nemůžou používat 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 nosné ověřování. Použití tokenu vráceného z volání /login, následná volání chráněných koncových bodů by 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ý JSobjekt ON ({}) 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í pro MapIdentityApi<TUser> přidání následujících koncových bodů do aplikace:

Použití koncového POST /register bodu

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

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

Další informace naleznete v tématu:

Použití koncového POST /login bodu

V textu Email požadavku a Password jsou 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 truecookieověřování na základě. false Nastavte nebo vynecháte ověřování na základě tokenu.

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

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

Pokud useCookies je nebo je 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ž platnost přístupového tokenu brzy vyprší, zavolejte koncový bod /refresh .

Použití koncového POST /refresh bodu

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. Volání tohoto koncového bodu, když platnost přístupového tokenu brzy vyprší.

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žití koncového GET /confirmEmail bodu

Pokud Identity je nastavené potvrzení e-mailu, úspěšné volání koncového /register bodu odešle e-mail, který obsahuje odkaz na /confirmEmail koncový bod. 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.

Pokud chcete nastavit Identity potvrzení e-mailu, přidejte kódProgram.cs, do kterého chcete true nastavit RequireConfirmedEmail a přidat 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žití koncového POST /resendConfirmationEmail bodu

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žití koncového POST /forgotPassword bodu

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žití koncového POST /resetPassword bodu

Volání tohoto koncového bodu po získání kódu pro resetování voláním koncového /forgotPassword bodu

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

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

Použití koncového POST /manage/2fa bodu

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

Povolení 2FA

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

  • /manage/2fa Zavolejte koncový bod a v textu požadavku odešlete prázdný JSobjekt ON ({}).

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

  • /manage/2fa Zavolejte koncový bod, 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

/login Zavolejte koncový bod, odešlete e-mailovou adresu, heslo a HESLO v textu požadavku. 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"
}

Resetování kódů 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 s nastaveným 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ě", zavolejte tento koncový bod s nastaveným 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žití koncového GET /manage/info bodu

Získá e-mailovou adresu a stav potvrzení e-mailu přihlášeného uživatele. Deklarace identity z tohoto koncového bodu byly z bezpečnostních důvodů vynechány. 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 Email vlastnosti a IsEmailConfirmed vlastnosti, jak je znázorněno v následujícím příkladu:

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

Použití koncového POST /manage/info bodu

Aktualizace 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 Připojení.

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 5.0 na verzi 6.0.

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 (Razorstrá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ů je možné použít s angular i s oprávněními služby 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í přidání projektu, když je zahrnuta podpora ověřování:

Program.cs

Následující příklady kódu spoléhají na Microsoft.AspNetCore.ApiAuthorization.IdentityBalíček NuGet serveru Příklady nakonfigurují ověřování a autorizaci rozhraní API pomocí AddApiAuthorization metod a AddIdentityServerJwt rozšíření. 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á nastaví některé výchozí konvence jádra ASP.NET nad serverem Identity:

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

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

    app.UseAuthentication();
    
  • Middleware Identityserveru, který zveřejňuje koncové body OpenID Připojení:

    app.UseIdentityServer();
    

Aplikace Azure Service v Linuxu

Pro nasazení služby Aplikace Azure v Linuxu zadejte explicitně vystavitele:

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

V předchozím kódu {AUTHORITY} se Authority zástupný symbol používá při provádění volání OpenID Připojení.

Příklad:

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

AddApiAuthorization

Tato pomocná metoda konfiguruje Identityserver tak, aby používal 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 zpřístupňuje zbytečné složitosti pro nejběžnější scénáře. 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 ověřování změní, je plný výkon Identityserveru stále k dispozici pro přizpůsobení ověřování tak, aby vyhovoval 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. Zpracovává JwtBearerHandler všechny ostatní požadavky. Kromě toho tato metoda zaregistruje <<ApplicationName>>API prostředek rozhraní API se serverem Identitys výchozím oborem <<ApplicationName>>API a nakonfiguruje middleware nosného tokenu JWT tak, aby ověřil tokeny vydané serverem Identitypro 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í zásady autorizace se konfigurují tak, aby používaly výchozí schéma ověřování, které je nastavené podle AddIdentityServerJwt schématu zásad, které bylo uvedeno výše. Tato pomocná metoda tak JwtBearerHandler nakonfiguruje výchozí obslužnou rutinu pro požadavky na aplikaci.

ApplicationDbContext

Všimněte si, že se v Identity souboru používá totéž DbContext s výjimkou, že rozšiřuje ApiAuthorizationDbContext (odvozenější třídu zIdentityDbContext) tak, aby zahrnoval schéma pro IdentityServer.

Pokud chcete získat úplnou kontrolu nad schématem databáze, dědte z jedné z dostupných IdentityDbContext tříd a nakonfigurujte kontext tak, aby zahrnoval Identity schéma voláním builder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value) metody 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 odhlášení odkazů při ověření uživatele
      • Registrace a přihlášení odkazů, pokud uživatel není ověřený.
  • Ochrana AuthorizeGuard tras, která se dá přidat do tras a před návštěvou trasy vyžaduje ověření uživatele.
  • Zachycovač AuthorizeInterceptor HTTP, který připojí přístupový token k odchozím požadavkům HTTP, které cílí na rozhraní API při ověření uživatele.
  • Služba 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 ke spotřebě.
  • Modul Angular, který definuje trasy přidružené k ověřovacím částem aplikace. Zpřístupňuje komponentu nabídky přihlášení, průsečík, stráž a službu pro spotřebu ze zbytku 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 odhlášení odkazů při ověření uživatele
      • Registrace a přihlášení odkazů, pokud uživatel není ověř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 o procesu ověřování na nižší úrovni a zveřejňuje informace o ověřeném uživateli pro zbytek aplikace ke spotřebě.

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. K zajištění podpory autorizace AddIdentityServerJwt rozhraní API zaregistrujete 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 se obslužná rutina OnTokenValidated události nahradí vlastní implementací. Tato implementace:

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

Ochrana trasy na straně klienta (Angular)

Ochrana trasy na straně klienta se provádí přidáním autorizovaného stráže do seznamu stráží, které se mají spustit při konfiguraci trasy. Například můžete vidět, jak fetch-data je trasa nakonfigurovaná v rámci hlavního modulu Angular aplikace:

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 pomocí zachytávání klienta HTTP definovaného aplikací.

Ochrana trasy na straně klienta (React)

Chraňte trasu na straně klienta pomocí AuthorizeRoute komponenty místo prosté Route komponenty. Všimněte si fetch-data například konfigurace trasy v rámci App komponenty:

<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í ověřený.

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 žádosti a připojí se 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.

Import komponenty authService

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 pro ukládání uživatelských Identity účtů a Identityserveru uděluje.
  • 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 certifikát podepsaný svým držitelem nebo certifikát zřízený prostřednictvím autority 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í ze Identityserveru se sadou konvencí, výchozích hodnot a vylepšení, které zjednodušují prostředí spA. Bez nutnosti říci, ž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ě se Identityserverem jako jedinou jednotku.
    • Výchozí redirect_uri hodnota /authentication/login-callbackje .
    • Výchozí post_logout_redirect_uri hodnota /authentication/logout-callbackje .
    • 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í hostovaná se serverem Identity.
    • 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ě se serverem Identity.
    • Aplikace je nakonfigurovaná tak, aby měla jeden obor, který má výchozí název aplikace.
  • API: Představuje rozhraní API, které není hostované se serverem Identity.
    • 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 vlastnosti a post_logout_redirect_uri vlastnosti jednotlivých klientůredirect_uri, 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 a 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 se serverem Identity pro implementaci openID Připojení.

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 (Razorstrá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ů je možné použít s angular i s oprávněními služby 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í přidání projektu, když je zahrnuta podpora ověřování:

Třída Startup

Následující příklady kódu spoléhají na Microsoft.AspNetCore.ApiAuthorization.IdentityBalíček NuGet serveru Příklady nakonfigurují ověřování a autorizaci rozhraní API pomocí AddApiAuthorization metod a AddIdentityServerJwt rozšíření. 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á nastaví některé výchozí konvence jádra ASP.NET nad serverem Identity:

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

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

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

      app.UseAuthentication();
      
    • Middleware Identityserveru, který zveřejňuje koncové body OpenID Připojení:

      app.UseIdentityServer();
      

Aplikace Azure Service v Linuxu

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

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

V předchozím kódu {AUTHORITY} se Authority zástupný symbol používá při provádění volání OpenID Připojení.

Příklad:

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

AddApiAuthorization

Tato pomocná metoda konfiguruje Identityserver tak, aby používal 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 zpřístupňuje zbytečné složitosti pro nejběžnější scénáře. 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 ověřování změní, je plný výkon Identityserveru stále k dispozici pro přizpůsobení ověřování tak, aby vyhovoval 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. Zpracovává JwtBearerHandler všechny ostatní požadavky. Kromě toho tato metoda zaregistruje <<ApplicationName>>API prostředek rozhraní API se serverem Identitys výchozím oborem <<ApplicationName>>API a nakonfiguruje middleware nosného tokenu JWT tak, aby ověřil tokeny vydané serverem Identitypro 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í zásady autorizace se konfigurují tak, aby používaly výchozí schéma ověřování, které je nastavené podle AddIdentityServerJwt schématu zásad, které bylo uvedeno výše. Tato pomocná metoda tak JwtBearerHandler nakonfiguruje výchozí obslužnou rutinu pro požadavky na aplikaci.

ApplicationDbContext

Všimněte si, že se v Identity souboru používá totéž DbContext s výjimkou, že rozšiřuje ApiAuthorizationDbContext (odvozenější třídu zIdentityDbContext) tak, aby zahrnoval schéma pro IdentityServer.

Pokud chcete získat úplnou kontrolu nad schématem databáze, dědte z jedné z dostupných IdentityDbContext tříd a nakonfigurujte kontext tak, aby zahrnoval Identity schéma voláním builder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value) metody 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 odhlášení odkazů při ověření uživatele
      • Registrace a přihlášení odkazů, pokud uživatel není ověřený.
  • Ochrana AuthorizeGuard tras, která se dá přidat do tras a před návštěvou trasy vyžaduje ověření uživatele.
  • Zachycovač AuthorizeInterceptor HTTP, který připojí přístupový token k odchozím požadavkům HTTP, které cílí na rozhraní API při ověření uživatele.
  • Služba 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 ke spotřebě.
  • Modul Angular, který definuje trasy přidružené k ověřovacím částem aplikace. Zpřístupňuje komponentu nabídky přihlášení, průsečík, stráž a službu pro spotřebu ze zbytku 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 odhlášení odkazů při ověření uživatele
      • Registrace a přihlášení odkazů, pokud uživatel není ověř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 o procesu ověřování na nižší úrovni a zveřejňuje informace o ověřeném uživateli pro zbytek aplikace ke spotřebě.

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. K zajištění podpory autorizace AddIdentityServerJwt rozhraní API zaregistrujete 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 se obslužná rutina OnTokenValidated události nahradí vlastní implementací. Tato implementace:

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

Ochrana trasy na straně klienta (Angular)

Ochrana trasy na straně klienta se provádí přidáním autorizovaného stráže do seznamu stráží, které se mají spustit při konfiguraci trasy. Například můžete vidět, jak fetch-data je trasa nakonfigurovaná v rámci hlavního modulu Angular aplikace:

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 pomocí zachytávání klienta HTTP definovaného aplikací.

Ochrana trasy na straně klienta (React)

Chraňte trasu na straně klienta pomocí AuthorizeRoute komponenty místo prosté Route komponenty. Všimněte si fetch-data například konfigurace trasy v rámci App komponenty:

<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í ověřený.

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 žádosti a připojí se 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.

Import komponenty authService

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 pro ukládání uživatelských Identity účtů a Identityserveru uděluje.
  • 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 certifikát podepsaný svým držitelem nebo certifikát zřízený prostřednictvím autority 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í ze Identityserveru se sadou konvencí, výchozích hodnot a vylepšení, které zjednodušují prostředí spA. Bez nutnosti říci, ž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ě se Identityserverem jako jedinou jednotku.
    • Výchozí redirect_uri hodnota /authentication/login-callbackje .
    • Výchozí post_logout_redirect_uri hodnota /authentication/logout-callbackje .
    • 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í hostovaná se serverem Identity.
    • 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ě se serverem Identity.
    • Aplikace je nakonfigurovaná tak, aby měla jeden obor, který má výchozí název aplikace.
  • API: Představuje rozhraní API, které není hostované se serverem Identity.
    • 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 vlastnosti a post_logout_redirect_uri vlastnosti jednotlivých klientůredirect_uri, 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