Jwt Cracking in Adonisjs
How JWT Cracking Manifests in AdonisJS
JWT cracking in AdonisJS applications typically stems from misconfigurations in the @adonisjs/auth package and improper handling of token secrets. AdonisJS uses a configuration-driven approach for authentication, where weak or exposed secrets in config/auth.ts become a primary attack vector. Attackers exploit these weaknesses through offline brute-force or dictionary attacks against the JWT signature, especially when the token uses the none algorithm or a short, predictable secret.
A common pattern in AdonisJS v5+ projects is the default api guard configuration:
// config/auth.ts
export default defineAuthConfig({
guards: {
api: {
driver: 'jwt',
tokenProvider: {
driver: 'database',
identifier: 'id',
// UNSAFE: Hardcoded or weak secret
secret: 'my-secret-key',
// UNSAFE: Algorithm not enforced
algorithm: 'HS256',
},
},
},
});Here, a statically defined secret in source code—especially a common default like 'secret' or a short alphanumeric string—can be cracked in seconds using tools like hashcat or john with JWT-specific mode (--format=JWT). Once cracked, the attacker can forge arbitrary tokens with elevated privileges (e.g., { "id": 1, "role": "admin" }).
Another AdonisJS-specific manifestation occurs when developers override the verify method without enforcing algorithm validation. The @adonisjs/auth token provider internally uses jsonwebtoken. If an application manually verifies tokens with jwt.verify(token, secret) without an algorithms array, it becomes vulnerable to algorithm confusion attacks (CVE-2020-28472). An attacker can change the token header to { "alg": "none" } and bypass signature verification entirely if the code does not explicitly reject none.
Finally, AdonisJS applications often trust claims like sub (subject) or custom roles from the JWT payload without re-validating them against the database. This can lead to Broken Object Level Authorization (BOLA/IDOR) if the JWT's id claim is used directly to fetch resources without additional ownership checks, a pattern frequently seen in AdonisJS controllers:
// Vulnerable controller
public async show({ auth, params }: HttpContext) {
// UNSAFE: auth.user!.id comes from JWT payload
const user = await User.query().where('id', auth.user!.id).firstOrFail();
return user;
}If the JWT's id is forged via a cracked secret, this endpoint returns data for any user.
AdonisJS-Specific Detection
Detecting JWT cracking vulnerabilities in an AdonisJS API requires analyzing both the OpenAPI/Swagger specification (if available) and runtime behavior. middleBrick's scanning engine tests for these issues through its Encryption and Authentication checks, which are part of its 12 parallel security assessments.
First, middleBrick inspects the JWT algorithm and secret strength. It sends crafted requests to authenticated endpoints (if any) and analyzes the WWW-Authenticate header or response patterns to infer token handling. For unauthenticated scans, it may detect JWT endpoints by common paths like /auth/login that return tokens. The scanner then:
- Checks for
alg: noneacceptance: Sends a token withalg: noneand an empty signature. If the server accepts it, this is a critical finding. - Tests weak secrets: Uses a dictionary of common secrets (e.g.,
secret,password,adonis) and short strings to attempt signature verification. Success indicates a crackable secret. - Validates algorithm enforcement: Tries to change the algorithm from
HS256toRS256in the token header. If the server still accepts it with the same secret, it suggests algorithm confusion.
To scan an AdonisJS API with middleBrick, use the CLI:
middlebrick scan https://api.your-adonis-app.comOr from the web dashboard, paste the endpoint URL. The scan takes 5–15 seconds and returns a risk score (A–F) with a per-category breakdown. A finding under the Encryption category might read: "JWT secret appears weak (dictionary match). Attackers can forge tokens." The report includes severity (typically High or Critical) and remediation guidance specific to AdonisJS configuration.
If your AdonisJS app provides an OpenAPI spec, middleBrick resolves all $ref definitions and cross-references security schemes. It looks for securitySchemes using bearerAuth and flags if the spec lacks bearerFormat: JWT or algorithm constraints. However, runtime testing is essential because spec declarations often don't match implementation.
AdonisJS-Specific Remediation
Remediating JWT cracking in AdonisJS involves hardening the authentication configuration, enforcing strong secrets, and validating claims. All fixes use AdonisJS's native features—no external libraries are required.
1. Use a strong, environment-based secret
Never hardcode secrets. In config/auth.ts, reference a strong secret from your .env file. Generate a 256-bit (32-byte) random string using OpenSSL or a similar tool:
// .env
JWT_SECRET=$(openssl rand -base64 32)
// config/auth.ts
import env from '#ioc/env'
export default defineAuthConfig({
guards: {
api: {
driver: 'jwt',
tokenProvider: {
driver: 'database',
identifier: 'id',
secret: env.get('JWT_SECRET'), // Strong secret from env
algorithm: 'HS256', // Explicitly set
},
},
},
});2. Enforce algorithm validation
AdonisJS's JWT provider uses jsonwebtoken under the hood. Ensure the verify call includes an algorithms array. If you manually verify tokens (e.g., in a custom middleware), do:
import jwt from 'jsonwebtoken'
public async handle({ auth, request }: HttpContext) {
const token = request.header('authorization')?.replace('Bearer ', '')
try {
// Explicitly allow only HS256
const payload = jwt.verify(token, env.get('JWT_SECRET'), { algorithms: ['HS256'] })
auth.user = payload
} catch (error) {
throw new UnauthorizedException('Invalid token')
}
}3. Validate JWT claims
Never trust user-controlled claims like id or role from the token. Re-validate against the database and scope the token to the user's actual permissions. In your controller or a policy:
import { schema, rules } from '@ioc:Adonis/Core/Validator'
public async show({ auth, params }: HttpContext) {
// Validate that the token's user ID matches the requested resource
if (auth.user!.id !== parseInt(params.id)) {
throw new ForbiddenException('Not authorized')
}
const user = await User.query().where('id', params.id).firstOrFail()
return user
}
// Alternatively, use a validator schema for the token payload
const tokenSchema = schema.create({
id: schema.number([rules.exists({ table: 'users' })]),
role: schema.enum(['user', 'admin'] as const),
})4. Rotate secrets periodically
For long-lived JWTs, implement secret rotation. AdonisJS doesn't have built-in rotation, but you can maintain a secret version in the token header (e.g., kid) and verify against a set of active secrets. This requires custom tokenProvider logic but is feasible using AdonisJS's provider extension points.
After applying these fixes, re-scan with middleBrick to confirm the Encryption and Authentication categories show no findings. The remediation guidance in middleBrick's report will reference these exact AdonisJS configuration patterns.
Frequently Asked Questions
How does JWT cracking specifically target AdonisJS applications?
config/auth.ts and missing algorithm enforcement in the JWT driver. Attackers exploit default configurations (e.g., short secrets) and algorithm confusion (CVE-2020-28472) to forge tokens. AdonisJS's reliance on jsonwebtoken means misconfigured verify calls without an algorithms array are vulnerable. middleBrick detects these by testing for alg: none acceptance and weak secret dictionaries.