Insufficient Logging in Adonisjs with Basic Auth
Insufficient Logging in Adonisjs with Basic Auth — how this specific combination creates or exposes the vulnerability
AdonisJS provides built-in authentication helpers, and when Basic Auth is used without additional logging, several security-relevant events are not recorded. Insufficient Logging becomes a finding when authentication successes and failures, token or credential validation results, and authorization denials are not captured with enough context to support incident investigation or anomaly detection.
With Basic Auth, credentials are transmitted on every request (base64-encoded). If the application does not log authentication outcomes, an attacker can probe credentials without leaving a trace in application logs. Useful audit dimensions include: timestamp, source IP, user identifier (if derivable from the credential), requested path, HTTP method, response status, and whether the credential was valid. Without these, defenders cannot reliably detect credential stuffing, brute-force attempts, or lateral movement after a successful compromise.
In AdonisJS, the Auth module can be configured to use a custom driver. If the driver’s verify method only returns a user or throws an error without emitting structured logs, critical events are lost. For example, a verify function that compares a plaintext password against a hashed value should log both failure and success outcomes, including the route and the identifier used (e.g., username or email). Logging only errors (e.g., database connection issues) while omitting auth outcomes creates a gap that scanning tools flag as Insufficient Logging.
When combined with unauthenticated scan capabilities, middleBrick tests endpoints that use Basic Auth and checks whether authentication events are recorded with actionable detail. The scanner inspects whether logs contain elements such as: timestamp, client IP, username/identifier, endpoint, method, and outcome. If these are consistently missing, the scanner reports Insufficient Logging with guidance to enrich audit records and ensure logs are protected against tampering.
Basic Auth-Specific Remediation in Adonisjs — concrete code fixes
To address Insufficient Logging while using HTTP Basic Auth in AdonisJS, enrich your custom auth driver to emit structured log entries for each authentication attempt. Below is a complete, syntactically correct example that logs successes and failures with relevant context.
1. Install dependencies (if not already present)
npm install @adonisjs/auth @adonisjs/core pino
2. Create a custom auth driver with logging (start/src/providers/AuthProvider.ts)
import { BaseProvider } from '@adonisjs/core/providers'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import Logger from '@ioc:Adonis/Core/Logger'
export default class AuthProvider extends BaseProvider {
public async register() {
// No-op
}
public async boot() {
this.app.container.singleton('auth:basic', async () => {
const guard = this.app.container.make('auth').getGuard('basic')
return {
guard,
verify: async (inputUser: { username: string; password: string }, ctx: HttpContextContract) => {
try {
const user = await guard.verify(inputUser.username, inputUser.password)
// Log successful authentication
Logger.info('auth:success', {
timestamp: new Date().toISOString(),
ip: ctx.request.ip(),
method: ctx.request.method(),
path: ctx.request.url(),
identifier: inputUser.username,
outcome: 'success',
})
return user
} catch (error) {
// Log failed authentication
Logger.warn('auth:failure', {
timestamp: new Date().toISOString(),
ip: ctx.request.ip(),
method: ctx.request.method(),
path: ctx.request.url(),
identifier: inputUser.username,
outcome: 'failure',
error: error instanceof Error ? error.message : 'unknown',
})
// Re-throw to let AdonisJS handle the response (e.g., 401)
throw error
}
},
}
})
}
}
3. Configure the driver in config/auth.ts
import { BasicAuthProvider } from 'App/Providers/auth'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import { BaseProviderConfig } from '@ioc:Adonis/Core/ProvidersManager'
const BasicAuthConfig: BaseProviderConfig = {
guard: 'basic',
provider: BasicAuthProvider,
}
export default BasicAuthConfig
4. Example login route that triggers the driver (start/routes.ts)
import Route from '@ioc:Adonis/Core/Route'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
Route.get('/protected', async ({ auth, response }: HttpContextContract) => {
// This will invoke the custom driver's verify method and produce logs
await auth.use('basic').authenticate()
return response.ok({ message: 'Authenticated' })
})
Route.post('/login', async ({ request, auth, response }: HttpContextContract) => {
const username = request.input('username')
const password = request.input('password')
try {
await auth.use('basic').verify({ username, password }, request)
return response.ok({ message: 'Login successful' })
} catch {
return response.unauthorized()
}
})
5. Verify logging output (example pino line)
{"level":30,"time":1717000000000,"pid":1234,"hostname":"host","msg":"auth:success","ip":"203.0.113.45","method":"GET","path":"/protected","identifier":"jdoe","outcome":"success"}
Key points in the remediation:
- Log both success and failure with timestamp, IP, method, path, identifier, and outcome.
- Use structured fields to enable log aggregation and alerting (e.g., repeated failures from the same IP or identifier).
- Avoid logging passwords or secrets; log only metadata necessary for detection.
- Ensure logs are stored securely and retained according to policy to support forensic analysis.
By implementing this pattern, the application remains detectable by middleBrick’s checks for Insufficient Logging while maintaining secure handling of Basic Auth credentials.