Dela via


Konfigurera JWT-ägarautentisering i ASP.NET Core

Av Damien Bowden

JWT-ägarautentisering (JSON-webbtoken) används ofta för API:er. Även om den fungerar på samma sätt som cookie autentisering, utfärdar identitetsprovidern en JWT eller token vid en lyckad autentisering. Dessa token kan sedan skickas till andra servrar för att autentisera, till skillnad från cookies som endast skickas tillbaka till den utfärdande domänen. En JWT är en fristående token som kapslar in information för en API-resurs eller en klient. Klienten som begärde JWT kan begära data från en API-resurs med hjälp av auktoriseringshuvudet och en ägartoken.

JWT Bearer Authentication tillhandahåller:

  • Authentication: När du använder JwtBearerHandlerär bearertoken nödvändiga för autentisering. JwtBearerHandler verifierar token och extraherar användarens identitet från dess anspråk.
  • Authorization: Bärare-token möjliggör auktorisering genom att tillhandahålla en samling av påståenden vilka representerar användarens eller programmets behörigheter, ungefär som en cookie.
  • Delegerad auktorisering: När en användarspecifik åtkomsttoken används för att autentisera mellan API:er i stället för en programomfattande åtkomsttoken kallas den här processen delegerad auktorisering.

En introduktion till JWT-ägarautentisering finns i JSON-webbtoken.Visa eller ladda ned exempelkod

Den här artikeln beskriver följande områden:

  • Tokentyper
  • Använda JWT-token för att skydda en API:er
  • Hur passar OIDC/OAuth in i detta?
  • Implementera autentisering med JWT-ägartoken
  • Rekommenderade metoder för att skapa en JWT

Tokentyper

Det finns många typer av token och format. Det rekommenderas inte att generera egna åtkomsttoken eller ID-token, förutom i testsyfte. Självskapade token som inte följer etablerade standarder:

  • Kan leda till säkerhetsrisker.
  • Lämpar sig endast för slutna system.

Vi rekommenderar att du använder OpenID Connect 1.0 eller en OAuth-standard för att skapa åtkomsttoken som är avsedda för API-åtkomst.

Åtkomsttoken

Åtkomsttoken:

  • Strängar används av en klientapp för att göra begäranden till servern som implementerar ett API.
  • Kan variera i format. Olika API:er kan använda olika format för token.
  • Kan krypteras.
  • Bör aldrig läsas eller tolkas av en webbklient eller en användargränssnittsapp som innehåller åtkomsttoken.
  • Är endast avsedda för att göra begäranden till ett API.
  • Skickas vanligtvis till API:et i Authorization begäranhuvud som en bärartoken.

Se OAuth 2.0 auktoriseringsramverk

Programåtkomsttoken och delegerade åtkomsttoken

Åtkomsttoken kan antingen vara programåtkomsttoken eller delegerade åtkomsttoken. Tokenen har olika anspråk och hanteras och lagras på olika sätt. En programåtkomsttoken lagras vanligtvis en gång i appen tills den upphör att gälla, medan en delegerad åtkomsttoken lagras per användare, antingen i en cookie eller i en säker servercache.

Vi rekommenderar att du använder delegerade användaråtkomsttoken när en användare är inblandad. Underordnade API:er kan begära en delegerad användaråtkomsttoken för den autentiserade användarens räkning.

Avsändarbegränsade åtkomsttoken

Åtkomsttoken kan användas som ägartoken eller avsändarbegränsade token för åtkomst till resurser. Avsändarbegränsade token kräver att den begärande klienten bevisar innehav av en privat nyckel för att använda token. Att bevisa innehav av en privat nyckel garanterar att token inte kan användas oberoende. Avsändarbegränsade token kan implementeras på två sätt:

ID-token

ID-token är säkerhetstoken som bekräftar att en användare har lyckats med autentiseringen. Med token kan klienten verifiera användarens identitet. JWT-tokenservern utfärdar ID-token som innehåller anspråk med användarinformation. ID-token finns alltid i JWT- format.

ID-token bör aldrig användas för åtkomst till API:er.

Andra token

Det finns många typer av token, inklusive åtkomst- och ID-token, enligt OpenID Connect- och OAuth-standarder. Uppdateringstoken kan användas för att uppdatera en användargränssnittsapp utan att autentisera användaren igen. OAuth JAR-token kan skicka auktoriseringsbegäranden på ett säkert sätt. Flöden för verifierbara uppgifter använder JWT-typer för att utfärda eller verifiera dessa uppgifter. Det är viktigt att använda token enligt specifikationerna. Mer information finns i standardlänkarna som tillhandahålls senare i den här artikeln.

Använda JWT-token för att skydda ett API

När du använder JWT-åtkomsttoken för API-auktorisering beviljar eller nekar API:et åtkomst baserat på den angivna token. Om begäran inte är auktoriserad returneras ett 401- eller 403-svar. API:et bör inte omdirigera användaren till identitetsprovidern för att hämta en ny token eller begära ytterligare behörigheter. Appen som använder API:et ansvarar för att hämta en lämplig token. Detta säkerställer en tydlig uppdelning av problem mellan API :et (auktorisering) och den förbrukande klientappen (autentisering).

Obs

HTTP tillåter också att 404 returneras för ej auktoriserade, för att inte läcka information om förekomsten av resurser till obehöriga klienter.

401 Ej auktoriserad

Ett 401-otillåtet svar anger att den angivna åtkomsttoken inte uppfyller de standarder som krävs. Detta kan bero på flera orsaker, bland annat:

  • Ogiltig signatur: Tokens signatur matchar inte, vilket tyder på potentiell manipulering.
  • Förfallodatum: Token har upphört att gälla och är inte längre giltig.
  • Felaktiga anspråk: Kritiska anspråk i token, till exempel målgruppen (aud) eller utfärdaren (iss), saknas eller är ogiltiga.

Obs

Från HTTP Semantics RFC 9110: Servern som genererar ett 401-svar måste skicka ett WWW-Authenticate rubrikfält (avsnitt 11.6.1) som innehåller minst en utmaning som gäller för målresursen.

OAuth-specifikationerna ger detaljerade riktlinjer för de påståenden som krävs och deras validering.

403 Förbjudet

Ett 403 Förbjudet-svar indikerar vanligtvis att den autentiserade användaren saknar de behörigheter som krävs för att få åtkomst till den begärda resursen. Detta skiljer sig från autentiseringsproblem, t.ex. en ogiltig token, och är inte relaterat till standardanspråken i åtkomsttoken.

I ASP.NET Core kan du framtvinga auktorisering med hjälp av:

Krav och principer: Definiera anpassade krav, t.ex. "Måste vara administratör" och associera dem med principer. Rollbaserad auktorisering: Tilldela användare till roller som "Administratör", "Redigerare" och begränsa åtkomst baserat på dessa roller.

Vilken roll har OIDC och/eller OAuth när du använder ägartoken?

När ett API använder JWT-åtkomsttoken för auktorisering validerar API:et endast åtkomsttoken, inte på hur token hämtades.

OpenID Connect (OIDC) och OAuth 2.0 tillhandahåller standardiserade, säkra ramverk för tokenförvärv. Tokenförvärv varierar beroende på apptyp. På grund av komplexiteten i anskaffning av säker token rekommenderar vi starkt att du använder följande standarder:

  • För appar som agerar på uppdrag av en användare och ett program: OIDC är det föredragna valet, vilket aktiverar delegerad användaråtkomst. I webbappar rekommenderas det konfidentiella kodflödet med proof key for Code Exchange (PKCE) för förbättrad säkerhet.
  • Om appen inte har någon användare: OAuth 2.0-klientens autentiseringsuppgifter är lämpligt för att hämta programåtkomsttoken.

Implementera autentisering med JWT-ägartoken

Microsoft.AspNetCore.Authentication.JwtBearer Nuget-paketet kan användas för att verifiera JWT-ägartoken.

JWT-ägartoken bör verifieras fullständigt i ett API. Följande bör verifieras:

  • Signatur för förtroende och integritet. Detta säkerställer att token skapades av den avsedda tjänsten för säker token och inte har manipulerats.
  • Utfärdarens anspråk med det förväntade värdet.
  • Målgruppspåstående med förväntat värde.
  • Förfallodatum för token.

Följande anspråk krävs för OAuth 2.0-åtkomsttoken: iss, exp, aud, sub, client_id, iatoch jti.

Om något av dessa anspråk eller värden är felaktiga bör API:et returnera ett 401-svar.

Grundläggande validering av JWT-ägartoken

En grundläggande implementering av AddJwtBearer kan bara verifiera målgruppen och utfärdaren. Signaturen måste verifieras så att token kan vara betrodd och att den inte har manipulerats.

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(jwtOptions =>
{
	jwtOptions.Authority = "https://{--your-authority--}";
	jwtOptions.Audience = "https://{--your-audience--}";
});

Explicita validering av JWT-bärartoken

Metoden AddJwtBearer innehåller flera konfigurationer. Vissa säkra tokenprovidrar använder en metadataadress som inte är standard och parametern kan konfigureras explicit. API:et kan acceptera flera utfärdare eller målgrupper.

Det krävs inte att du uttryckligen definierar parametrarna. Definitionerna beror på anspråksvärdena för åtkomsttoken och den säkra tokenserver som används för att verifiera åtkomsttoken. Du bör använda standardvärdena om möjligt.

Se Mappningsanspråk detaljer om MapInboundClaims.

builder.Services.AddAuthentication()
.AddJwtBearer("some-scheme", jwtOptions =>
{
	jwtOptions.MetadataAddress = builder.Configuration["Api:MetadataAddress"];
	// Optional if the MetadataAddress is specified
	jwtOptions.Authority = builder.Configuration["Api:Authority"];
	jwtOptions.Audience = builder.Configuration["Api:Audience"];
	jwtOptions.TokenValidationParameters = new TokenValidationParameters
	{
		ValidateIssuer = true,
		ValidateAudience = true,
		ValidateIssuerSigningKey = true,
		ValidAudiences = builder.Configuration.GetSection("Api:ValidAudiences").Get<string[]>(),
		ValidIssuers = builder.Configuration.GetSection("Api:ValidIssuers").Get<string[]>()
	};

	jwtOptions.MapInboundClaims = false;
});

JWT med flera scheman

API:er behöver ofta hantera åtkomsttoken från olika utfärdare. Stöd för flera token utfärdare i ett API kan utföras genom att:

  • separata API:er: Skapa distinkta API:er med dedikerade autentiseringsscheman för varje utfärdare.
  • AddPolicyScheme Den här metoden kan definiera flera autentiseringsscheman och implementera logik för att välja lämpligt schema baserat på tokenegenskaper (t.ex. utfärdare och anspråk). Den här metoden ger större flexibilitet inom ett enda API.

Att framtvinga bäraautentiseringen

SetFallbackPolicy kan användas för att kräva autentisering för alla begäranden även till slutpunkter utan ett [Authorize]-attribut. SetDefaultPolicy konfigurerar policyn som används för slutpunkter med attributet [Authorize] och redan kräver autentiserade användare. Se dokumentationen för autentiserade användare för mer information.

var requireAuthPolicy = new AuthorizationPolicyBuilder()
	.RequireAuthenticatedUser()
	.Build();

builder.Services.AddAuthorizationBuilder()
	.SetFallbackPolicy(requireAuthPolicy);

Attributet AuthorizeAttribute kan också användas för att framtvinga autentiseringen. Om flera scheman används måste ägarschemat vanligtvis anges som standardautentiseringsschema eller anges via [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme]).

Auktorisering i kontrollörer:

[Authorize]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{

Auktorisering i minimala API:er:

app.MapGet("/hello", [Authorize] () => "Hi");

Osäker hantering av åtkomsttoken, till exempel svag autentisering eller lagring av token i sårbar lagring på klientsidan, kan leda till betydande säkerhetsrisker. Du kan till exempel lagra åtkomsttoken direkt i webbläsaren med hjälp av lokal lagring, sessionslagring eller webbarbetare. Följande avsnitt innehåller metodtips för appar som använder och skapar åtkomsttoken.

Använda standarder

Standarder som OpenID Connect eller OAuth bör alltid användas när du skapar åtkomsttoken. Åtkomsttoken bör inte skapas i produktionsappar utan att följa de säkerhetsåtgärder som beskrivs i den här artikeln. Att skapa åtkomsttoken bör begränsas till testscenarier.

Använda asymmetriska nycklar

Asymmetriska nycklar bör alltid användas när du skapar åtkomsttokenar. Den offentliga nyckeln är tillgänglig i de välkända slutpunkterna och API-klienterna kan verifiera signaturen för åtkomsttoken med hjälp av den offentliga nyckeln.

Skapa aldrig en åtkomsttoken från en begäran om användarnamn/lösenord

Du bör INTE skapa en åtkomsttoken från en begäran om användarnamn/lösenord. Begäranden om användarnamn/lösenord autentiseras inte och är sårbara för förfalsknings- och phishingattacker. Åtkomsttoken bör endast skapas med ett OpenID Connect-flöde eller ett OAuth-standardflöde. Om du avviker från dessa standarder kan det leda till en osäker app.

Använda cookies

För säkra webbappar krävs en serverdel för att lagra åtkomsttoken på en betrodd server. Endast en säker HTTP-Only cookie delas i klientwebbläsaren. Se dokumentationen om OIDC-autentisering för hur du gör detta i en ASP.NET Core-webbapp.

Underordnade API:er

API:er behöver ibland komma åt användardata från underordnade API:er för den autentiserade användarens räkning i den anropande appen. Det är ett alternativ att implementera ett OAuth-flöde för klientautentiseringsuppgifter, men det kräver fullständigt förtroende mellan de två API-apparna. En säkrare metod innebär att använda en nollförtroendestrategi med en delegerad användaråtkomsttoken. Den här metoden:

  • Förbättrar säkerheten genom att endast ge API:et de behörigheter som krävs för den specifika användaren.
  • Kräver att API:et skapar den nya åtkomsttoken för användaren som anropar appen och API:et.

Det finns flera sätt att implementera en nollförtroendestrategi med en delegerad användaråtkomsttoken:

Använd OAuth 2.0 Token Exchange för att begära en ny delegerad åtkomsttoken

Det här är ett bra sätt att implementera det här kravet, men det är komplicerat om du måste implementera OAuth-flödet.

Se OAuth 2.0 Token Exchange

Använd Microsoft Identity Web åt Flow för att begära en ny delegerad åtkomsttoken

Att använda Microsoft Identity webbautentiseringsbibliotek är den enklaste och säkra metoden. Det fungerar bara med Microsoft Entra ID, Microsoft Entra Externt ID.

Mer information finns i Microsofts identitetsplattform och OAuth 2.0 On-Behalf-Of-flödet.

Använd samma delegerade åtkomsttoken som skickas till API:et

Den här metoden är inte svår att implementera, men åtkomsttoken har åtkomst till alla underordnade API:er. Yarp reverse proxy kan användas för att implementera detta.

Använd OAuth-klientens autentiseringsuppgifter och använd en applikationsåtkomsttoken

Det här är enkelt att implementera, men klientprogrammet har fullständig programåtkomst och inte en delegerad åtkomsttoken. Token ska cachelagras i klient-API-programmet.

Obs

App-till-app-säkerhet fungerar också. Certifikatautentisering, eller i Azure, kan en hanterad identitet användas.

Hantera åtkomsttoken

När du använder åtkomsttoken i ett klientprogram måste åtkomsttoken roteras, sparas och lagras på servern. I en webbapp används cookies för att skydda sessionen och kan användas för att lagra token via egenskapen SaveTokens .

SaveTokens uppdaterar inte åtkomsttoken automatiskt, men den här funktionen planeras för en framtida version. Under tiden kan du uppdatera åtkomsttoken manuellt enligt vad som visas i OIDC-dokumentationen Blazor Web App eller använda ett NuGet-paket från tredje part, till exempel Duende.AccessTokenManagement.OpenIdConnect. Mer information finns i Hantering av Duende-token.

Obs

Om du distribuerar till produktion bör cachen fungera i en distribution med flera instanser. En beständig cache krävs normalt.

Vissa säkra tokenservrar krypterar åtkomsttoken. Åtkomsttoken kräver inget format. När du använder OAuth-introspektion används en referenstoken i stället för en åtkomsttoken. Ett klientprogram (UI) bör aldrig öppna en åtkomsttoken eftersom åtkomsttoken inte är avsedd för detta. Endast ett API som åtkomsttoken skapades för ska öppna åtkomsttoken.

  • Öppna inte åtkomsttoken i ett användargränssnittsprogram
  • Skicka inte ID-token till API:erna
  • Åtkomsttoken kan ha valfritt format
  • Åtkomsttoken kan krypteras
  • Åtkomsttoken upphör att gälla och måste roteras
  • Åtkomsttoken sparas på en säker backendserver

YARP (ännu en till omvänd proxy)

YARP (Yet Another Reverse Proxy) är en användbar teknik för att hantera HTTP-begäranden och vidarebefordra begäranden till andra API:er. YARP kan implementera säkerhetslogik för att hämta nya åtkomstautentiseringsuppgifter. YARP används ofta när du använder säkerhetsarkitekturen Backend for Frontend (BFF).

Exempel Blazor som använder YARP för att implementera BFF-mönstret finns i följande artiklar:

Ett Blazor exempel som använder YARP för att implementera BFF-mönstret finns i Skydda en ASP.NET Core Blazor Web App med OpenID Connect (OIDC).

För mer information, se auth0: The Backend for Frontend Pattern.

Testa API:er

Integreringstester och containrar med åtkomsttoken kan användas för att testa säkra API:er. Åtkomsttoken kan skapas med hjälp av verktyget dotnet user-jwts.

Varning

Se till att säkerhetsproblem inte introduceras i API:et i testsyfte. Testning blir svårare när delegerade åtkomsttoken används, eftersom dessa token bara kan skapas via ett användargränssnitt och ett OpenID Connect-flöde. Om ett testverktyg används för att skapa delegerade åtkomsttoken måste säkerhetsfunktioner inaktiveras för testning. Det är viktigt att dessa funktioner endast inaktiveras i testmiljön.

Skapa dedikerade och isolerade testmiljöer där säkerhetsfunktioner på ett säkert sätt kan inaktiveras eller ändras. Se till att dessa ändringar är strikt begränsade till testmiljön.

Använda Swagger UI, Curl och andra API UI-verktyg

Swagger UI och Curl är bra gränssnittsverktyg för att testa API:er. För att verktygen ska fungera kan API:et skapa ett OpenAPI-dokument och det kan läsas in i klienttestningsverktyget. Ett säkerhetsflöde för att hämta en ny åtkomsttoken kan läggas till i API OpenAPI-filen.

Varning

Distribuera inte osäkra säkerhetstestflöden till produktion.

När du implementerar ett Swagger-användargränssnitt för ett API bör du normalt inte distribuera användargränssnittet till produktion eftersom säkerheten måste försvagas för att detta ska fungera.

Mappa krav från OpenID Connect

Se följande dokument:

Mappa, anpassa och transformera anspråk i ASP.NET Core

Standarder