HIGH auth bypassadonisjsapi keys

Auth Bypass in Adonisjs with Api Keys

Auth Bypass in Adonisjs with Api Keys — how this specific combination creates or exposes the vulnerability

AdonisJS does not provide a built-in API key authentication layer; developers typically implement API key validation in application code or via an authentication provider. When API keys are used, an auth bypass can occur if route guards rely on incomplete checks, such as verifying the key’s presence but not its scope, validity, or association with the requested resource. For example, a route may call auth.authenticate() with an API guard but skip additional authorization logic that confirms the key permits access to the specific endpoint or object.

In a black-box scan, middleBrick tests unauthenticated attack surfaces and can detect whether an API key–protected endpoint returns data when it should require scope-specific permissions. If a key intended for read-only analytics can access admin routes because the route does not enforce scope checks, this is an Auth Bypass/BOLA (Broken Access Control Level Authorization) pattern. AdonisJS applications that generate tokens with broad permissions or that fail to validate key bindings to the correct tenant or user can inadvertently expose sensitive operations.

Consider an endpoint that retrieves user data by ID. If the handler loads the user via User.findOrFail(params.id) and then checks only that a valid API key exists, a client can change the ID in the URL to access other users’ data. The API key is accepted, but the application does not verify whether the key’s owner is allowed to view that specific user record. This is a classic IDOR (Insecure Direct Object Reference) enabled by insufficient authorization tied to API key usage. The scan’s Authentication and BOLA/IDOR checks can surface such misconfigurations by probing endpoints with different keys and IDs to see if access control is enforced per request.

Additional risk patterns include endpoints that accept keys via headers or query parameters but do not enforce HTTPS, allowing interception; keys embedded in logs or URLs that leak via referrer or error messages; and keys with excessive privileges due to coarse-grained roles. middleBrick’s Property Authorization and Data Exposure checks evaluate whether responses contain sensitive fields (such as passwords or tokens) and whether encryption is enforced, highlighting weak spots in how API keys are handled within the request lifecycle.

Api Keys-Specific Remediation in Adonisjs — concrete code fixes

Secure API key handling in AdonisJS requires explicit validation of key ownership, scope, and usage context. Always treat API keys as credentials and enforce authorization checks after authentication. Below are concrete, working examples you can apply.

1. Define an API key model and relationship

Create an ApiKey model that references a user or client and includes fields like scope, expiresAt, and allowedRoutes. Define a relationship on the User model.

// app/Models/ApiKey.ts
import { DateTime } from 'luxon'
import { BaseModel, column, belongsTo } from '@ioc:Adonis/Lucid/Orm'
import User from './User'

export default class ApiKey extends BaseModel {
  @column({ isPrimary: true })
  public id: number

  @column()
  public keyHash: string

  @column()
  public scope: 'read' | 'write' | 'admin'

  @column.dateTime()
  public expiresAt: DateTime

  @column()
  public allowedRoutes?: string[]

  @belongsTo(() => User)
  public user: User
}

2. Create a custom auth provider for API key validation

Use AdonisJS provider files to implement lookup and verification without exposing raw keys.

// start/auth.ts
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import ApiKey from 'App/Models/ApiKey'
import { sha256 } from '@ioc:Adonis/Addons/hash'

export default class ApiKeyProvider {
  public async authenticate(request: HttpContextContract, providedKey: string): Promise {
    const keyHash = sha256.hash(providedKey)
    const apiKey = await ApiKey.query()
      .where('keyHash', keyHash)
      .where('expiresAt', '>', new Date())
      .preload('user')
      .first()

    if (!apiKey) {
      return false
    }

    // Attach key metadata to the request for downstream checks
    request.authUser = apiKey.user
    request.apiKeyScope = apiKey.scope
    request.apiKeyRoutes = apiKey.allowedRoutes
    return true
  }
}

3. Enforce scope and route checks in handlers

In your controller or middleware, verify that the key’s scope and allowed routes match the incoming request.

// controllers/UsersController.ts
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import User from 'App/Models/User'

export default class UsersController {
  public async show({ params, request, response }: HttpContextContract) {
    const user = await User.findOrFail(params.id)

    // Scope check: ensure key has at least 'read' scope
    const scope = request.apiKeyScope
    if (!scope || (scope !== 'read' && scope !== 'write' && scope !== 'admin')) {
      return response.forbidden({ message: 'Insufficient scope' })
    }

    // Optional route-specific allowlist
    const allowedRoutes = request.apiKeyRoutes
    if (allowedRoutes && !allowedRoutes.includes(request.url())) {
      return response.forbidden({ message: 'Route not permitted for this key' })
    }

    // Prevent IDOR: ensure the key owner is allowed to view this user
    if (scope === 'read' && request.authUser?.id !== user.id) {
      return response.forbidden({ message: 'Access to this resource denied' })
    }

    return user
  }
}

4. Rotate keys and avoid query parameters

Store keys in headers (e.g., X-API-Key) rather than query strings to reduce leakage in logs. Implement key rotation and revocation endpoints, and hash keys before storage using a strong one-way hash.

5. Integrate with middleware

Apply the auth check globally or per route group to centralize enforcement.

// start/routes.ts
import Route from '@ioc:Adonis/Core/Route'
import ApiKey from 'App/Models/ApiKey'

Route.group(() => {
  Route.get('/users/:id', 'UsersController.show')
}).middleware('apikey') // ensure middleware triggers the provider above

These steps ensure API keys are validated, scoped, and checked against business rules, reducing the likelihood of auth bypass and IDOR in AdonisJS applications.

Related CWEs: authentication

CWE IDNameSeverity
CWE-287Improper Authentication CRITICAL
CWE-306Missing Authentication for Critical Function CRITICAL
CWE-307Brute Force HIGH
CWE-308Single-Factor Authentication MEDIUM
CWE-309Use of Password System for Primary Authentication MEDIUM
CWE-347Improper Verification of Cryptographic Signature HIGH
CWE-384Session Fixation HIGH
CWE-521Weak Password Requirements MEDIUM
CWE-613Insufficient Session Expiration MEDIUM
CWE-640Weak Password Recovery HIGH

Frequently Asked Questions

How can I test my AdonisJS API for auth bypass without a pentest vendor?
You can run an unauthenticated scan with middleBrick to check whether endpoints return data when they should enforce scope or ownership. The scan tests Authentication, BOLA/IDOR, and Property Authorization to surface missing checks.
Does middleBrick fix the auth bypass findings it detects?
middleBrick detects and reports findings with remediation guidance; it does not fix, patch, block, or remediate. Use the provided guidance to update validation, scope checks, and key handling in your AdonisJS code.