monacousa-portal/PASSWORD_RESET_FIX_SUMMARY.md

3.5 KiB

Password Reset Fix - Implementation Summary

Problem

The password reset functionality was failing with a 500 error because the portal client (monacousa-portal) was being used to access Keycloak's Admin API, but it didn't have the necessary permissions to execute admin operations like sending password reset emails.

Root Cause

The original implementation was using the portal client credentials for both:

  1. User authentication (correct usage)
  2. Admin operations like password reset (incorrect - needs admin permissions)

Error from logs:

❌ Failed to send reset email: 500
Reset email error details: {"errorMessage":"Failed to send execute actions email: Error when attempting to send the email to the server. More information is available in the server log."}

Solution

Implemented a dedicated admin client approach using Keycloak's admin-cli client:

1. Keycloak Configuration

  • Enabled "Client authentication" for admin-cli client
  • Enabled "Service accounts roles"
  • Assigned realm-management roles:
    • view-users
    • manage-users
    • query-users
  • Generated client secret

2. Environment Variables

Added new admin client configuration:

NUXT_KEYCLOAK_ADMIN_CLIENT_ID=admin-cli
NUXT_KEYCLOAK_ADMIN_CLIENT_SECRET=your-admin-cli-secret

3. Code Changes

Files Modified:

  • nuxt.config.ts - Added keycloakAdmin runtime config
  • .env.example - Documented new environment variables
  • utils/types.ts - Added KeycloakAdminConfig interface
  • server/utils/keycloak-admin.ts - NEW Admin client utility
  • server/api/auth/forgot-password.post.ts - Updated to use admin client

Key Fix:

Before (broken):

// Using portal client for admin operations (no permissions)
body: new URLSearchParams({
  grant_type: 'client_credentials',
  client_id: config.keycloak.clientId,        // monacousa-portal
  client_secret: config.keycloak.clientSecret // portal secret
})

After (working):

// Using admin client for admin operations (has permissions)
body: new URLSearchParams({
  grant_type: 'client_credentials',
  client_id: config.keycloakAdmin.clientId,     // admin-cli
  client_secret: config.keycloakAdmin.clientSecret // admin secret
})

4. Enhanced Error Handling

Added specific handling for:

  • Permission errors (403/Forbidden)
  • SMTP server errors (500)
  • Timeout errors
  • User not found scenarios

5. Security Improvements

  • Always return generic success messages (don't reveal if email exists)
  • Enhanced logging for debugging
  • Proper error categorization
  • Rate limiting considerations documented

Architecture

Password Reset Flow:
1. User submits email via forgot password form
2. Server validates email format
3. Server creates Keycloak admin client
4. Admin client obtains admin token using admin-cli credentials
5. Admin client searches for user by email
6. If user found, admin client sends password reset email
7. Server always returns generic success message

Benefits

  • Password reset emails now work properly
  • Proper separation of concerns (portal vs admin operations)
  • Enhanced security and error handling
  • Better logging for troubleshooting
  • Maintainable admin utility for future admin operations

Testing

To test the fix:

  1. Navigate to login page
  2. Click "Forgot Password"
  3. Enter valid email address
  4. Check email inbox for reset link
  5. Verify server logs show successful operation

Future Enhancements

  • Rate limiting on forgot password endpoint
  • CAPTCHA integration
  • Admin dashboard for user management
  • Email template customization