Förstå JWT-validering: En praktisk guide med kodexempel

Av Natalia Moskaleva den 22 januari 2026

11 min lästid

Två datorer bredvid varandra med kodningslinjer

JSON Web Tokens (JWT) erbjuder en säker och standardiserad metod för att lagra och utbyta data i JSON-format. Trots att de används i stor utsträckning inom modern webbutveckling kräver en robust implementering av JWT kunskap och noggrann hantering för att garantera optimal säkerhet. Detta för oss in på ämnet JWT-validering.

I den här artikeln kommer vi att diskutera:

  • Hur säkerställer vi att en JWT-token kan lita på och inte har manipulerats?
  • Vad innebär JWT-validering och vilka tokenelement valideras?
  • Hur man utför JWT-validering.

JWT:er kan också krypteras för konfidentialitet (se JSON Web Encryption, JWE), men här fokuserar vi på signerade tokens (JSON Web Signature, JWS). Krypterade tokens håller den information de innehåller dold för externa parter. Signerade tokens, å andra sidan, döljer inte informationen, utan erbjuder bevis på dataintegritet genom validering. Det är därför valideringssteget är avgörande när man arbetar med signerade JWT:er.

Vi kommer att använda en JWT-token utfärdad av Idura Verify för att visa tokenstrukturen och de element som kräver validering.

En grundkurs om JWT:er

JWT:er används ofta för att hantera identitet, autentisering och auktorisering. JWT-baserad användarautentisering har blivit en standardmetod, särskilt eftersom den integreras så smidigt med mobila applikationer och SPA. Ett annat vanligt fall för JWT är att använda dem som åtkomsttokens och ID-tokens i OAuth2- och OpenID Connect-flöden.

Demonstration: en JWT-token i ett OpenID Connect-flöde

Tänk dig ett OpenID Connect-flöde där en användare loggar in i en webbapplikation med ett elektroniskt ID (eID). Idura Verify fungerar som en OpenID-provider för inloggningsprocessen: vid lyckad autentisering utfärdar den en ID-token formaterad som en JWT till klientapplikationen. (Mer specifikt kommer din domän hos Idura att fungera som en OpenID-provider).

Till exempel, när en användare loggar in med hjälp av danska MitID, får applikationen en ID-token som kan se ut så här:

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjhCREY3OUEzRkY5OTdFQTg1QjYyRjk1OUQzRDdCMzdFRDAyMjhFOTAifQ.eyJpc3MiOiJodHRwczovL2RlbW9zLXRlc3QuY3JpaXB0by5pZCIsImF1ZCI6InVybjpkZW1vczpjb29sLWRlbGl2ZXJ5LXJlYWN0IiwiaWRlbnRpdHlzY2hlbWUiOiJka21pdGlkIiwiYXV0aGVudGljYXRpb250eXBlIjoidXJuOmdybjphdXRobjpkazptaXRpZDpzdWJzdGFudGlhbCIsImF1dGhlbnRpY2F0aW9ubWV0aG9kIjoiYXBwOjE3MDUzMjQ5MjYxNTM6U1VCU1RBTlRJQUw6U1VCU1RBTlRJQUw6SElHSDpISUdIIiwiYXV0aGVudGljYXRpb25pbnN0YW50IjoiMjAyNC0wMS0xNVQxMzoyMjowNy44MDFaIiwibmFtZWlkZW50aWZpZXIiOiJiYWQwZmJiMmRmM2Q0Yzg3YTU5OGRjZDcyYTJlYWRjMCIsInN1YiI6IntiYWQwZmJiMi1kZjNkLTRjODctYTU5OC1kY2Q3MmEyZWFkYzB9Iiwic2Vzc2lvbmluZGV4IjoiYjRiMmE1ZjctMTM1Ni00YjhkLTliZjMtZTFlNjIzOWEzOTJlIiwibG9BIjoiU1VCU1RBTlRJQUwiLCJpYWwiOiJTVUJTVEFOVElBTCIsImFhbCI6IlNVQlNUQU5USUFMIiwiZmFsIjoiSElHSCIsInV1aWQiOiJkNWVhNjMzMS02ZGU0LTQ5ZTktODUyYy0xNDE1YjMxNTM3YzIiLCJiaXJ0aGRhdGUiOiIxOTk1LTAzLTAyIiwiZGF0ZW9mYmlydGgiOiIxOTk1LTAzLTAyIiwiYWdlIjoiMjgiLCJuYW1lIjoiS2FqIEFuZGVyc2VuIiwicmVmVGV4dEhlYWRlciI6IkxvZyBvbiBhdCBDcmlpcHRvIChURVNUKSIsInJlZlRleHRCb2R5IjoiTG9nIGluIHRvIENvb2wgRGVsaXZlcnkiLCJjb3VudHJ5IjoiREsiLCJpYXQiOjE3MDUzMjQ5NDUsIm5iZiI6MTcwNTMyNDk0NSwiZXhwIjoxNzA1MzI2MTQ1fQ.O7QilOzcqLqRFCr9ij_bPS_hLXtJSZjufTLpNhtU_Oy8FmtHl88ErUsOMKPAgo2WJoCLwrtgLGlPKVzcQ66iUZwboza7bEJF9tQFWAvK1XEw7Fce_TztjsJrxDl-vue4ImjkBZQl-IToPg4egrq6gqXYBcWtWk4xZXRSMtQ4wNOX3gtlAyhDmiAbWwjFNGFzDJYP--sZvxU0MsvDNGzJwz0_JoZGEQoDkUYABxyp9syVyJv6Hock5QGzPMI5JmgPkSPrnRGV2ZnYaytRn1CdQcKIijlh61vwvOxffZBHnNkGXJxim8lOUtEyhDQO4fmnh_bLc2cxOl1hdkGHkgjoRQ

Det som ser ut som en slumpmässig teckensträng är i själva verket en kompakt, utskrivbar representation av en uppsättning anspråk, tillsammans med en kryptografisk signatur. Anspråken innehåller information om den autentiserade användaren och signaturen säkerställer tokenens äkthet: Eftersom token är kryptografiskt signerad är det lätt att verifiera att den är legitim och inte har manipulerats.

Processen med att validera påståendena och signaturen kallas tokenvalidering. Detta valideringssteg är obligatoriskt: Om du inte validerar signaturen får du inte lita på den slutanvändarinformation som ingår.

Låt oss nu utforska JWT:s struktur för att få en djupare förståelse för vad valideringen innebär och vilka tokenelement som valideras.

Översikt över JWT-strukturen

Enligt definitionen i RFC 7519 består en signerad JWT av tre segment åtskilda av punkter:

  • Huvud
  • Nyttolast
  • Signatur

Detta skapar strukturen: header.payload.signature

Avsnitten header och payload innehåller JSON-data som kodats med Base64Url. Så i huvudsak är JWT: er bitar av Base64Url-kodade JSON-data med en kryptografisk signatur i slutet. Alla som har tillgång till en JWT kan avkoda token och se vilken information den innehåller. Du kan experimentera med avkodning på jwt.io - en interaktiv lekplats för att lära dig mer om JWT. Kopiera gärna token ovan och se resultatet. Notera vad som händer när du redigerar innehållet (Tips: Alla ändringar av innehållet kommer att ogiltigförklara signaturen).

Låt oss nu bryta ner varje segment för att förstå dess roll.

Rubrik

Headern innehåller information om token-typen och den algoritm som används för signaturgenerering. De vanligaste signaturalgoritmerna för JWT är RS256 (RSA med SHA256) och HS256 (HMAC med SHA256). JWT kan signeras med hjälp av en delad hemlighet (med HMAC-algoritmen) eller den privata nyckeln från ett offentligt-privat nyckelpar (med RSA).

Den avkodade rubriken från vår token ser ut så här:

{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "8BDF79A3FF997EA85B62F959D3D7B37ED0228E90"
}

Egenskaperna här är:

  • "typ" för token-typen
  • "alg" för signaturalgoritmen (Idura Verify använder RSA för att signera JWT:er)
  • "kid" (nyckel-ID) identifierar en publik nyckel som ska användas för verifiering enligt RSA-algoritmen.

Vi behöver denna information för att utföra token-validering.

Nyttolast

Nyttolasten är central för en JWT: Den innehåller information som token är avsedd att transportera. Anspråken i nyttolasten ger data om användaren som loggade in, till exempel deras identitet, roll eller systembehörigheter. Läs mer om JWT-claims här. Det finns tre typer av JWT-anspråk:

Registrerade anspråk: Dessa definieras av JWT-specifikationen för att säkerställa interoperabilitet med tredjepartsapplikationer. De registrerade anspråken är inte obligatoriska men rekommenderas. Några registrerade anspråk är: issuer (utfärdare), exp (expiration time), sub (subject), aud (audience) och andra. Registrerade anspråk är användbara för vissa vanliga operationer som utförs med JWT och de spelar en roll vid tokenvalidering, vilket demonstreras i nästa session.

Offentliga anspråk: Dessa avser icke-registrerade anspråk som definieras av de parter som använder JWT:er . Offentliga anspråk bör vara universellt kollisionsresistenta: antingen registrerade i IANA-registret "JSON Web Token Claims" eller ha ett kollisionsresistent namn.

Privata anspråk: Privata anspråk definieras på samma sätt av de parter som använder JWT, men skiljer sig från offentliga anspråk genom att de inte behöver vara kollisionssäkra. I vårt exempel på token är identityscheme och authenticationtype privata anspråk.

Den avkodade nyttolasten från vår token ser ut så här (förkortad för korthetens skull, men du kan se den i sin helhet med hjälp av jwt.io):

{
  "iss": "https://demos-test.idura.broker",
  "aud": "urn:demos:cool-delivery-react",
  "identityscheme": "dkmitid",
  "authenticationtype": "urn:grn:authn:dk:mitid:substantial",
  "authenticationinstant": "2024-01-15T13:22:07.801Z",
  "nameidentifier": "bad0fbb2df3d4c87a598dcd72a2eadc0",
  "sub": "{bad0fbb2-df3d-4c87-a598-dcd72a2eadc0}",
  "sessionindex": "b4b2a5f7-1356-4b8d-9bf3-e1e6239a392e",
  "loA": "SUBSTANTIAL",
  "uuid": "d5ea6331-6de4-49e9-852c-1415b31537c2",
  "birthdate": "1995-03-02",
  "dateofbirth": "1995-03-02",
  "age": "28",
  "name": "Kaj Andersen",
  "country": "DK",
  "iat": 1705324945,
  "nbf": 1705324945,
  "exp": 1705326145
}

Signatur

När en OpenID Provider utfärdar en token signerar den den med en kryptografisk signatur.

Signaturen genereras genom att kombinera de base64URL-kodade header- och payload-segmenten med en hemlig eller privat nyckel (beroende på vald algoritm).

För RSA256:

RSA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  private_key
)

För HMAC256:

HMAC256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret
)

Som visas ovan kan JWT:er signeras med antingen en delad hemlighet (med HMAC) eller en privat nyckel (med RSA).

Den exakta processen för signering innebär att man tar en hash av signeringsingången och sedan signerar den hashen. Den här artikeln ger en utmärkt detaljerad förklaring av signeringsprocessen om du vill fylla i några luckor i din förståelse.

Det primära målet med signaturen är att fastställa JWT: s äkthet och bekräfta att dess data inte har manipulerats. Med andra ord kan informationen i token verifieras och lita på just för att token är digitalt signerad.

Det är viktigt att förstå att även om en signatur säkerställer dataintegritet, hindrar den inte andra från att visa innehållet i token. Därför bör känslig information som användarlösenord aldrig överföras i en JWT; allt i huvudet och nyttolasten kan och bör vara säkert för allmän "konsumtion".

Som tidigare nämnts signeras JWT:er som utfärdas av Idura Verify med RS256. RSA, som är en asymmetrisk algoritm, använder par av kryptografiskt länkade nycklar: en offentlig och en privat. Idura Verify håller den privata nyckeln för signaturgenerering, medan applikationen som konsumerar JWT:er kan hämta en motsvarande offentlig nyckel från metadataändpunkten och använda den för att validera signaturen.

Publika nycklar finns tillgängliga på jwks_uri från OpenID Connect Discovery-slutpunkten. JWKS står för JWK Set och representerar en uppsättning JSON Web Keys. För vår exempel-token är jwks_uri: https://demos-test.idura.broker/.well-known/jwks

Med tanke på att nycklar ändras (nyckelrotation) rekommenderas det att använda slutpunkten för dynamisk nyckelhämtning.

När nycklar ingår i JWT-huvudet är det dessutom viktigt att kontrollera att de tillhör den förväntade utfärdaren. Lita bara på tokens från utfärdare som är förregistrerade med din applikation.

När bör du validera en JWT?

Du måste alltid validera en inkommande JWT. Detta är bästa praxis även om du arbetar i ett internt nätverk där auktoriseringsservern, klienten och resursservern inte är anslutna via Internet.

För OpenID Connect-flöden hanteras processen med att skapa och koda en JWT-token av OpenID Provider, medan valideringen måste göras på serversidan av klientapplikationen. Valfritt kan du också utföra validering på klientsidan: det ersätter inte de obligatoriska kontrollerna i backend, men kan fungera som en ledtråd och potentiellt ett sätt att minska serverbelastningen genom att inte skicka ogiltiga JWT:er från frontend till backend.

I projekt som förlitar sig på JWT-baserad autentisering hanteras tokenvalidering vanligtvis av ett dedikerat bibliotek eller middleware, som vi ska illustrera.

JWT-validering steg för steg

I det här avsnittet går vi igenom JWT-valideringsprocessen, återigen med den Idura Verify-utfärdade ID-token som exempel. Även om vissa detaljer, till exempel var man får tag på JWT-nycklar, är specifika för vårt fall, gäller den övergripande kombinationen av steg för alla signerade JWT:er.

Här är de viktigaste stegen för att utföra JWT-validering:

  • Hämta och analysera JSON-webbnyckeluppsättningen (JWK)
  • Avkoda token
  • Verifiera anspråken
  • Verifiera signaturen

Ordningen i vilken dessa steg utförs kan variera. Till exempel kan den råa JWT dekodas och analyseras först för att extrahera `iss`-anspråket, vilket möjliggör tidigt avvisande av tokens från icke betrodda utfärdare. På samma sätt beror ordningen för verifiering av anspråk och signatur på det valda biblioteket. Det implementerande biblioteket har i princip rätt att självt bestämma i vilken ordning dessa steg skall utföras, förutsatt att alla steg utförs.

Hämta JSON Web Keys

Hämta JSON Web Key Set (JWKSet / JWKs) från OIDC discovery endpoint för din domän på Idura. OIDC-upptäcktspunkten innehåller metadata om din tokenutfärdare. Du behöver jwks_uri som gör att du kan komma åt JWK:er. Helst bör din applikation regelbundet kontrollera och cachelagra dessa nycklar.

Avkoda token

Som nämnts är tokens Base64URL-kodade, vilket innebär att du måste avkoda token innan du validerar den.

Verifiera anspråk

Verifiera följande påståenden i JWT-headern:

  • alg
    Bästa praxis är att alltid kontrollera värdet av alg-kravet mot en positivlista över algoritmer som systemet accepterar. Detta hjälper till att förhindra potentiella attacker där någon manipulerar token för att få dig att använda en annan, förmodligen mindre säker algoritm för signaturverifiering. Det finns också en känd attackvektor som utnyttjar värdet "none" i alg-anspråket.


  • kid
    Påståenden som pekar på publika nycklar kräver också särskild uppmärksamhet. Om dessa påståenden är förfalskade kan de leda din tjänst till förfalskade verifieringsnycklar och lura den att acceptera skadliga tokens. Dubbelkolla att nycklarna (eller eventuella URL:er) i rubriken motsvarar tokenens utfärdare (iss-anspråket)eller har de värden du förväntar dig
  • .

Verifiera följande påståenden i JWT Payload:

  • iss(issuer)
    Påståendet om utfärdare bör matcha identifieraren för din OpenID Provider. Med OpenID Connect måste utfärdaren representeras som en URL med hjälp av HTTPS-schemat. Till exempel, i vårt scenario är utfärdaren vår domän på Idura: https://demos-test.idura.broker

Vi rekommenderar att du korsrefererar påståendet med en godkänd lista över betrodda utfärdare och att du alltid validerar att de kryptografiska nycklar som används för att signera token faktiskt tillhör utfärdaren. När man arbetar med JWT:er är det i allmänhet viktigt att bekräfta att token kommer från den förväntade utfärdaren. Detta är särskilt viktigt om din applikation hämtar JWKS dynamiskt.

  • aud(publik)
    Kontrolleraalltid aud-anspråket och verifieraatt token utfärdades till en publik som inkluderar din applikation. Du bör avvisa alla begäranden som innehåller en token som är avsedd för olika målgrupper.

    En ID-token kommer alltid att innehålla klient-ID i aud-anspråket. I vårt scenario kommer aud-anspråket att vara klient-ID för vår Idura Verify-applikation.

  • Tidsbaserade anspråk
    Anspråketiat (issued at time) anger när den här ID-token utfärdades, uttryckt i Unix-tid. Du kan använda det här påståendet för att avvisa tokens som du anser vara för gamla för att användas av din applikation.

Påståendetexp (expiry time) är den tidpunkt då denna token kommer att upphöra att gälla, uttryckt i Unix-tid. Du bör se till att denna tid inte redan har passerat.

Nbf-anspråket (not-before time): token ska avvisas om den aktuella tiden är före tiden i nbf-anspråket.

En vanlig fallgrop är att klientapplikationer inte tillåter någon form av klockförskjutning vid validering av dessa påståenden. Skillnader mellan tidsservrar kan då leda till att tokens visas som ogiltiga. Ett värde på 5 minuter för klockförskjutning rekommenderas normalt.

Verifiera signaturen

För att sammanfatta: med RS256, som i vårt fall, signeras JWT:er med en privat nyckel när de genereras och valideras med en offentlig nyckel vid mottagandet. Validering är avgörande för att säkerställa att tokens inte har modifierats under transitering.

Du verifierar tokenens signatur genom att matcha den nyckel som används för att signera den med en av de nycklar som du hämtade från JWKs-ändpunkten. Varje nyckel identifieras av ett kid-attribut, som motsvarar kid-anspråket i tokenhuvudet.

Om kid-anspråket inte matchar, och du använder någon form av cachelagring för JWKSets, är det möjligt att signeringsnycklarna kan ha ändrats (nyckelrullning). Hämta data från slutpunkten jwks_uri i OIDC-metadata och kontrollera nycklarna igen (du bör utföra denna omhämtning exakt en gång för att undvika oändliga loopar i logiken för tokenvalidering).

Implementering av validering

Det finns flera sätt att utföra JWT-validering:

1. Befintlig mellanprogramvara

Du kan utnyttja befintlig middleware i ditt webbramverk. ASP.NET tillhandahåller till exempel en dedikerad JWT-mellanvara som sömlöst integreras med den övergripande autentiseringslogiken.

2. Bibliotek från tredje part

Vi rekommenderar starkt att du väljer ett väletablerat bibliotek för din plattform för att utföra tokenvalidering. Du kan hitta en omfattande lista över bibliotek för olika språk på jwt.io. När du gör ditt val, bekräfta att biblioteket stöder den signeringsalgoritm som används av dina JWTs och kontrollera vilka påståenden det validerar. De flesta tredjepartsbibliotek erbjuder en flexibel verifieringsmetod med anpassningsbara argument, vilket gör att du kan skräddarsy verifieringsprocessen efter dina behov.

Du bör noggrant följa alla instruktioner om hur du använder det valda biblioteket, eftersom standardinställningar kan medföra potentiella säkerhetsrisker.

3. Manuell implementering (rekommenderas inte):

Även om RFC 7519 > 7.2 Validating a JWT beskriver viktiga kontroller för att validera en token, avråds starkt från manuell JWT-validering på grund av risken för att felaktig implementering leder till säkerhetsproblem.

Det rekommenderas starkt att du använder middleware eller något av de befintliga tredjepartsbiblioteken för att validera JWT. Nedan har vi inkluderat kodprover med exempel på olika språk.

Exempel på kod

Python

Med PyJWT-biblioteket kan t.ex. en token verifieras med metoden decode, som skickar med token och hämtar signeringsnyckeln från JWKS-slutpunkten. PyJWKClient hanterar automatiskt nyckelupplösning baserat på den unge som finns i JWT-huvudet.

import jwt
from jwt import PyJWKClient

token = "your_jwt_token"
url = "https://demos-test.idura.broker/.well-known/jwks"
optional_custom_headers = {"User-agent": "custom-user-agent"}

# Initialize PyJWKClient and fetch the signing key from JWKS
jwks_client = PyJWKClient(url, headers=optional_custom_headers)
signing_key = jwks_client.get_signing_key_from_jwt(token)

# Decode the token using the retrieved signing key
data = jwt.decode(
    token,
    signing_key.key,
    algorithms=["RS256"],
    audience="your_audience"
)
print(data)

NodeJS

Med jose-biblioteket använder du funktionen jwtVerify. För att få de offentliga nycklarna för verifiering kan du hämta JSON Web Key Set från en JWKS-slutpunkt med createRemoteJWKSet . Kodprovet nedan innehåller också valfria parametrar, t.ex. algoritm och specifika krav.

const jose = require('jose');
const token = 'your_jwt_token';
const JWKS = jose.createRemoteJWKSet(new URL('https://demos-test.idura.broker/.well-known/jwks'));

async function verifyToken() {
  try {
    const decodedToken = await jose.jwtVerify(token, JWKS, {
      algorithms: ['RS256'],
      issuer: 'https://demos-test.idura.broker',
      audience: 'your_audience',
    });
    console.log('Token is valid:', decodedToken);
  } catch (error) {
    console.error('Error verifying token:', error);
  }
}

verifyToken();

C#

Med biblioteket Microsoft.IdentityModel.JsonWebTokens i C# kan du använda klassen JwtSecurityTokenHandler och använda metoden ValidateToken. Kodprovet nedan innehåller en asynkron GetJsonWebKeySetAsync-metod, som använder HttpClient för att hämta JSON Web Key Set från en angiven slutpunkt. TokenValidationParameters innehåller inställningar för validering av utfärdaren(ValidIssuer) och målgruppen(ValidAudience).

using System;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var token = "your_jwt_token";
        var jwksEndpoint = "https://demos-test.idura.broker/.well-known/jwks.json";

        var jsonWebKeySet = await GetJsonWebKeySetAsync(jwksEndpoint);

        var handler = new JwtSecurityTokenHandler();
        var validationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKeyResolver = (s, securityToken, identifier, parameters) => jsonWebKeySet.FindKey(identifier),
            ValidIssuer = "https://demos-test.idura.broker",
            ValidAudience = "your_audience"
        };

        try
        {
            var claimsPrincipal = handler.ValidateToken(token, validationParameters, out _);
            Console.WriteLine("Token is valid.");
        }
        catch (SecurityTokenException)
        {
            Console.WriteLine("Invalid token.");
        }
    }

    static async Task<JsonWebKeySet> GetJsonWebKeySetAsync(string jwksEndpoint)
    {
        using (var httpClient = new HttpClient())
        {
            var json = await httpClient.GetStringAsync(jwksEndpoint);
            return new JsonWebKeySet(json);
        }
    }
}

Sammanfattning

Säkerheten för JWT beror i hög grad på hur tokens används och valideras.

Det är viktigt att betona att JWT inte är ett protokoll utan endast ett meddelandeformat. RFC fungerar som en guide för att strukturera meddelanden och införliva lager av säkerhet för att skydda meddelandets integritet. Det är upp till implementatören att följa bästa praxis när man arbetar med JWT. Därför är det viktigt att använda ett tillförlitligt verktyg eller bibliotek för att koda och avkoda tokens och kontrollera deras giltighet.