Missing Authentication in Adonisjs with Mutual Tls
Missing Authentication in Adonisjs with Mutual Tls — how this specific combination creates or exposes the vulnerability
Mutual Transport Layer Security (mTLS) requires both the client and the server to present valid certificates during the TLS handshake. In Adonisjs, mTLS is typically enforced at the infrastructure or proxy layer (e.g., Nginx, Envoy, or a load balancer) and not directly in application code. When authentication is missing or misconfigured in this setup, the API can be exposed even though mTLS appears to be in place.
Consider a deployment where Adonisjs runs behind a reverse proxy that handles mTLS verification. If the proxy is configured to forward requests without validating the client certificate or if the Adonisjs route definitions do not require authentication, an unauthenticated request can reach the application layer. This often occurs when developers assume mTLS alone is sufficient for authorization, but mTLS only establishes identity, not permissions. Without explicit route-level or policy-based checks in Adonisjs, any client that presents a valid certificate (or bypasses certificate validation) can access protected endpoints.
For example, an Adonisjs route defined as Route.get('/users/:id', 'UsersController.show') with no authentication guard can be invoked by any mTLS-enabled client. If the proxy does not enforce strict client certificate verification or if the certificate validation is downgraded to 'optional,' an attacker could connect with a self-signed or revoked certificate that the proxy accepts. The request then reaches Adonisjs as authenticated, but the application has no additional check to confirm scope, role, or consent. This gap between transport-layer identity and application-layer authorization is a common cause of Missing Authentication in mTLS environments.
In a black-box scan, middleBrick tests for Missing Authentication by probing endpoints that should require credentials while operating without them. It checks whether sensitive operations or data are exposed when no valid authentication context is provided, even when mTLS is negotiated. Findings include missing route guards, overly permissive proxy configurations, and lack of scope validation in Adonisjs controllers, all of which can lead to unauthorized data access or operations.
Mutual Tls-Specific Remediation in Adonisjs — concrete code fixes
To secure Adonisjs applications in an mTLS environment, combine robust proxy configuration with explicit route and policy enforcement. Below are concrete steps and code examples.
1. Enforce client certificate validation at the proxy
Ensure your reverse proxy (e.g., Nginx) is configured to require and verify client certificates. Example Nginx snippet:
server {
listen 443 ssl;
ssl_certificate /etc/ssl/certs/server.crt;
ssl_certificate_key /etc/ssl/private/server.key;
ssl_verify_client on;
ssl_client_certificate /etc/ssl/certs/ca.crt;
location / {
proxy_pass http://localhost:3333;
proxy_set_header X-SSL-Client-Verify $ssl_client_verify;
proxy_set_header X-SSL-Client-DN $ssl_client_s_dn;
}
}
This configuration rejects requests without a valid client certificate signed by the trusted CA. The headers X-SSL-Client-Verify and X-SSL-Client-DN can be used in Adonisjs for logging or supplemental checks, but should not replace route guards.
2. Add route-level authentication guards in Adonisjs
Use Adonisjs auth providers to enforce authentication on sensitive routes. For example, with the default session provider:
// start/routes.ts
import Route from '@ioc:Adonis/Core/Route'
Route.group(() => {
Route.get('/users/me', 'UsersController.me').middleware(['auth'])
Route.resource('users', 'UsersController').apiOnly().middleware({ only: ['index', 'show'], middlewares: ['auth'] })
}).prefix('api/v1')
For token-based scenarios (e.g., JWT), use the jwt middleware:
// start/routes.ts
import Route from '@ioc:Adonis/Core/Route'
import jwtMiddleware from 'ioc:middleware/jwt'
Route.get('/admin', 'AdminController.index').middleware([jwtMiddleware])
Ensure your middleware pipeline validates the presence and correctness of credentials on every request, regardless of mTLS status.
3. Validate scopes and roles within controllers
Even with mTLS and route guards, validate that the authenticated principal has the right scope or role. Example in a controller:
// app/Controllers/Http/UsersController.ts
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class UsersController {
public async show({ params, auth }: HttpContextContract) {
const user = await auth.authenticate()
if (!user.canView(params.id)) {
throw new ResponseStatusException('forbidden', 'You cannot view this resource')
}
return User.findOrFail(params.id)
}
}
This ensures that identity established by mTLS is further constrained by application-level permissions.
4. Reject requests with missing or invalid client certs at the app layer (defense in depth)
In Adonisjs, you can add a global middleware to verify that the request includes a valid client identity when required:
// app/Middleware/RequireMtls.ts
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class RequireMtls {
public async handle(ctx: HttpContextContract, next: () => Promise) {
const clientCert = ctx.request.header('x-ssl-client-verify')
if (process.env.NODE_ENV === 'production' && clientCert !== 'SUCCESS') {
ctx.response.status = 400
response.body = { error: 'mTLS client certificate required' }
return
}
await next()
}
}
Register this middleware selectively for routes that demand strict mTLS validation.
Related CWEs: authentication
| CWE ID | Name | Severity |
|---|---|---|
| CWE-287 | Improper Authentication | CRITICAL |
| CWE-306 | Missing Authentication for Critical Function | CRITICAL |
| CWE-307 | Brute Force | HIGH |
| CWE-308 | Single-Factor Authentication | MEDIUM |
| CWE-309 | Use of Password System for Primary Authentication | MEDIUM |
| CWE-347 | Improper Verification of Cryptographic Signature | HIGH |
| CWE-384 | Session Fixation | HIGH |
| CWE-521 | Weak Password Requirements | MEDIUM |
| CWE-613 | Insufficient Session Expiration | MEDIUM |
| CWE-640 | Weak Password Recovery | HIGH |