Så här använder du Identity för att skydda en webb-API-serverdel för SPA:er
Obs
Det här är inte den senaste versionen av den här artikeln. Den aktuella versionen finns i den .NET 9-versionen av den här artikeln.
Varning
Den här versionen av ASP.NET Core stöds inte längre. Mer information finns i .NET och .NET Core Support Policy. Den aktuella versionen finns i .NET 9-versionen av den här artikeln.
Viktig
Den här informationen gäller en förhandsversionsprodukt som kan ändras avsevärt innan den släpps kommersiellt. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, med avseende på den information som tillhandahålls här.
För att se den aktuella versionen, se .NET 9-versionen av den här artikeln.
ASP.NET Core Identity tillhandahåller API:er som hanterar autentisering, auktorisering och identitetshantering. API:erna gör det möjligt att skydda slutpunkter för en webb-API-serverdel med cookie-baserad autentisering. Ett tokenbaserat alternativ är tillgängligt för klienter som inte kan använda cookies, men när du använder detta ansvarar du för att säkerställa att token hålls säkra. Vi rekommenderar att du använder cookies för webbläsarbaserade program, eftersom webbläsaren som standard hanterar dem automatiskt utan att exponera dem för JavaScript.
Den här artikeln visar hur du använder Identity för att skydda en webb-API-serverdel för SPA:er som Angular, React och Vue-appar. Samma serverdels-API:er kan användas för att skydda Blazor WebAssembly appar.
Förutsättningar
Stegen som visas i den här artikeln lägger till autentisering och auktorisering i en ASP.NET Core Web API-app som:
- Har inte redan konfigurerats för autentisering.
- Mål
net8.0
eller senare. - Kan vara antingen minimalt API eller kontrollantbaserat API.
Några av testinstruktionerna i den här artikeln använder Swagger-användargränssnittet som ingår i projektmallen. Swagger-användargränssnittet krävs inte för att använda Identity med en webb-API-backend.
Installera NuGet-paket
Installera följande NuGet-paket:
-
Microsoft.AspNetCore.Identity.EntityFrameworkCore
– Gör att Identity kan arbeta med Entity Framework Core (EF Core). - Ett som gör det möjligt för EF Core att arbeta med en databas, till exempel ett av följande paket:
Använd den minnesinterna databasen för att komma igång så snabbt som möjligt.
Ändra databasen senare till SQLite eller SQL Server för att spara användardata mellan sessioner vid testning eller för produktionsanvändning. Det ger en viss komplexitet jämfört med minnesintern, eftersom det kräver att databasen skapas via migreringar, som du ser i självstudiekursen EF Core komma igång.
Installera dessa paket med hjälp av NuGet-pakethanteraren i Visual Studio eller kommandot dotnet add package CLI.
Skapa en IdentityDbContext
Lägg till en klass med namnet ApplicationDbContext
som ärver från 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)
{ }
}
Koden som visas innehåller en särskild konstruktor som gör det möjligt att konfigurera databasen för olika miljöer.
Lägg till ett eller flera av följande using
direktiv efter behov när du lägger till koden som visas i de här stegen.
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
Konfigurera EF Core-kontexten
Som tidigare nämnts är det enklaste sättet att komma igång att använda minnesintern databas. Med minnesinternt börjar varje körning med en ny databas och du behöver inte använda migreringar. När anropet till WebApplication.CreateBuilder(args)
lägger du till följande kod för att konfigurera Identity att använda en minnesintern databas:
builder.Services.AddDbContext<ApplicationDbContext>(
options => options.UseInMemoryDatabase("AppDb"));
Om du vill spara användardata mellan sessioner vid testning eller för produktionsanvändning ändrar du databasen senare till SQLite eller SQL Server.
Lägga till Identity tjänster i containern
Efter anropet till WebApplication.CreateBuilder(args)
anropar du AddAuthorization för att lägga till tjänster i di-containern (dependency injection):
builder.Services.AddAuthorization();
Aktivera Identity API:er
Efter anropet till WebApplication.CreateBuilder(args)
anropar du AddIdentityApiEndpoints<TUser>(IServiceCollection) och AddEntityFrameworkStores<TContext>(IdentityBuilder).
builder.Services.AddIdentityApiEndpoints<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
Som standard aktiveras både cookies och egna token. Cookies och token utfärdas vid inloggning om frågesträngsparametern useCookies
i inloggningsslutpunkten är true
.
Kartlägg rutterna Identity
Efter anropet till builder.Build()
anropar du MapIdentityApi<TUser>(IEndpointRouteBuilder) för att mappa Identity slutpunkter:
app.MapIdentityApi<IdentityUser>();
Skydda valda slutpunkter
Om du vill skydda en slutpunkt använder du RequireAuthorization-tilläggsmetoden på Map{Method}
-anropet som definierar vägen. Till exempel:
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();
Metoden RequireAuthorization
kan också användas för att:
Skydda Swagger UI-slutpunkter, som du ser i följande exempel:
app.MapSwagger().RequireAuthorization();
Skydda med ett specifikt anspråk eller behörighet, som du ser i följande exempel:
.RequireAuthorization("Admin");
I ett kontrollantbaserat webb-API-projekt skyddar du slutpunkter genom att tillämpa attributet [Authorize
] på en kontrollant eller åtgärd.
Testa API:et
Ett snabbt sätt att testa autentisering är att använda den minnesinterna databasen och Swagger-användargränssnittet som ingår i projektmallen. Följande steg visar hur du testar API:et med Swagger-användargränssnittet. Kontrollera att slutpunkterna för Swagger-användargränssnittet inte är skyddade.
Försök att komma åt en säker slutpunkt
- Kör appen och navigera till Swagger-användargränssnittet.
- Expandera en skyddad slutpunkt, till exempel
/weatherforecast
i ett projekt som skapats av webb-API-mallen. - Välj Prova.
- Välj Kör. Svaret är
401 - not authorized
.
Testregistrering
Expandera
/register
och välj Prova.I avsnittet Parametrar i användargränssnittet visas ett exempel på begärandetext:
{ "email": "string", "password": "string" }
Ersätt "sträng" med en giltig e-postadress och ett giltigt lösenord och välj sedan Utför.
För att uppfylla standardreglerna för lösenordsverifiering måste lösenordet vara minst sex tecken långt och innehålla minst ett av följande tecken:
- Versal bokstav
- Gemener bokstav
- Siffra
- Icke-numeriskt tecken
Om du anger en ogiltig e-postadress eller ett felaktigt lösenord innehåller resultatet valideringsfelen. Här är ett exempel på en svarstext med valideringsfel:
{ "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')." ] } }
Felen returneras i ProblemDetails format så att klienten kan parsa dem och visa valideringsfel efter behov.
En lyckad registrering resulterar i ett
200 - OK
-svar.
Testinlogg
Expandera
/login
och välj Prova. Exempeltexten för begäran visar två ytterligare parametrar:{ "email": "string", "password": "string", "twoFactorCode": "string", "twoFactorRecoveryCode": "string" }
De extra JSON-egenskaperna behövs inte för det här exemplet och kan tas bort. Ange
useCookies
tilltrue
.Ersätt "text" med den e-postadress och det lösenord som du använde när du registrerade dig, och välj sedan Kör.
En lyckad inloggning resulterar i ett
200 - OK
svar med en cookie i svarshuvudet.
Testa den skyddade slutpunkten igen
Efter en lyckad inloggning kör du den skyddade slutpunkten igen. Autentiseringen cookie skickas automatiskt med begäran och slutpunkten är auktoriserad. Cookie-baserad autentisering är säkert inbyggd i webbläsaren och "fungerar bara".
Testa med nonbrowser-klienter
Vissa webbklienter kanske inte innehåller cookies i rubriken som standard:
Om du använder ett verktyg för att testa API:er kan du behöva aktivera cookies i inställningarna.
JavaScript-
fetch
API innehåller inte cookies som standard. Aktivera dem genom att angecredentials
till värdetinclude
i alternativen.En
HttpClient
som körs i en Blazor WebAssembly app behöverHttpRequestMessage
för att inkludera autentiseringsuppgifter, som i följande exempel:request.SetBrowserRequestCredential(BrowserRequestCredentials.Include);
Använda tokenbaserad autentisering
Vi rekommenderar att du använder cookies i webbläsarbaserade program eftersom webbläsaren som standard hanterar dem automatiskt utan att exponera dem för JavaScript.
En anpassad token (en som är skyddad för ASP.NET Core-identitetsplattformen) utfärdas som kan användas för att autentisera efterföljande begäranden. Token skickas i Authorization
-huvudet som en bärartoken. En uppdateringstoken tillhandahålls också. Med den här token kan programmet begära en ny token när den gamla upphör att gälla utan att tvinga användaren att logga in igen.
Tokenen är inte standard-JSON-webbtokens (JWT). Användningen av anpassade token är avsiktlig eftersom det inbyggda Identity-API:et främst är avsett för enkla scenarier. Tokenalternativet är inte avsett att vara en komplett identitetstjänstleverantör eller tokenserver, utan i stället ett alternativ till alternativet cookie för klienter som inte kan använda cookies.
Om du vill använda tokenbaserad autentisering anger du useCookies
frågesträngsparametern till false
när du anropar /login
slutpunkten. Tokens använder autentiseringsschemat för bärare . Med hjälp av token som returneras från anropet till /login
bör efterföljande anrop till skyddade slutpunkter lägga till headern Authorization: Bearer <token>
där <token>
är åtkomsttoken. Mer information finns i Använd POST /login
slutpunkten senare i den här artikeln.
Logga ut
Definiera en /logout
slutpunkt som i följande exempel för att ge användaren ett sätt att logga ut:
app.MapPost("/logout", async (SignInManager<IdentityUser> signInManager,
[FromBody] object empty) =>
{
if (empty != null)
{
await signInManager.SignOutAsync();
return Results.Ok();
}
return Results.Unauthorized();
})
.WithOpenApi()
.RequireAuthorization();
Ange ett tomt JSON-objekt ({}
) i begärandetexten när du anropar den här slutpunkten. Följande kod är ett exempel på ett anrop till utloggningsslutpunkten:
public signOut() {
return this.http.post('/logout', {}, {
withCredentials: true,
observe: 'response',
responseType: 'text'
Slutpunkterna för MapIdentityApi<TUser>
Anropet till MapIdentityApi<TUser>
lägger till följande slutpunkter i appen:
POST /register
POST /login
POST /refresh
GET /confirmEmail
POST /resendConfirmationEmail
POST /forgotPassword
POST /resetPassword
POST /manage/2fa
GET /manage/info
POST /manage/info
Använd POST /register
slutpunkten
Begärandetexten måste ha egenskaper för Email och Password:
{
"email": "string",
"password": "string",
}
Mer information finns i:
- Testregistrering som omtals tidigare i den här artikeln.
- RegisterRequest.
Använd POST /login
-slutpunkten
I begärandetexten krävs Email och Password. Om tvåfaktorautentisering (2FA) är aktiverat krävs antingen TwoFactorCode eller TwoFactorRecoveryCode. Om 2FA inte är aktiverat utelämnar du både twoFactorCode
och twoFactorRecoveryCode
. Mer information finns i Använd POST /manage/2fa
slutpunkten senare i den här artikeln.
Här är ett exempel på begärandetext med 2FA inte aktiverat:
{
"email": "string",
"password": "string"
}
Här är exempel på begärandetext med 2FA aktiverat:
-
{ "email": "string", "password": "string", "twoFactorCode": "string", }
-
{ "email": "string", "password": "string", "twoFactorRecoveryCode": "string" }
Slutpunkten förväntar sig en frågesträngsparameter:
-
useCookies
– Ange tilltrue
för cookie-baserad autentisering. Ange tillfalse
eller utelämna för tokenbaserad autentisering.
Mer information om cookie-baserad autentisering finns i Testa inloggning tidigare i den här artikeln.
Tokenbaserad autentisering
Om useCookies
är false
eller utelämnas aktiveras tokenbaserad autentisering. Svarstexten innehåller följande egenskaper:
{
"tokenType": "string",
"accessToken": "string",
"expiresIn": 0,
"refreshToken": "string"
}
Mer information om dessa egenskaper finns i AccessTokenResponse.
Placera åtkomsttoken i en rubrik för att göra autentiserade begäranden, enligt följande exempel
Authorization: Bearer {access token}
När åtkomsttoken snart upphör att gälla anropar du slutpunkten /refresh.
Använd POST /refresh
slutpunkten
Endast för användning med tokenbaserad autentisering. Hämtar en ny åtkomsttoken utan att tvinga användaren att logga in igen. Anropa den här slutpunkten när åtkomsttoken håller på att gå ut.
Begärandetexten innehåller endast RefreshToken. Här är ett exempel på begärandetext:
{
"refreshToken": "string"
}
Om anropet lyckas är svarstexten en ny AccessTokenResponse, som du ser i följande exempel:
{
"tokenType": "string",
"accessToken": "string",
"expiresIn": 0,
"refreshToken": "string"
}
Använd GET /confirmEmail
slutpunkten
Om Identity har konfigurerats för e-postbekräftelse skickar ett lyckat samtal till /register
-slutpunkten ett e-postmeddelande som innehåller en länk till /confirmEmail
slutpunkten. Länken innehåller följande frågesträngsparametrar:
userId
code
-
changedEmail
– Ingår endast om användaren ändrade e-postadressen under registreringen.
Identity innehåller standardtext för bekräftelsemeddelandet. Som standard är e-postämnet "Bekräfta din e-post" och e-posttexten ser ut som i följande exempel:
Please confirm your account by <a href='https://contoso.com/confirmEmail?userId={user ID}&code={generated code}&changedEmail={new email address}'>clicking here</a>.
Om egenskapen RequireConfirmedEmail är inställd på true
kan användaren inte logga in förrän e-postadressen har bekräftats genom att klicka på länken i e-postmeddelandet. Slutpunkten /confirmEmail
:
- Bekräftar e-postadressen och gör det möjligt för användaren att logga in.
- Returnerar texten "Tack för att du bekräftar din e-post." i svarstexten.
Om du vill konfigurera Identity för e-postbekräftelse lägger du till kod i Program.cs
för att ange RequireConfirmedEmail
till true
och lägga till en klass som implementerar IEmailSender i DI-containern. Till exempel:
builder.Services.Configure<IdentityOptions>(options =>
{
options.SignIn.RequireConfirmedEmail = true;
});
builder.Services.AddTransient<IEmailSender, EmailSender>();
Mer information finns i Kontobekräftelse och lösenordsåterställning i ASP.NET Core.
Identity innehåller standardtext för andra e-postmeddelanden som också måste skickas, till exempel för 2FA och lösenordsåterställning. Om du vill anpassa dessa e-postmeddelanden tillhandahåller du en anpassad implementering av IEmailSender
-gränssnittet. I föregående exempel är EmailSender
en klass som implementerar IEmailSender
. Mer information, inklusive ett exempel på en klass som implementerar IEmailSender
, finns i Kontobekräftelse och lösenordsåterställning i ASP.NET Core.
Använd POST /resendConfirmationEmail
slutpunkten
Skickar endast ett e-postmeddelande om adressen är giltig för en registrerad användare.
Begärandetexten innehåller endast Email. Här är ett exempel på begärandetext:
{
"email": "string"
}
Mer information finns i Använd GET /confirmEmail
slutpunkten tidigare i den här artikeln.
Använd POST /forgotPassword
slutpunkten
Genererar ett e-postmeddelande som innehåller en lösenordsåterställningskod. Skicka koden till /resetPassword
med ett nytt lösenord.
Begärandetexten innehåller endast Email. Här är ett exempel:
{
"email": "string"
}
Information om hur du aktiverar Identity för att skicka e-postmeddelanden finns i Använd GET /confirmEmail
-slutpunkten.
Använd POST /resetPassword
slutpunkten
Anropa den här slutpunkten när du har fått en återställningskod genom att anropa slutpunkten /forgotPassword
.
Begärandetexten kräver Email, ResetCodeoch NewPassword. Här är ett exempel:
{
"email": "string",
"resetCode": "string",
"newPassword": "string"
}
Använd POST /manage/2fa
slutpunkten
Konfigurerar tvåfaktorautentisering (2FA) för användaren. När 2FA är aktiverat kräver lyckad inloggning en kod som skapats av en autentiseringsapp utöver e-postadressen och lösenordet.
Aktivera 2FA
Så här aktiverar du 2FA för den autentiserade användaren:
Anropa
/manage/2fa
slutpunkten och skicka ett tomt JSON-objekt ({}
) i begärandetexten.Svarstexten innehåller SharedKey tillsammans med några andra egenskaper som inte behövs just nu. Den delade nyckeln används för att konfigurera autentiseringsappen. Exempel på svarstext:
{ "sharedKey": "string", "recoveryCodesLeft": 0, "recoveryCodes": null, "isTwoFactorEnabled": false, "isMachineRemembered": false }
Använd den delade nyckeln för att hämta ett tidsbaserat engångslösenord (TOTP). Mer information finns i Aktivera QR-kodgenerering för TOTP-autentiseringsappar i ASP.NET Core.
Anropa endpoint
/manage/2fa
och skicka TOTP och"enable": true
i begäran. Till exempel:{ "enable": true, "twoFactorCode": "string" }
Svarstexten bekräftar att IsTwoFactorEnabled är sant och ger RecoveryCodes. Återställningskoderna används för att logga in när autentiseringsappen inte är tillgänglig. Exempel på svarstext efter aktivering av 2FA:
{ "sharedKey": "string", "recoveryCodesLeft": 10, "recoveryCodes": [ "string", "string", "string", "string", "string", "string", "string", "string", "string", "string" ], "isTwoFactorEnabled": true, "isMachineRemembered": false }
Logga in med 2FA
Anropa /login
slutpunkten och skicka e-postadressen, lösenordet och TOTP i begärandetexten. Till exempel:
{
"email": "string",
"password": "string",
"twoFactorCode": "string"
}
Om användaren inte har åtkomst till autentiseringsappen loggar du in genom att anropa /login
slutpunkten med en av återställningskoderna som angavs när 2FA aktiverades. Begärandetexten ser ut som i följande exempel:
{
"email": "string",
"password": "string",
"twoFactorRecoveryCode": "string"
}
Återställa återställningskoderna
Om du vill hämta en ny samling återställningskoder anropar du den här slutpunkten med ResetRecoveryCodes inställd på true
. Här är ett exempel på begärandetext:
{
"resetRecoveryCodes": true
}
Återställa den delade nyckeln
Om du vill hämta en ny slumpmässig delad nyckel anropar du den här slutpunkten med ResetSharedKey inställd på true
. Här är ett exempel på begärandetext:
{
"resetSharedKey": true
}
Om du återställer nyckeln inaktiveras automatiskt kravet på tvåfaktorinloggning för den autentiserade användaren tills den återaktiveras av en senare begäran.
Glöm maskinen
Om du vill rensa cookie "kom ihåg mig-flaggan" om den är närvarande anropar du den här slutpunkten med ForgetMachine inställd till true. Här är ett exempel på begärandetext:
{
"forgetMachine": true
}
Den här slutpunkten påverkar inte tokenbaserad autentisering.
Använd slutpunkten GET /manage/info
Hämtar e-postadress och e-postbekräftelsestatus för den inloggade användaren. Anspråk utelämnades från den här slutpunkten av säkerhetsskäl. Om anspråk behövs använder du API:erna på serversidan för att konfigurera en slutpunkt för anspråk. Eller i stället för att dela alla användares anspråk anger du en valideringsslutpunkt som accepterar ett anspråk och svarar på om användaren har det.
Begäran kräver inga parametrar. Svarstexten innehåller egenskaperna Email och IsEmailConfirmed, som i följande exempel:
{
"email": "string",
"isEmailConfirmed": true
}
Använd POST /manage/info
slutpunkten
Uppdaterar e-postadressen och lösenordet för den inloggade användaren. Skicka NewEmail, NewPasswordoch OldPassword i begärandetexten, som du ser i följande exempel:
{
"newEmail": "string",
"newPassword": "string",
"oldPassword": "string"
}
Här är ett exempel på svarstexten:
{
"email": "string",
"isEmailConfirmed": false
}
Se även
Mer information finns i följande resurser:
- Välj en lösning för identitetshantering
- Identity hanteringslösningar för .NET-webbappar
- Enkel auktorisering i ASP.NET Core
- Lägg till, ladda ned och ta bort användardata till Identity i ett ASP.NET Core-projekt
- Skapa en ASP.NET Core-app med användardata som skyddas av auktorisering
- Kontobekräftelse och lösenordsåterställning i ASP.NET Core
- Aktivera QR-kodgenerering för TOTP-autentiseringsappar i ASP.NET Core
-
Exempelwebb-API-serverdelen för SPA:er .http-filen visar tokenbaserad autentisering. Till exempel:
- Anger inte
useCookies
- Använder Authorization-headern för att skicka en token
- Visar uppdatering för att utöka sessionen utan att tvinga användaren att logga in igen
- Anger inte
- Angular-exempelapp som använder Identity för att skydda en webb-API-serverdel
De ASP.NET Core-mallarna erbjuder autentisering för ensidesapplikationer (SPA) med stödet för API-auktorisering. ASP.NET Core Identity för autentisering och lagring av användare kombineras med Duende Identity Server för implementering av OpenID Connect.
Viktig
Duende Software kan kräva att du betalar en licensavgift för produktionsanvändning av Duende Identity Server. Mer information finns i Migrera från ASP.NET Core 5.0 till 6.0.
En autentiseringsparameter lades till i projektmallarna Angular och React som liknar autentiseringsparametern i projektmallarna Web Application (Model-View-Controller) (MVC) och Web Application (Razor Pages). De tillåtna parametervärdena är None och Individual. Projektmallen React.js och Redux stöder för närvarande inte autentiseringsparametern.
Skapa en app med API-auktoriseringsstöd
Användarautentisering och auktorisering kan användas med både Angular och React SPA. Öppna ett kommandogränssnitt och kör följande kommando:
Angular:
dotnet new angular -au Individual
React:
dotnet new react -au Individual
Föregående kommando skapar en ASP.NET Core-app med en ClientApp- katalog som innehåller SPA.
Allmän beskrivning av appens ASP.NET Core-komponenter
I följande avsnitt beskrivs tillägg till projektet när autentiseringsstöd ingår:
Program.cs
Följande kodexempel förlitar sig på Microsoft.AspNetCore.ApiAuthorization.IdentityServer NuGet-paketet. Exemplen konfigurerar API-autentisering och auktorisering med hjälp av AddApiAuthorization och AddIdentityServerJwt tilläggsmetoder. Projekt som använder React- eller Angular SPA-projektmallar med autentisering innehåller en referens till det här paketet.
dotnet new angular -au Individual
genererar följande Program.cs
-fil:
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();
Föregående kod konfigurerar:
Identity med standardgränssnittet:
builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlite(connectionString)); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<ApplicationDbContext>();
IdentityServer med ytterligare en
AddApiAuthorization
hjälpmetod som konfigurerar vissa standardkonventioner för ASP.NET Core ovanpå IdentityServer:builder.Services.AddIdentityServer() .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
Autentisering med ytterligare en
AddIdentityServerJwt
hjälpmetod som konfigurerar appen för att verifiera JWT-token som skapats av IdentityServer:builder.Services.AddAuthentication() .AddIdentityServerJwt();
Mellanprogrammet för autentisering som ansvarar för att verifiera autentiseringsuppgifterna för begäran och ange användaren i begärandekontexten:
app.UseAuthentication();
IdentityServer-mellanprogrammet som exponerar OpenID Connect-slutpunkterna:
app.UseIdentityServer();
Varning
Den här artikeln visar användningen av anslutningssträngar. Med en lokal databas behöver användaren inte autentiseras, men i produktion innehåller anslutningssträngar ibland ett lösenord för att autentisera. En resursägares lösenordsautentiseringsuppgifter (ROPC) är en säkerhetsrisk som bör undvikas i produktionsdatabaser. Produktionsappar bör använda det säkraste tillgängliga autentiseringsflödet. Mer information om autentisering för appar som distribueras till test- eller produktionsmiljöer finns i Säkra autentiseringsflöden.
Azure App Service i Linux
För Azure App Service-distributioner i Linux anger du utfärdaren explicit:
builder.Services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
options.Authority = "{AUTHORITY}";
});
I föregående kod är platshållaren {AUTHORITY}
den Authority att använda när du gör OpenID Connect-anrop.
Exempel:
options.Authority = "https://contoso-service.azurewebsites.net";
AddApiAuthorization
Den här hjälpmetoden konfigurerar IdentityServer för att använda vår konfiguration som stöds. IdentityServer är ett kraftfullt och utökningsbart ramverk för hantering av appsäkerhetsproblem. Samtidigt exponerar det onödig komplexitet för de vanligaste scenarierna. Därför tillhandahålls en uppsättning konventioner och konfigurationsalternativ till dig som anses vara en bra utgångspunkt. När autentiseringen behöver ändras är den fulla kraften i IdentityServer fortfarande tillgänglig för att anpassa autentiseringen efter dina behov.
AddIdentityServerJwt
Den här hjälpmetoden konfigurerar ett principschema för appen som standardautentiseringshanterare. Policyn har konfigurerats för att låta Identity hantera alla begäranden som dirigeras till en delstig i Identity URL-utrymmet "/Identity".
JwtBearerHandler
hanterar alla andra begäranden. Dessutom registrerar den här metoden en <<ApplicationName>>API
API-resurs med IdentityServer med standardomfånget <<ApplicationName>>API
och konfigurerar mellanprogrammet för JWT Bearer-token för att verifiera token som utfärdats av IdentityServer för appen.
WeatherForecastController
Observera det [Authorize]
attribut som tillämpas på klassen i filen som anger att användaren måste auktoriseras baserat på standardprincipen för att få åtkomst till resursen. Standardauktoriseringsprincipen råkar vara konfigurerad för att använda standardautentiseringsschemat, som konfigureras av AddIdentityServerJwt
till det principschema som nämndes ovan, vilket gör JwtBearerHandler
som konfigurerats med den här hjälpmetoden till standardhanteraren för begäranden till appen.
ApplicationDbContext
Observera att samma DbContext
används i Identity i filen, med undantag för att den utökar ApiAuthorizationDbContext
(en mer härledd klass från IdentityDbContext
) för att inkludera schemat för IdentityServer.
Om du vill få fullständig kontroll över databasschemat ärver du från någon av de tillgängliga IdentityDbContext
klasserna och konfigurerar kontexten så att den inkluderar Identity-schemat genom att anropa builder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value)
på OnModelCreating
-metoden.
OidcConfigurationController
Observera den slutpunkt i filen som har etablerats för att hantera de OIDC-parametrar som klienten behöver använda.
appsettings.json
I den appsettings.json
filen i projektroten finns det ett nytt IdentityServer
avsnitt som beskriver listan över konfigurerade klienter. I följande exempel finns det en enda klient. Klientnamnet motsvarar appnamnet och mappas enligt konventionen till parametern OAuth ClientId
. Profilen anger vilken apptyp som konfigureras. Den används internt för att driva konventioner som förenklar konfigurationsprocessen för servern. Det finns flera tillgängliga profiler, enligt beskrivningen i avsnittet Programprofiler.
"IdentityServer": {
"Clients": {
"angularindividualpreview3final": {
"Profile": "IdentityServerSPA"
}
}
}
appsettings.Development.json
I appsettings.Development.json
-filen i projektroten finns det ett IdentityServer
-avsnitt som beskriver nyckeln som används för att signera token. När du distribuerar till produktion måste en nyckel etableras och distribueras tillsammans med appen, enligt beskrivningen i avsnittet Distribuera till produktion.
"IdentityServer": {
"Key": {
"Type": "Development"
}
}
Allmän beskrivning av Angular-appen
Stöd för autentisering och API-auktorisering i Angular-mallen finns i en egen Angular-modul i katalogen ClientApp/src/api-authorization. Modulen består av följande element:
- 3 komponenter:
-
login.component.ts
: Hanterar appens inloggningsflöde. -
logout.component.ts
: Hanterar appens utloggningsflöde. -
login-menu.component.ts
: En widget som visar en av följande uppsättningar länkar:- Användarprofilhantering och utloggningslänkar när användaren autentiseras.
- Registrerings- och inloggningslänkar när användaren inte autentiseras.
-
- Ett ruttsskydd
AuthorizeGuard
som kan läggas till rutter och kräver att en användare autentiseras innan de besöker rutterna. - En HTTP-interceptor
AuthorizeInterceptor
som kopplar åtkomsttoken till utgående HTTP-begäranden som riktas mot API:et när användaren autentiseras. - En tjänst
AuthorizeService
som hanterar information på lägre nivå i autentiseringsprocessen och exponerar information om den autentiserade användaren för resten av appen för förbrukning. - En Angular-modul som definierar vägar som är associerade med appens autentiseringsdelar. Den exponerar komponenten för inloggningsmenyn, interceptorn, skyddet och tjänsten för användning från resten av appen.
Allmän beskrivning av React-appen
Stödet för autentisering och API-auktorisering i React-mallen finns i katalogen ClientApp/src/components/api-authorization. Den består av följande element:
- 4 komponenter:
-
Login.js
: Hanterar appens inloggningsflöde. -
Logout.js
: Hanterar appens utloggningsflöde. -
LoginMenu.js
: En widget som visar en av följande uppsättningar länkar:- Användarprofilhantering och utloggningslänkar när användaren autentiseras.
- Registrerings- och inloggningslänkar när användaren inte autentiseras.
-
AuthorizeRoute.js
: En ruttkomponent som kräver att en användare autentiseras innan den komponent som anges i parameternComponent
återges.
-
- En exporterad
authService
instans av klassAuthorizeService
som hanterar information på lägre nivå om autentiseringsprocessen och exponerar information om den autentiserade användaren för resten av appen för förbrukning.
Nu när du har sett huvudkomponenterna i lösningen kan du titta närmare på enskilda scenarier för appen.
Kräv auktorisering för ett nytt API
Som standard är systemet konfigurerat för att enkelt kräva auktorisering för nya API:er. För att göra det skapar du en ny kontrollant och lägger till attributet [Authorize]
till kontrollantklassen eller till någon åtgärd i kontrollanten.
Anpassa API-autentiseringshanteraren
Om du vill anpassa konfigurationen av API:ets JWT-hanterare konfigurerar du dess JwtBearerOptions-instans:
builder.Services.AddAuthentication()
.AddIdentityServerJwt();
builder.Services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
...
});
API:ets JWT-hanterare genererar händelser som aktiverar kontroll över autentiseringsprocessen med hjälp av JwtBearerEvents
. För att ge stöd för API-auktorisering registrerar AddIdentityServerJwt
sina egna händelsehanterare.
Om du vill anpassa hanteringen av en händelse omsluter du den befintliga händelsehanteraren med ytterligare logik efter behov. Till exempel:
builder.Services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
var onTokenValidated = options.Events.OnTokenValidated;
options.Events.OnTokenValidated = async context =>
{
await onTokenValidated(context);
...
}
});
I föregående kod ersätts OnTokenValidated
händelsehanteraren med en anpassad implementering. Den här implementeringen:
- Anropar den ursprungliga implementeringen som tillhandahålls av API-auktoriseringssupporten.
- Kör sin egen anpassade logik.
Skydda en väg på klientsidan (Angular)
Att skydda en väg på klientsidan görs genom att lägga till auktorisera skyddet i listan över skyddsåtgärder som ska köras när du konfigurerar en väg. Du kan till exempel se hur rutten fetch-data
är konfigurerad i huvudapplikationens Angular-modul.
RouterModule.forRoot([
// ...
{ path: 'fetch-data', component: FetchDataComponent, canActivate: [AuthorizeGuard] },
])
Det är viktigt att nämna att skyddet av en väg inte skyddar den faktiska slutpunkten (som fortfarande kräver ett [Authorize]
attribut som tillämpas på den) men att det bara hindrar användaren från att navigera till den angivna vägen på klientsidan när den inte autentiseras.
Autentisera API-begäranden (Angular)
Autentisering av begäranden till API:er som hostade tillsammans med appen görs automatiskt med hjälp av HTTP-klientavlyssnaren som definieras av appen.
Skydda en väg på klientsidan (React)
Skydda en väg på klientsidan med hjälp av komponenten AuthorizeRoute
i stället för den vanliga Route
komponenten. Observera till exempel hur den fetch-data
vägen konfigureras i komponenten App
:
<AuthorizeRoute path='/fetch-data' component={FetchData} />
Skydda en väg:
- Skyddar inte den faktiska slutpunkten (som fortfarande kräver ett
[Authorize]
attribut som tillämpas på den). - Hindrar endast användaren från att navigera till den angivna vägen på klientsidan när den inte autentiseras.
Autentisera API-begäranden (React)
Autentisera begäranden med React görs genom att först importera authService
-instansen från AuthorizeService
. Åtkomsttoken hämtas från authService
och är kopplad till begäran enligt nedan. I React-komponenter utförs det här arbetet vanligtvis i componentDidMount
livscykelmetod eller som ett resultat av viss användarinteraktion.
Importera authService
till en komponent
import authService from './api-authorization/AuthorizeService'
Hämta och koppla åtkomsttoken till svaret
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 });
}
Distribuera till produktion
För att distribuera appen till produktion måste följande resurser etableras:
- En databas för lagring av Identity användarkonton och IdentityServer-tillstånd.
- Ett produktionscertifikat som ska användas för signering av token.
- Det finns inga specifika krav för det här certifikatet. Det kan vara ett självsignerat certifikat eller ett certifikat som etablerats via en certifikatutfärdare.
- Det kan genereras via standardverktyg som PowerShell eller OpenSSL.
- Den kan installeras i certifikatarkivet på måldatorerna eller distribueras som en .pfx- fil med ett starkt lösenord.
Exempel: Distribuera till en icke-Azure-webbvärdleverantör
Skapa eller läs in certifikatet i webbvärdpanelen. I appens appsettings.json
-fil ändrar du sedan avsnittet IdentityServer
så att den innehåller nyckelinformationen. Till exempel:
"IdentityServer": {
"Key": {
"Type": "Store",
"StoreName": "WebHosting",
"StoreLocation": "CurrentUser",
"Name": "CN=MyApplication"
}
}
I föregående exempel:
-
StoreName
representerar namnet på certifikatarkivet där certifikatet lagras. I det här fallet pekar den på webbutiken. -
StoreLocation
representerar var certifikatet ska läsas in från (CurrentUser
i det här fallet). -
Name
motsvarar certifikatets unika ämne.
Exempel: Distribuera till Azure App Service
I det här avsnittet beskrivs hur du distribuerar appen till Azure App Service med hjälp av ett certifikat som lagras i certifikatarkivet. Om du vill ändra appen så att den läser in ett certifikat från certifikatarkivet krävs en tjänstplan på standardnivå eller bättre när du konfigurerar appen i Azure-portalen i ett senare steg.
I appens appsettings.json
-fil ändrar du avsnittet IdentityServer
så att den innehåller nyckelinformationen:
"IdentityServer": {
"Key": {
"Type": "Store",
"StoreName": "My",
"StoreLocation": "CurrentUser",
"Name": "CN=MyApplication"
}
}
- Butiksnamnet representerar namnet på certifikatarkivet där certifikatet lagras. I det här fallet pekar den på den personliga användarlagringen.
- Lagringsplatsen representerar var certifikatet ska läsas in från (
CurrentUser
ellerLocalMachine
). - Namnegenskapen på certifikatet motsvarar certifikatets unika ämne.
Om du vill distribuera till Azure App Service följer du stegen i Distribuera appen till Azure, som förklarar hur du skapar nödvändiga Azure-resurser och distribuerar appen till produktion.
När du har följt föregående instruktioner distribueras appen till Azure men fungerar ännu inte. Certifikatet som används av appen måste konfigureras i Azure-portalen. Leta upp tumavtrycket för certifikatet och följ stegen som beskrivs i Läs in dina certifikat.
De här stegen nämner SSL, men det finns ett privata certifikat i Azure-portalen där du kan ladda upp det etablerade certifikatet som ska användas med appen.
När du har konfigurerat appen och appens inställningar i Azure-portalen startar du om appen i portalen.
Andra konfigurationsalternativ
Stödet för API-auktorisering bygger ovanpå IdentityServer med en uppsättning konventioner, standardvärden och förbättringar för att förenkla upplevelsen för SPA:er. Naturligtvis är den fulla kraften i IdentityServer tillgänglig i bakgrunden om ASP.NET Core-integreringarna inte täcker ditt scenario. Stödet för ASP.NET Core fokuserar på appar från första part, där alla appar skapas och distribueras av vår organisation. Därför erbjuds inte stöd för sådant som medgivande eller federation. I dessa scenarier använder du IdentityServer och följer deras dokumentation.
Programprofiler
Programprofiler är fördefinierade konfigurationer för appar som ytterligare definierar sina parametrar. För närvarande stöds följande profiler:
-
IdentityServerSPA
: Representerar ett SPA som hanteras tillsammans med IdentityServer som en enda enhet.- Standardvärdet för
redirect_uri
är/authentication/login-callback
. - Standardinställningen för
post_logout_redirect_uri
är/authentication/logout-callback
. - Uppsättningen med omfång innehåller
openid
,profile
och varje omfång som definierats för API:erna i appen. - Uppsättningen tillåtna OIDC-svarstyper är
id_token token
eller var och en av dem individuellt (id_token
,token
). - Det tillåtna svarsläget är
fragment
.
- Standardvärdet för
-
SPA
: Representerar ett SPA som inte är hostat med IdentityServer.- Uppsättningen med omfång innehåller
openid
,profile
och varje omfång som definierats för API:erna i appen. - Uppsättningen tillåtna OIDC-svarstyper är
id_token token
eller var och en av dem individuellt (id_token
,token
). - Det tillåtna svarsläget är
fragment
.
- Uppsättningen med omfång innehåller
-
IdentityServerJwt
: Representerar ett API som finns tillsammans med IdentityServer.- Appen är konfigurerad för att ha ett enda omfång som är standard för appnamnet.
-
API
: Representerar ett API som inte finns med IdentityServer.- Appen är konfigurerad för att ha ett enda omfång som är standard för appnamnet.
Konfiguration via AppSettings
Konfigurera apparna via konfigurationssystemet genom att lägga till dem i listan över Clients
eller Resources
.
Konfigurera varje klients egenskap redirect_uri
och post_logout_redirect_uri
enligt följande exempel:
"IdentityServer": {
"Clients": {
"MySPA": {
"Profile": "SPA",
"RedirectUri": "https://www.example.com/authentication/login-callback",
"LogoutUri": "https://www.example.com/authentication/logout-callback"
}
}
}
När du konfigurerar resurser kan du konfigurera resursens omfång enligt nedan:
"IdentityServer": {
"Resources": {
"MyExternalApi": {
"Profile": "API",
"Scopes": "a b c"
}
}
}
Konfiguration via kod
Du kan också konfigurera klienter och resurser via kod med hjälp av en överlagring av AddApiAuthorization
som vidtar en åtgärd för att konfigurera alternativ.
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"));
});
Ytterligare resurser
Mallarna i ASP.NET Core 3.1 och senare erbjuder autentisering för SPAs med stöd för API-auktorisering. ASP.NET Core Identity för autentisering och lagring av användare kombineras med IdentityServer- för implementering av OpenID Connect.
En autentiseringsparameter lades till i projektmallarna Angular och React som liknar autentiseringsparametern i projektmallarna Web Application (Model-View-Controller) (MVC) och Web Application (Razor Pages). De tillåtna parametervärdena är None och Individual. Projektmallen React.js och Redux stöder för närvarande inte autentiseringsparametern.
Skapa en app med API-auktoriseringsstöd
Användarautentisering och auktorisering kan användas med både Angular och React SPA. Öppna ett kommandogränssnitt och kör följande kommando:
Angular:
dotnet new angular -o <output_directory_name>
React:
dotnet new react -o <output_directory_name> -au Individual
Föregående kommando skapar en ASP.NET Core-app med en ClientApp- katalog som innehåller SPA.
Allmän beskrivning av appens ASP.NET Core-komponenter
I följande avsnitt beskrivs tillägg till projektet när autentiseringsstöd ingår:
Startup
klass
Följande kodexempel förlitar sig på Microsoft.AspNetCore.ApiAuthorization.IdentityServer NuGet-paketet. Exemplen konfigurerar API-autentisering och auktorisering med hjälp av AddApiAuthorization och AddIdentityServerJwt tilläggsmetoder. Projekt som använder React- eller Angular SPA-projektmallar med autentisering innehåller en referens till det här paketet.
Klassen Startup
har följande tillägg:
I metoden
Startup.ConfigureServices
:Identity med standardgränssnittet:
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlite(Configuration.GetConnectionString("DefaultConnection"))); services.AddDefaultIdentity<ApplicationUser>() .AddEntityFrameworkStores<ApplicationDbContext>();
IdentityServer med ytterligare en
AddApiAuthorization
hjälpmetod som konfigurerar vissa standardkonventioner för ASP.NET Core ovanpå IdentityServer:services.AddIdentityServer() .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
Autentisering med ytterligare en
AddIdentityServerJwt
hjälpmetod som konfigurerar appen för att verifiera JWT-token som skapats av IdentityServer:services.AddAuthentication() .AddIdentityServerJwt();
Inuti i metoden
Startup.Configure
:Mellanprogrammet för autentisering som ansvarar för att verifiera autentiseringsuppgifterna för begäran och ange användaren i begärandekontexten:
app.UseAuthentication();
IdentityServer-mellanprogrammet som exponerar OpenID Connect-slutpunkterna:
app.UseIdentityServer();
Varning
Den här artikeln visar användningen av anslutningssträngar. Med en lokal databas behöver användaren inte autentiseras, men i produktion innehåller anslutningssträngar ibland ett lösenord för att autentisera. En resursägares lösenordsautentiseringsuppgifter (ROPC) är en säkerhetsrisk som bör undvikas i produktionsdatabaser. Produktionsappar bör använda det säkraste tillgängliga autentiseringsflödet. Mer information om autentisering för appar som distribueras till test- eller produktionsmiljöer finns i Säkra autentiseringsflöden.
Azure App Service i Linux
För Azure App Service-distributioner i Linux anger du utfärdaren explicit i Startup.ConfigureServices
:
services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
options.Authority = "{AUTHORITY}";
});
I föregående kod är platshållaren {AUTHORITY}
den Authority som används när OpenID Connect-anrop görs.
Exempel:
options.Authority = "https://contoso-service.azurewebsites.net";
AddApiAuthorization
Den här hjälpmetoden konfigurerar IdentityServer för att använda vår konfiguration som stöds. IdentityServer är ett kraftfullt och utökningsbart ramverk för hantering av appsäkerhetsproblem. Samtidigt exponerar det onödig komplexitet för de vanligaste scenarierna. Därför tillhandahålls en uppsättning konventioner och konfigurationsalternativ till dig som anses vara en bra utgångspunkt. När autentiseringen behöver ändras är den fulla kraften i IdentityServer fortfarande tillgänglig för att anpassa autentiseringen efter dina behov.
AddIdentityServerJwt
Den här hjälpmetoden konfigurerar ett principschema för appen som standardautentiseringshanterare. Policyn har konfigurerats för att låta Identity hantera alla begäranden som dirigeras till en undermapp i Identity:s URL-utrymme "/Identity".
JwtBearerHandler
hanterar alla andra begäranden. Dessutom registrerar den här metoden en <<ApplicationName>>API
API-resurs med IdentityServer med standardomfånget <<ApplicationName>>API
och konfigurerar mellanprogrammet för JWT Bearer-token för att verifiera token som utfärdats av IdentityServer för appen.
WeatherForecastController
Observera det [Authorize]
attribut som tillämpas på klassen i filen som anger att användaren måste auktoriseras baserat på standardprincipen för att få åtkomst till resursen. Standardauktoriseringsprincipen råkar vara konfigurerad för att använda standardautentiseringsschemat, som konfigureras av AddIdentityServerJwt
till det principschema som nämndes ovan, vilket gör JwtBearerHandler
som konfigurerats med den här hjälpmetoden till standardhanteraren för begäranden till appen.
ApplicationDbContext
Observera att samma DbContext
används i Identity i filen, med undantag för att den utökar ApiAuthorizationDbContext
(en mer härledd klass från IdentityDbContext
) för att inkludera schemat för IdentityServer.
Om du vill få fullständig kontroll över databasschemat ärver du från någon av de tillgängliga IdentityDbContext
klasserna och konfigurerar kontexten så att den inkluderar Identity-schemat genom att anropa builder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value)
på OnModelCreating
-metoden.
OidcConfigurationController
Observera den slutpunkt i filen som har etablerats för att hantera de OIDC-parametrar som klienten behöver använda.
appsettings.json
I den appsettings.json
filen i projektroten finns det ett nytt IdentityServer
avsnitt som beskriver listan över konfigurerade klienter. I följande exempel finns det en enda klient. Klientnamnet motsvarar appnamnet och mappas enligt konventionen till parametern OAuth ClientId
. Profilen anger vilken apptyp som konfigureras. Den används internt för att driva konventioner som förenklar konfigurationsprocessen för servern. Det finns flera tillgängliga profiler, enligt beskrivningen i avsnittet Programprofiler.
"IdentityServer": {
"Clients": {
"angularindividualpreview3final": {
"Profile": "IdentityServerSPA"
}
}
}
appsettings.Development.json
I appsettings.Development.json
-filen i projektroten finns det en IdentityServer
-sektion som beskriver nyckeln som används för att signera tokenen. När du distribuerar till produktion måste en nyckel etableras och distribueras tillsammans med appen, enligt beskrivningen i avsnittet Distribuera till produktion.
"IdentityServer": {
"Key": {
"Type": "Development"
}
}
Allmän beskrivning av Angular-appen
Stöd för autentisering och API-auktorisering i Angular-mallen finns i en egen Angular-modul i katalogen ClientApp/src/api-authorization. Modulen består av följande element:
- 3 komponenter:
-
login.component.ts
: Hanterar appens inloggningsflöde. -
logout.component.ts
: Hanterar appens utloggningsflöde. -
login-menu.component.ts
: En widget som visar en av följande uppsättningar länkar:- Användarprofilhantering och utloggningslänkar när användaren autentiseras.
- Registrerings- och inloggningslänkar när användaren inte autentiseras.
-
- Ett vägskydd
AuthorizeGuard
som kan läggas till i vägar och kräver att en användare autentiseras innan den besöker vägen. - En HTTP-interceptor
AuthorizeInterceptor
som kopplar åtkomsttoken till utgående HTTP-begäranden som riktas mot API:et när användaren autentiseras. - En tjänst
AuthorizeService
som hanterar information på lägre nivå i autentiseringsprocessen och exponerar information om den autentiserade användaren för resten av appen för förbrukning. - En Angular-modul som definierar vägar som är associerade med appens autentiseringsdelar. Den exponerar komponenten för inloggningsmenyn, interceptorn, skyddet och tjänsten för användning från resten av appen.
Allmän beskrivning av React-appen
Stödet för autentisering och API-auktorisering i React-mallen finns i katalogen ClientApp/src/components/api-authorization. Den består av följande element:
- 4 komponenter:
-
Login.js
: Hanterar appens inloggningsflöde. -
Logout.js
: Hanterar appens utloggningsflöde. -
LoginMenu.js
: En widget som visar en av följande uppsättningar länkar:- Användarprofilhantering och utloggningslänkar när användaren autentiseras.
- Registrerings- och inloggningslänkar när användaren inte autentiseras.
-
AuthorizeRoute.js
: En ruttkomponent som kräver att en användare är autentiserad innan komponenten återges som anges i parameternComponent
.
-
- En exporterad
authService
instans av klassAuthorizeService
som hanterar information på lägre nivå om autentiseringsprocessen och exponerar information om den autentiserade användaren för resten av appen för förbrukning.
Nu när du har sett huvudkomponenterna i lösningen kan du titta närmare på enskilda scenarier för appen.
Kräv auktorisering för ett nytt API
Som standard är systemet konfigurerat för att enkelt kräva auktorisering för nya API:er. För att göra det skapar du en ny kontrollant och lägger till attributet [Authorize]
till kontrollantklassen eller till någon åtgärd i kontrollanten.
Anpassa API-autentiseringshanteraren
Om du vill anpassa konfigurationen av API:ets JWT-hanterare konfigurerar du dess JwtBearerOptions-instans:
services.AddAuthentication()
.AddIdentityServerJwt();
services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
...
});
API:ets JWT-hanterare genererar händelser som aktiverar kontroll över autentiseringsprocessen med hjälp av JwtBearerEvents
. För att ge stöd för API-auktorisering registrerar AddIdentityServerJwt
sina egna händelsehanterare.
Om du vill anpassa hanteringen av en händelse omsluter du den befintliga händelsehanteraren med ytterligare logik efter behov. Till exempel:
services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
var onTokenValidated = options.Events.OnTokenValidated;
options.Events.OnTokenValidated = async context =>
{
await onTokenValidated(context);
...
}
});
I föregående kod ersätts OnTokenValidated
händelsehanteraren med en anpassad implementering. Den här implementeringen:
- Anropar den ursprungliga implementeringen som tillhandahålls av API-auktoriseringssupporten.
- Kör sin egen anpassade logik.
Skydda en väg på klientsidan (Angular)
Att skydda en väg på klientsidan görs genom att lägga till auktorisera skyddet i listan över skyddsåtgärder som ska köras när du konfigurerar en väg. Till exempel kan du se hur rutten fetch-data
är konfigurerad inom huvudapplikationens Angular-modul.
RouterModule.forRoot([
// ...
{ path: 'fetch-data', component: FetchDataComponent, canActivate: [AuthorizeGuard] },
])
Det är viktigt att nämna att skyddet av en väg inte skyddar den faktiska slutpunkten (som fortfarande kräver ett [Authorize]
attribut som tillämpas på den) men att det bara hindrar användaren från att navigera till den angivna vägen på klientsidan när den inte autentiseras.
Autentisera API-begäranden (Angular)
Autentisering av förfrågningar till API:er som finns tillsammans med appen sker automatiskt genom användning av HTTP-klientens avlyssningsfunktion som definierats av appen.
Skydda en väg på klientsidan (React)
Skydda en väg på klientsidan med hjälp av komponenten AuthorizeRoute
i stället för den vanliga Route
komponenten. Observera till exempel hur den fetch-data
vägen konfigureras i komponenten App
:
<AuthorizeRoute path='/fetch-data' component={FetchData} />
Skydda en väg:
- Skyddar inte den faktiska slutpunkten (som fortfarande kräver ett
[Authorize]
attribut som tillämpas på den). - Hindrar endast användaren från att navigera till den angivna vägen på klientsidan när den inte autentiseras.
Autentisera API-begäranden (React)
Autentisera begäranden med React görs genom att först importera authService
-instansen från AuthorizeService
. Åtkomsttoken hämtas från authService
och är kopplad till begäran enligt nedan. I React-komponenter utförs det här arbetet vanligtvis i componentDidMount
livscykelmetod eller som ett resultat av viss användarinteraktion.
Importera authService
till en komponent
import authService from './api-authorization/AuthorizeService'
Hämta och koppla åtkomsttoken till svaret
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 });
}
Driftsätta i produktion
För att distribuera appen till produktion måste följande resurser etableras:
- En databas för att lagra användarkonton för Identity och tillstånd från IdentityServer.
- Ett produktionscertifikat för att användas vid signering av token.
- Det finns inga specifika krav för det här certifikatet. Det kan vara ett självsignerat certifikat eller ett certifikat som etablerats via en certifikatutfärdare.
- Det kan genereras via standardverktyg som PowerShell eller OpenSSL.
- Den kan installeras i certifikatarkivet på måldatorerna eller distribueras som en .pfx- fil med ett starkt lösenord.
Exempel: Distribuera till en icke-Azure-webbvärdleverantör
Skapa eller läs in certifikatet i webbvärdpanelen. I appens appsettings.json
-fil ändrar du sedan avsnittet IdentityServer
så att den innehåller nyckelinformationen. Till exempel:
"IdentityServer": {
"Key": {
"Type": "Store",
"StoreName": "WebHosting",
"StoreLocation": "CurrentUser",
"Name": "CN=MyApplication"
}
}
I föregående exempel:
-
StoreName
representerar namnet på certifikatarkivet där certifikatet lagras. I det här fallet pekar den på webbhotellbutiken. -
StoreLocation
representerar var certifikatet ska läsas in från (CurrentUser
i det här fallet). -
Name
motsvarar certifikatets unika ämne.
Exempel: Distribuera till Azure App Service
I det här avsnittet beskrivs hur du distribuerar appen till Azure App Service med hjälp av ett certifikat som lagras i certifikatarkivet. Om du vill ändra appen så att den läser in ett certifikat från certifikatarkivet krävs en tjänstplan på standardnivå eller bättre när du konfigurerar appen i Azure-portalen i ett senare steg.
I appens appsettings.json
-fil ändrar du avsnittet IdentityServer
så att den innehåller nyckelinformationen:
"IdentityServer": {
"Key": {
"Type": "Store",
"StoreName": "My",
"StoreLocation": "CurrentUser",
"Name": "CN=MyApplication"
}
}
- Butiksnamnet representerar namnet på certifikatarkivet där certifikatet lagras. I det här fallet pekar den på den personliga användarbutiken.
- Lagringsplatsen representerar var certifikatet ska läsas in från (
CurrentUser
ellerLocalMachine
). - Namnegenskapen på certifikatet motsvarar certifikatets unika ämne.
Om du vill distribuera till Azure App Service följer du stegen i Distribuera appen till Azure, som förklarar hur du skapar nödvändiga Azure-resurser och distribuerar appen till produktion.
När du har följt föregående instruktioner distribueras appen till Azure men fungerar ännu inte. Certifikatet som används av appen måste konfigureras i Azure-portalen. Leta upp tumavtrycket för certifikatet och följ stegen som beskrivs i Läs in dina certifikat.
De här stegen nämner SSL, men det finns ett privata certifikat i Azure-portalen där du kan ladda upp det etablerade certifikatet som ska användas med appen.
När du har konfigurerat appen och appens inställningar i Azure-portalen startar du om appen i portalen.
Andra konfigurationsalternativ
Stödet för API-auktorisering bygger ovanpå IdentityServer med en uppsättning konventioner, standardvärden och förbättringar för att förenkla upplevelsen för SPA:er. Naturligtvis är den fulla kraften i IdentityServer tillgänglig i bakgrunden om ASP.NET Core-integreringarna inte täcker ditt scenario. Stödet för ASP.NET Core fokuserar på appar från första part, där alla appar skapas och distribueras av vår organisation. Därför erbjuds inte stöd för sådant som medgivande eller federation. I dessa scenarier använder du IdentityServer och följer deras dokumentation.
Programprofiler
Programprofiler är fördefinierade konfigurationer för appar som ytterligare definierar sina parametrar. För närvarande stöds följande profiler:
-
IdentityServerSPA
: Representerar ett SPA som hanteras tillsammans med IdentityServer som en enda enhet.- Standardvärdet för
redirect_uri
är/authentication/login-callback
. - Standardvärdet för
post_logout_redirect_uri
är/authentication/logout-callback
. - Uppsättningen med omfång innehåller
openid
,profile
och varje omfång som definierats för API:erna i appen. - Uppsättningen tillåtna OIDC-svarstyper är
id_token token
eller var och en av dem individuellt (id_token
,token
). - Det tillåtna svarsläget är
fragment
.
- Standardvärdet för
-
SPA
: Representerar ett SPA som inte värdshålls av IdentityServer.- Uppsättningen med omfång innehåller
openid
,profile
och varje omfång som definierats för API:erna i appen. - Uppsättningen tillåtna OIDC-svarstyper är
id_token token
eller var och en av dem individuellt (id_token
,token
). - Det tillåtna svarsläget är
fragment
.
- Uppsättningen med omfång innehåller
-
IdentityServerJwt
: Representerar ett API som finns tillsammans med IdentityServer.- Appen är konfigurerad för att ha ett enda omfång som är standard för appnamnet.
-
API
: Representerar ett API som inte finns med IdentityServer.- Appen är konfigurerad för att ha ett enda omfång som är standard för appnamnet.
Konfiguration via AppSettings
Konfigurera apparna via konfigurationssystemet genom att lägga till dem i listan över Clients
eller Resources
.
Konfigurera varje klients egenskap redirect_uri
och post_logout_redirect_uri
enligt följande exempel:
"IdentityServer": {
"Clients": {
"MySPA": {
"Profile": "SPA",
"RedirectUri": "https://www.example.com/authentication/login-callback",
"LogoutUri": "https://www.example.com/authentication/logout-callback"
}
}
}
När du konfigurerar resurser kan du konfigurera resursens omfång enligt nedan:
"IdentityServer": {
"Resources": {
"MyExternalApi": {
"Profile": "API",
"Scopes": "a b c"
}
}
}
Konfiguration via kod
Du kan också konfigurera klienter och resurser via kod med hjälp av en överlagring av AddApiAuthorization
som vidtar en åtgärd för att konfigurera alternativ.
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"));
});
Ytterligare resurser
ASP.NET Core