Api Key Exposure in Adonisjs with Openid Connect
Api Key Exposure in Adonisjs with Openid Connect — how this specific combination creates or exposes the vulnerability
When an AdonisJS application exposes API keys through an OpenID Connect (OIDC) integration, it typically stems from insecure handling of tokens, client secrets, or callback parameters. AdonisJS often uses packages such as @adonisjs/oauth to manage OIDC flows, where the application acts as an OAuth 2.0 client. Misconfigured routes or overly permissive session storage can lead to API keys being leaked in URLs, logs, or browser history.
Consider an OIDC callback route that receives an authorization code and exchanges it for tokens. If the client secret or an API key is passed as a query parameter instead of using HTTPS-backed token endpoints with proper authentication, tools run by middleBrick can detect this exposure during its unauthenticated scan. For example, logging the entire request query in development mode might inadvertently print the code verifier or state parameter that contains sensitive material.
Insecure patterns include storing client secrets in environment files with weak file permissions, or embedding API keys directly in frontend JavaScript that communicates with AdonisJS endpoints. middleBrick’s checks for Data Exposure and Unsafe Consumption would flag such practices, especially when sensitive values appear in URLs or unencrypted logs. The scanner does not assume internal context; it observes what is reachable and reports findings with severity and remediation guidance.
Another common scenario involves improper redirect URI validation in OIDC flows. If an AdonisJS application accepts arbitrary redirect URIs, an attacker might capture authorization codes or tokens that include embedded keys. middleBrick’s Authentication and BOLA/IDOR checks look for missing validation on redirect parameters and missing proof-of-possession for tokens, which can reveal paths where API keys are exposed unintentionally.
SSRF (Server-Side Request Forgery) risks also intersect with OIDC in AdonisJS. If the application dynamically constructs OIDC discovery URLs using user-supplied input without strict allowlisting, an attacker can force internal endpoints to reveal metadata that includes API keys or tokens. middleBrick’s SSRF testing probes parameter-driven URL construction and flags endpoints that reach unexpected internal services.
Finally, inadequate rate limiting on token exchange endpoints can enable credential stuffing or token enumeration attacks. middleBrick’s Rate Limiting check examines whether token-related endpoints enforce reasonable request caps. When combined with weak logging, repeated probing might expose patterns that reveal API key usage within error messages returned by AdonisJS routes.
Openid Connect-Specific Remediation in Adonisjs — concrete code fixes
To remediate API key exposure in AdonisJS with OpenID Connect, start by ensuring all OIDC communication uses HTTPS and avoids passing sensitive material in URLs. Use the Authorization Code flow with PKCE instead of implicit flows, and keep client secrets stored securely outside the web root.
Example of a secure OIDC configuration in AdonisJS using @adonisjs/oauth:
import { oidcConfig } from '@adonisjs/oauth/build/oidc/main'
import Env from '@ioc:Adonis/Core/Env'
export const authConfig = {
driver: 'oidc',
clientId: Env.get('OIDC_CLIENT_ID'),
clientSecret: Env.get('OIDC_CLIENT_SECRET'),
authorizationEndpoint: 'https://auth.example.com/oauth/authorize',
tokenEndpoint: 'https://auth.example.com/oauth/token',
userInfoEndpoint: 'https://auth.example.com/oauth/userinfo',
redirectUri: 'https://app.example.com/oauth/callback',
scope: ['openid', 'profile', 'email'],
pkce: true,
responseType: 'code',
prompt: 'consent',
extraParams: new URLSearchParams({
acr_values: 'urn:mace:incommon:iap:silver',
}),
}
Ensure that redirectUri is registered exactly with the OIDC provider and avoid using dynamic or user-supplied values. Validate state and nonce parameters rigorously:
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import { validateOIDCState } from 'Validator'
export default class OauthController {
public async callback({ request, response, session }: HttpContextContract) {
const state = request.input('state')
const nonce = request.input('nonce')
if (!validateOIDCState(state) || !validateOIDCNonce(nonce)) {
session.flash('error', 'Invalid OIDC parameters')
return response.redirect('/login')
}
// Exchange code for tokens using server-side POST with client secret in Authorization header
const tokens = await this.exchangeCodeForToken(request.input('code'))
session.put('oidc_tokens', tokens)
return response.redirect('/dashboard')
}
private async exchangeCodeForToken(code: string) {
const client = new HttpClient()
const response = await client.post('https://auth.example.com/oauth/token', {
data: {
grant_type: 'authorization_code',
code,
redirect_uri: 'https://app.example.com/oauth/callback',
},
auth: {
username: Env.get('OIDC_CLIENT_ID'),
password: Env.get('OIDC_CLIENT_SECRET'),
},
})
return response.body
}
}
Store client secrets and API keys in environment variables with strict file permissions, and avoid logging request parameters that may contain sensitive values. Use middleware to scrub sensitive data from logs:
import { ExceptionHandler } from '@ioc:Adonis/Core/ExceptionHandler'
export default class CustomExceptionHandler extends ExceptionHandler {
public handle(error: any, ctx: HttpContextContract) {
if (error && error.message) {
const sanitized = error.message
.replace(new RegExp(Env.get('OIDC_CLIENT_SECRET', ''), 'g'), '[REDACTED]')
.replace(/authorization_code=[^&]*/g, 'authorization_code=[REDACTED]')
// Log sanitized error
}
return super.handle(error, ctx)
}
}
Implement strict Content Security Policy and referrer policies to reduce the risk of tokens being sent in Referer headers:
import { middleware } from '@adonisjs/core'
const securityHeaders = middleware(() => {
return {
'Content-Security-Policy': "default-src 'self'; script-src 'self' 'unsafe-inline';",
'Referrer-Policy': 'strict-origin-when-cross-origin',
}
})
middleBrick’s GitHub Action can be used to enforce that future changes do not reintroduce insecure OIDC configurations. By scanning your repository, it checks for hardcoded secrets and missing PKCE usage, integrating these checks into your CI/CD pipeline.