HIGH phishing api keysadonisjsjwt tokens

Phishing Api Keys in Adonisjs with Jwt Tokens

Phishing API Keys in AdonisJS with JWT Tokens — how this specific combination creates or exposes the vulnerability

When API keys are mishandled in an AdonisJS application that also issues JWT tokens, the attack surface for phishing and token compromise expands. AdonisJS applications often store long-lived API keys as environment variables and use JWTs for stateless session management. If an attacker can phish a developer’s credentials or compromise a build pipeline, they can retrieve API keys and use them to generate or forge JWTs, or they can directly target JWT-handling endpoints.

A concrete scenario: an AdonisJS service reads process.env.SUPER_SECRET_KEY to sign JWTs and also uses the same key material (or a related key) to call third-party services. If a phishing site captures a developer’s Git credentials, the attacker can obtain the repository with the .env file, extract the signing key, and craft valid JWTs. Alternatively, if an endpoint echoes the token or exposes debug information, an attacker can phish for tokens via social engineering or session fixation, then reuse them across systems.

JWTs themselves do not protect against key leakage. If the secret used to sign tokens is exposed, attackers can impersonate any user. AdonisJS commonly uses jsonwebtoken with HS256, where the same secret must remain confidential on both the issuer and consumer sides. A misconfigured CORS policy or a verbose error message in an authentication route can inadvertently reveal whether a token is valid, aiding phishing campaigns that target token reuse patterns.

Another vector involves storing API keys in client-side code or logs. AdonisJS applications that embed keys in JavaScript bundles or print tokens to console during debugging expose secrets that can be phished through XSS or log scraping. When JWTs are issued with long lifetimes and high privileges, a single phished key can lead to extended access across APIs protected by those tokens.

To detect these risks, scans compare the runtime behavior of the endpoint with the declared OpenAPI schema. If the spec defines an OAuth2 security scheme but the implementation leaks tokens in URLs or logs, this inconsistency is flagged. Additionally, if the scan discovers unauthenticated endpoints that issue or introspect JWTs, or if API keys appear in responses, these findings map to OWASP API Top 10 A07:2021 (Identification and Authentication Failures) and A05:2021 (Security Misconfiguration).

JWT Tokens-Specific Remediation in AdonisJS — concrete code fixes

Remediation focuses on protecting secrets, tightening token handling, and ensuring that API keys and JWT signing materials are never exposed to clients or logs. Below are concrete, safe patterns for AdonisJS.

1. Keep signing keys out of source and logs

Use environment variables loaded via Env and avoid logging tokens. Never print token or process.env keys in console statements.

// start/hooks.ts
import { Exception } from '@poppinss/utils'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import { DateTime } from 'luxon'
import jwt from 'jsonwebtoken'

// Use Env.get with a strict type and a fallback that does not expose secrets
const jwtSecret = Env.get('JWT_SECRET', '')
if (!jwtSecret) {
  throw new Exception('JWT_SECRET is required', 500, 'E_MISSING_JWT_SECRET')
}

export const JWT_SECRET = jwtSecret

In .env, store the secret as a long random string:

JWT_SECRET=7a3f8c2e9b1d4a6f0c5e2b8a1d9f7e6c3a0b2c4d5e6f7a8b9c0d1e2f3a4b5c6d

2. Use asymmetric keys for signing when feasible

Prefer RS256 over HS256 so the verification key can be public while the signing key stays private. This limits exposure even if a consumer service is compromised.

import jwt from 'jsonwebtoken'
import fs from 'fs'
import path from 'path'

const privateKey = fs.readFileSync(path.resolve(__dirname, '../../keys/private.pem'))
const publicKey = fs.readFileSync(path.resolve(__dirname, '../../keys/public.pem'))

export function signToken(payload: object): string {
  return jwt.sign(payload, privateKey, { algorithm: 'RS256', expiresIn: '15m' })
}

export function verifyToken(token: string): jwt.JwtPayload {
  return jwt.verify(token, publicKey, { algorithms: ['RS256'] }) as jwt.JwtPayload
}

3. Validate and sanitize inputs that may influence token handling

Never trust query parameters or headers that could redirect token validation. Use schema validation for token-related inputs.

import { schema } from '@ioc:Adonis/Core/Validator'

const tokenSchema = schema.create({
  token: schema.string({}, [rules.alpha()]) // adjust rules to your token format
})

export async function validateTokenInput(ctx: HttpContextContract) {
  const payload = await ctx.validate({
    schema: tokenSchema,
    messages: {
      'token.alpha': 'Invalid token format'
    }
  })
  return payload.token
}

4. Enforce short lifetimes and secure transmission

Issue short-lived JWTs and use HTTPS everywhere. Configure CORS strictly and avoid embedding tokens in URLs.

// In a route handler
const token = jwt.sign({ sub: user.id, scope: 'api:read' }, Env.get('JWT_SECRET'), {
  expiresIn: '10m'
})

// Return token in an HttpOnly, Secure cookie or in an Authorization header only
ctx.response.header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains')
ctx.response.json({ token })

5. Rotate secrets and audit usage

Plan for secret rotation and monitor for unexpected token usage patterns. MiddleBrick scans can surface inconsistencies between declared OAuth flows and actual runtime behavior, helping you detect leakage early.

Frequently Asked Questions

Can JWT tokens be safely passed in URL query parameters in AdonisJS?
No. Passing JWTs in URLs exposes tokens in server logs, browser history, and Referer headers, increasing phishing and leakage risk. Use HTTP-only, Secure cookies or the Authorization header instead.
How do I prevent API keys used for JWT signing from being phished via source code or logs?
Store keys exclusively in environment variables, never commit them to version control, and avoid logging raw secrets or tokens. Use asymmetric keys (RS256) so verification can be public while signing remains private.