project-nomad/admin/app/services/admin_auth_service.ts

49 lines
1.3 KiB
TypeScript

import { timingSafeEqual } from 'node:crypto'
import env from '#start/env'
const FALLBACK_ADMIN_USER = 'admin'
export default class AdminAuthService {
/**
* Resolve the configured admin username. The password must still be provided
* with ADMIN_PASS before login is enabled.
*/
static user(): string {
return env.get('ADMIN_USER', FALLBACK_ADMIN_USER).trim() || FALLBACK_ADMIN_USER
}
/**
* Admin login is disabled until ADMIN_PASS has a non-empty value.
*/
static isConfigured(): boolean {
return Boolean(env.get('ADMIN_PASS')?.trim())
}
/**
* Compare supplied credentials to environment-controlled credentials.
*/
static authenticate(user: string, password: string): boolean {
const configuredPassword = env.get('ADMIN_PASS')?.trim()
if (!configuredPassword) {
return false
}
return (
this.secureCompare(user, this.user()) &&
this.secureCompare(password, configuredPassword)
)
}
private static secureCompare(input: string, expected: string): boolean {
const inputBuffer = Buffer.from(input)
const expectedBuffer = Buffer.from(expected)
if (inputBuffer.length !== expectedBuffer.length) {
return false
}
return timingSafeEqual(inputBuffer, expectedBuffer)
}
}