Skip to main content

Practical example - Threat Modelling of an authentication service with JWT

🎯 Technical context​

During the design phase of a new authentication service (auth-service), the team identified the following components and flows:

  • Publicly accessible REST API at https://auth.exemplo.com
  • Login flow:
    1. The user submits email + password via POST /login
    2. The service validates the credentials locally in a database
    3. If valid, the service generates a JWT token
    4. The JWT is returned to the client and used in future requests (Authorization: Bearer)
  • Initial configuration:
    • JWT with alg: none (no signature)
    • Claims: sub, email, role, exp (24h)
    • No MFA
    • Endpoint /admin/config accessible with any JWT
    • No structured logging and no profile control

🔁 Modelling with a DFD (representation of the system)​

🔷 Threat Model - auth-service (DFD in Mermaid)​


🧱 Elements identified​

ElementTypeDescription
Browser / Mobile AppExternal ActorClient that initiates the login
auth.exemplo.comProcessPublic API that exposes the /login endpoint
JWT GeneratorProcessLogic that generates the JWT tokens
User DatabaseData StoreUser database
SIEM / LogsData StoreStructured event storage
Admin Config EndpointProcessSensitive endpoint: /admin/config
Backend APIsProcessProtected APIs that consume and validate the JWT

🔁 Data flows​

SourceDestinationData Transmitted
Browser → auth APIemail/password via POST /login (HTTPS)
auth API → DBUser lookup
auth API → JWT GenJWT token request
JWT Gen → BrowserJWT (Authorization: Bearer <token>)
Browser → Backend APIsAuthenticated request with JWT
Browser → Admin ConfigAccess with JWT to /admin/config
auth API → SIEM(Absent) - no structured logs

🔍 STRIDE threats per element​

ElementSTRIDE CategoryThreat IdentifiedSeverityRecommended Mitigation
auth.exemplo.comSpoofingLogin with reused credentials or without MFAHighMFA, rate limiting, context analysis (device/IP)
JWT GeneratorTamperingTamperable JWTs (alg: none)HighRS256 signature, header validation, reduced TTL
Admin ConfigElevation of PrivilegeAny user can access administrative endpointsHighClaims-based RBAC, validation of role in the backend
auth.exemplo.comRepudiationNo record of logins or sensitive changesMediumStructured logging with userId, IP, action, result
JWT GeneratorInformation DisclosureExcessive claims (email, role, createdAt) exposed to the clientMediumMinimise claims in the JWT, context-based scoping
auth.exemplo.comDenial of ServiceBrute force on /login or mass reuse of JWTsMediumRate limiting, CAPTCHA, progressive delays

🛡️ Threat ↔ control map​

ThreatRecommended Control
SpoofingMandatory MFA; context-aware login; device binding
TamperingSigned JWT (RS256); validation of alg, aud, iss; TTL ≤ 15 min
Elevation of PrivilegeRBAC with explicit control of claims (e.g. role: admin)
RepudiationCentralised logging; action tracking; integration with SIEM
Information DisclosureMinimal JWT; segregation of claims per endpoint; scoping
Denial of ServiceRate limiting on the /login endpoint; protection at the API Gateway; quotas

✅ Conclusion​

This example illustrates a typical case of modern architecture with:

  • JWT-based authentication
  • Public API accessible via the Internet
  • Lack of basic validations and controls

Even in apparently simple architectures, the misuse of standards (e.g. unsigned JWT) can introduce critical flaws.
The use of a structured approach (e.g. STRIDE) and an explicit representation of the flows (DFD) makes it possible to identify and mitigate threats before going into production.

This threat model must be documented, versioned and reused in other services with an identical architecture, as described in the section “♻️ Reuse of Threat Models”.