- Added support for generating Android access tokens and managing refresh sessions in the auth endpoints. - Implemented new tests for login, logout, and refresh functionalities specific to Android clients. - Enhanced password reset logging with normalization and masking of email addresses. - Created a new diagnostics endpoint for password reset attempts, including filtering and summarizing logs. - Introduced a new utility for managing password reset logs with retention policies. - Added tests for password reset log utilities to ensure proper functionality and privacy compliance. - Updated WebAuthn configuration tests to validate origin handling for production and allowed origins.
48 lines
1.9 KiB
JavaScript
48 lines
1.9 KiB
JavaScript
import { generateAndroidAccessToken, getUserById, revokeRefreshSession, rotateRefreshSession } from '../../utils/auth.js'
|
|
import { assertRateLimit, getClientIp, registerRateLimitFailure, registerRateLimitSuccess } from '../../utils/rate-limit.js'
|
|
import { writeAuditLog } from '../../utils/audit-log.js'
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
const ip = getClientIp(event)
|
|
const body = await readBody(event)
|
|
const refreshToken = body?.refreshToken
|
|
|
|
if (!refreshToken) {
|
|
throw createError({ statusCode: 400, message: 'Refresh-Token fehlt' })
|
|
}
|
|
|
|
assertRateLimit(event, {
|
|
name: 'auth:refresh:ip',
|
|
keyParts: [ip],
|
|
windowMs: 10 * 60 * 1000,
|
|
maxAttempts: 60,
|
|
lockoutMs: 15 * 60 * 1000
|
|
})
|
|
|
|
const rotated = await rotateRefreshSession(refreshToken)
|
|
if (rotated.status !== 'rotated') {
|
|
await registerRateLimitFailure(event, { name: 'auth:refresh:ip', keyParts: [ip], delayBaseMs: 100 })
|
|
await writeAuditLog('auth.refresh.failed', { ip, reason: rotated.status })
|
|
throw createError({ statusCode: 401, message: 'Sitzung ist nicht mehr gültig' })
|
|
}
|
|
|
|
const user = await getUserById(rotated.session.userId)
|
|
if (!user || user.active === false) {
|
|
await revokeRefreshSession(rotated.refreshToken, 'inactive_or_missing_user')
|
|
await writeAuditLog('auth.refresh.failed', { ip, userId: rotated.session.userId, reason: 'inactive_or_missing_user' })
|
|
throw createError({ statusCode: 401, message: 'Sitzung ist nicht mehr gültig' })
|
|
}
|
|
|
|
const accessToken = generateAndroidAccessToken(user, rotated.session.id)
|
|
registerRateLimitSuccess(event, { name: 'auth:refresh:ip', keyParts: [ip] })
|
|
await writeAuditLog('auth.refresh.success', { ip, userId: user.id, sessionId: rotated.session.id })
|
|
|
|
return {
|
|
success: true,
|
|
token: accessToken,
|
|
accessToken,
|
|
refreshToken: rotated.refreshToken,
|
|
sessionId: rotated.session.id
|
|
}
|
|
})
|