You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
53 lines
1.6 KiB
53 lines
1.6 KiB
/**
|
|
* Basic Authentication Middleware for /internal/* routes
|
|
* Protects internal pages (styleguide, admin tools) with HTTP Basic Auth
|
|
*/
|
|
|
|
export default defineEventHandler((event) => {
|
|
const path = event.path
|
|
|
|
// Only protect /internal/* routes
|
|
if (!path.startsWith('/internal')) {
|
|
return
|
|
}
|
|
|
|
const config = useRuntimeConfig()
|
|
|
|
// Get credentials from environment variables
|
|
const validUsername = config.internalAuthUsername
|
|
const validPassword = config.internalAuthPassword
|
|
|
|
// Skip auth if credentials are not configured (development convenience)
|
|
if (!validUsername || !validPassword) {
|
|
console.warn('⚠️ INTERNAL_AUTH_USERNAME or INTERNAL_AUTH_PASSWORD not set. /internal routes are unprotected!')
|
|
return
|
|
}
|
|
|
|
// Get Authorization header
|
|
const authHeader = getHeader(event, 'authorization')
|
|
|
|
if (!authHeader || !authHeader.startsWith('Basic ')) {
|
|
// Request authentication
|
|
setHeader(event, 'WWW-Authenticate', 'Basic realm="Internal Area"')
|
|
throw createError({
|
|
statusCode: 401,
|
|
statusMessage: 'Authentication required',
|
|
})
|
|
}
|
|
|
|
// Decode credentials
|
|
const base64Credentials = authHeader.split(' ')[1]
|
|
const credentials = Buffer.from(base64Credentials, 'base64').toString('utf-8')
|
|
const [username, password] = credentials.split(':')
|
|
|
|
// Validate credentials
|
|
if (username !== validUsername || password !== validPassword) {
|
|
setHeader(event, 'WWW-Authenticate', 'Basic realm="Internal Area"')
|
|
throw createError({
|
|
statusCode: 401,
|
|
statusMessage: 'Invalid credentials',
|
|
})
|
|
}
|
|
|
|
// Authentication successful, continue
|
|
})
|
|
|