feat(auth): implement Android refresh token handling and session management
- 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.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { readUsers, writeUsers, verifyPassword, generateToken, createSession, migrateUserRoles } from '../../utils/auth.js'
|
||||
import { readUsers, writeUsers, verifyPassword, generateToken, generateAndroidAccessToken, createSession, createRefreshSession, migrateUserRoles } from '../../utils/auth.js'
|
||||
import { assertRateLimit, getClientIp, registerRateLimitFailure, registerRateLimitSuccess } from '../../utils/rate-limit.js'
|
||||
import { getAuthCookieOptions } from '../../utils/cookies.js'
|
||||
import { writeAuditLog } from '../../utils/audit-log.js'
|
||||
@@ -7,6 +7,7 @@ export default defineEventHandler(async (event) => {
|
||||
try {
|
||||
const body = await readBody(event)
|
||||
const { email, password } = body
|
||||
const isAndroidClient = body.client === 'android'
|
||||
|
||||
if (!email || !password) {
|
||||
throw createError({
|
||||
@@ -72,11 +73,15 @@ export default defineEventHandler(async (event) => {
|
||||
registerRateLimitSuccess(event, { name: 'auth:login:ip', keyParts: [ip] })
|
||||
registerRateLimitSuccess(event, { name: 'auth:login:account', keyParts: [emailKey] })
|
||||
|
||||
// Generate token
|
||||
const token = generateToken(user)
|
||||
|
||||
// Create session
|
||||
await createSession(user.id, token)
|
||||
let token
|
||||
let refreshSession = null
|
||||
if (isAndroidClient) {
|
||||
refreshSession = await createRefreshSession(user.id, body.deviceName)
|
||||
token = generateAndroidAccessToken(user, refreshSession.session.id)
|
||||
} else {
|
||||
token = generateToken(user)
|
||||
await createSession(user.id, token)
|
||||
}
|
||||
|
||||
await writeAuditLog('auth.login.success', { ip, email: emailKey, userId: user.id })
|
||||
|
||||
@@ -85,10 +90,13 @@ export default defineEventHandler(async (event) => {
|
||||
const updatedUsers = users.map(u => u.id === user.id ? user : u)
|
||||
await writeUsers(updatedUsers)
|
||||
|
||||
// Set cookie
|
||||
setCookie(event, 'auth_token', token, {
|
||||
...getAuthCookieOptions()
|
||||
})
|
||||
if (isAndroidClient) {
|
||||
deleteCookie(event, 'auth_token')
|
||||
} else {
|
||||
setCookie(event, 'auth_token', token, {
|
||||
...getAuthCookieOptions()
|
||||
})
|
||||
}
|
||||
|
||||
// Migriere Rollen falls nötig
|
||||
const migratedUser = migrateUserRoles({ ...user })
|
||||
@@ -98,6 +106,9 @@ export default defineEventHandler(async (event) => {
|
||||
return {
|
||||
success: true,
|
||||
token: token, // Token auch im Body für externe API-Clients
|
||||
accessToken: isAndroidClient ? token : undefined,
|
||||
refreshToken: refreshSession?.refreshToken,
|
||||
sessionId: refreshSession?.session.id,
|
||||
user: {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
@@ -112,4 +123,3 @@ export default defineEventHandler(async (event) => {
|
||||
throw error
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user