From a3869425c531e7f4ab2e2fe354cc08409256a4e6 Mon Sep 17 00:00:00 2001 From: Paul Nothaft Date: Mon, 5 Jan 2026 23:07:38 +0100 Subject: [PATCH] fix: Convert PHP $2y$ bcrypt hashes to $2a$ for Node.js compatibility PHP uses $2y$ variant which Node.js bcrypt may not support directly. Convert to $2a$ which is functionally equivalent. --- backend/src/services/auth.service.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/backend/src/services/auth.service.js b/backend/src/services/auth.service.js index fce8583..76e2104 100644 --- a/backend/src/services/auth.service.js +++ b/backend/src/services/auth.service.js @@ -33,6 +33,13 @@ class AuthService { hash = hash.trim().replace(/^["']|["']$/g, ''); } + // Convert PHP's $2y$ to $2a$ for Node.js bcrypt compatibility + // $2y$ is PHP-specific and may not be supported by all bcrypt implementations + if (hash && hash.startsWith('$2y$')) { + hash = '$2a$' + hash.substring(4); + logger.debug('Converted $2y$ hash to $2a$ for compatibility'); + } + // Debug logging for troubleshooting logger.debug('Password verification attempt', { hashExists: !!hash, @@ -48,15 +55,16 @@ class AuthService { } // Validate hash format (bcrypt hashes start with $2a$, $2b$, or $2y$) - if (!hash.match(/^\$2[aby]\$\d{2}\$/)) { + if (!hash.match(/^\$2[ab]\$\d{2}\$/)) { logger.error('Invalid bcrypt hash format - hash may be corrupted by environment variable interpolation', { hashPrefix: hash.substring(0, 20), - expectedFormat: '$2b$12$... or $2y$10$...' + expectedFormat: '$2b$12$... or $2a$10$...' }); return false; } const isValid = await bcrypt.compare(password, hash); + logger.debug('Password comparison result', { isValid }); return isValid; } catch (error) { logger.error('Password verification error', {