HIGH api key exposureadonisjsbasic auth

Api Key Exposure in Adonisjs with Basic Auth

Api Key Exposure in Adonisjs with Basic Auth — how this specific combination creates or exposes the vulnerability

AdonisJS applications that rely on HTTP Basic Authentication can inadvertently expose API keys when credentials are handled inconsistently across middleware, logging, and error handling. Basic Auth transmits credentials on each request using the Authorization: Basic base64(username:password) header. If the application treats the decoded credentials as an API key or uses the same secret for both authentication and key-based authorization, an attacker who intercepts or logs the header can obtain a long-lived key.

In AdonisJS, a common pattern uses the auth:basic provider to validate users against the database. If route guards or permission checks then reuse the authenticated user’s token or an embedded key from the database record as an API key, any misconfiguration in request logging or error reporting can leak that key. For example, if unauthenticated or improperly namespaced endpoints echo request headers for debugging, the Base64–encoded credentials may be captured in logs or browser developer tools. Because Base64 is reversible, the exposure of the header effectively exposes the credentials, which may function as an API key if the backend treats them as such.

Another vector arises when AdonisJS applications proxy requests to internal services and forward the incoming Authorization header without stripping or transforming it. If the downstream service interprets the Basic Auth credentials as an API key (for example, by mapping the username to a service account key), an unauthenticated attacker who reaches the proxy endpoint can enumerate valid credentials through rate-limited probing or SSRF-assisted scans. The risk is compounded when the same secret is used for both HTTP Basic Authentication and third-party service authentication, creating a path where exposure of one vector compromises multiple systems.

The OpenAPI/Swagger analysis performed by middleBrick highlights these risks by correlating spec definitions with runtime behavior. When an endpoint declares security schemes using httpBasic but also references bearer-like scopes or custom headers that carry key-like values, the scanner flags potential credential-to-key reuse. Cross-referencing spec definitions with runtime findings can reveal whether responses inadvertently include authorization headers in error payloads or logs, which would constitute data exposure under frameworks such as OWASP API Top 10 and GDPR.

middleBrick’s 12 security checks run in parallel to detect issues like Data Exposure, Unsafe Consumption, and SSRF in this context. For instance, it tests whether unauthenticated responses reveal whether Basic Auth validation succeeded or failed in ways that disclose user existence, and whether error messages contain encoded credentials. Because scans are black-box and require no credentials, they can safely probe publicly reachable endpoints to identify leakage paths without impacting production systems.

When findings are surfaced in the Web Dashboard or tracked over time via the Dashboard, teams receive prioritized findings with severity ratings and remediation guidance. The CLI tool (middlebrick scan <url>) can be integrated into scripts to automate detection of misconfigurations, while the GitHub Action can enforce a security score threshold in CI/CD pipelines to prevent deployment of vulnerable configurations. For continuous protection, the Pro plan enables scheduled scans and alerts, ensuring that changes to authentication logic are reviewed before they reach production.

Basic Auth-Specific Remediation in Adonisjs — concrete code fixes

Remediation focuses on preventing the reuse of Basic Auth credentials as API keys, tightening logging, and ensuring that headers are not forwarded to downstream services. Below are concrete AdonisJS code examples that implement these controls.

1. Use dedicated authentication middleware that avoids exposing credentials as keys:

// start/hooks.ts
import { Exception } from '@poppinss/utils'

export const handleAuthErrors = (error: any) => {
  if (error.name === 'E_INVALID_CREDENTIALS') {
    return new Exception('Invalid credentials', 401, {
      code: 'E_INVALID_CREDENTIALS',
    })
  }
  return error
}

// app/Controllers/Http/auth.controller.ts
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import User from 'App/Models/User'
import { Exception } from '@poppinss/utils'

export default class AuthController {
  public async login({ request, auth, response }: HttpContextContract) {
    const { username, password } = request.only(['username', 'password'])
    const token = await auth.attempt(username, password)
    // Do NOT expose token as Basic Auth credentials
    return response.header('Authorization', '').json({ access_token: token })
  }
}

2. Configure the auth provider to use a custom resolver that does not map credentials to API keys:

// config/auth.ts
import { AuthConfig } from '@ioc:Adonis/Add/Auth'

const authConfig: AuthConfig = {
  defaults: {
    guard: 'api',
    usernameField: 'email',
  },
  guards: {
    api: {
      driver: 'jwt',
      key: process.env.API_JWT_SECRET,
      provider: 'users',
    },
    basic: {
      driver: 'basic',
      provider: 'users',
      // Use a separate field for key-like tokens, not credentials
      keyField: 'service_key',
    },
  },
  providers: {
    users: {
      driver: 'lucid',
      model: () => import('App/Models/User'),
    },
  },
}
export default authConfig

3. Strip sensitive headers before logging or forwarding requests:

// start/middleware/secure-headers.ts
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'

export default function secureHeadersMiddleware(ctx: HttpContextContract, next: () => Promise) {
  // Remove Authorization header before logging
  const safeHeaders = { ...ctx.request.headers() }
  delete safeHeaders.authorization
  ctx.logger.info('Incoming request', { headers: safeHeaders })
  return next()
}

4. In gateway or proxy scenarios, do not forward Basic Auth headers to downstream services; instead, exchange credentials for a scoped token:

// app/Services/ProxyService.ts
import fetch from 'node-fetch'

export default class ProxyService {
  async forward(url: string, userEmail: string, password: string) {
    const credentials = Buffer.from(`${userEmail}:${password}`).toString('base64')
    // Exchange credentials for an internal token, do not forward Authorization header
    const response = await fetch(url, {
      headers: {
        'X-Internal-Token': process.env.INTERNAL_TOKEN,
        'X-User-Email': userEmail,
      },
    })
    return response
  }
}

These steps reduce the likelihood that Basic Auth credentials are treated as or leaked as API keys. By isolating authentication from key-based authorization, sanitizing logs, and avoiding header propagation, you limit the attack surface even if credentials are exposed through other vectors.

Frequently Asked Questions

Can Basic Auth credentials be safely used as API keys in AdonisJS?
No. Reusing Basic Auth credentials as API keys increases the impact of exposure. If the header is intercepted or logged, both authentication and key-based access are compromised. Use separate secrets for authentication and API authorization, and avoid embedding keys in credentials.
How does middleBrick detect API key exposure risks in AdonisJS Basic Auth setups?
middleBrick scans public endpoints using 12 parallel checks, including Data Exposure and Unsafe Consumption, to identify whether authentication headers or key-like values appear in responses, logs, or error payloads. It correlates findings with OpenAPI/Swagger specs to detect mismatches between declared security schemes and runtime behavior.