DirectoryTree / LdapRecord-Laravel

Multi-domain LDAP Authentication & Management for Laravel.
https://ldaprecord.com/docs/laravel/v3
MIT License
509 stars 54 forks source link

[Support] Error with messages coming from "ldapDiagnosticCodeErrorMap()" method #380

Closed AlanBig closed 2 years ago

AlanBig commented 2 years ago

Environment:

Hi all!

I am developing an app, which makes use of the Fortify package and this wonderful LdapRecord package. I'm running into a problem when sending the messages to the view. I make use of the "Fortify::authenticateUsing()" method. My code is the following...

Fortify::authenticateUsing(function ($request) {

    $validated = Auth::validate([
        'userprincipalname' => $request->email,
        'password' => $request->password,
        'fallback' => [
            'email' => $request->email,
            'password' => $request->password,
        ],
    ]);

    return $validated ? Auth::getLastAttempted() : null;
});

Now the error I have is that when I disable an account in the AD, the message shown in the view is the following "ldap::errors.account_disabled" which from what I saw comes from the class "ListensForLdapBindFailure.php" of the method

protected function ldapDiagnosticCodeErrorMap()
{
    return [
        '525' => trans('ldap::errors.user_not_found'),
        '530' => trans('ldap::errors.user_not_permitted_at_this_time'),
        '531' => trans('ldap::errors.user_not_permitted_to_login'),
        '532' => trans('ldap::errors.password_expired'),
        '533' => trans('ldap::errors.account_disabled'),
        '701' => trans('ldap::errors.account_expired'),
        '773' => trans('ldap::errors.user_must_reset_password'),
        '775' => trans('ldap::errors.user_account_locked'),
    ];
}

If the mentioned method is modified as follows

protected function ldapDiagnosticCodeErrorMap()
{
    return [
        '525' => trans('ldap.user_not_found'),
        '530' => trans('ldap.user_not_permitted_at_this_time'),
        '531' => trans('ldap.user_not_permitted_to_login'),
        '532' => trans('ldap.password_expired'),
        '533' => trans('ldap.account_disabled'),
        '701' => trans('ldap.account_expired'),
        '773' => trans('ldap.user_must_reset_password'),
        '775' => trans('ldap.user_account_locked'),
    ];
}

The messages are displayed correctly, located in "\resources\lang\en\ldap.php"... Is there a way to rewrite the method, without having to modify the original class of the package, and thus avoid having to modify it every time the library is updated?

I also clarify that when I put the file "errors.php" in the path mentioned in the documentation, I keep getting the message "ldap::errors.account_disabled" in the view.

Greetings and thanks!

stevebauman commented 2 years ago

Hi @AlanBig! I'm so glad you've found LdapRecord useful 😄

Hmmm I think my documentation is incorrect -- can you try namespacing the errors.php file by creating it in the following path:

resources/lang/vendor/ldap/en/errors.php

Let me know if that works!

stevebauman commented 2 years ago

Oh okay the docs are actually correct: Screen Shot 2022-01-20 at 10 01 35 AM

Was there a place you saw this file path that I'm possibly missing?

AlanBig commented 2 years ago

Dear, thanks for the quick response! Unfortunately, it doesn't work for me, I can't understand why, but I'll tell you that I found an acceptable solution for me and that it can probably help someone else, I'll share it here...

use Illuminate\Validation\ValidationException;
use LdapRecord\Laravel\Auth\BindFailureListener;

BindFailureListener::setErrorHandler(function ($message, $code = null) {

    $message = 'ldap.' . explode('.', $message, 2)[1];

    switch ($code) {
        case '525':
            throw ValidationException::withMessages(['email' => trans($message)]);
            break;
        case '530':
            throw ValidationException::withMessages(['email' => trans($message)]);
            break;
        case '531':
            throw ValidationException::withMessages(['email' => trans($message)]);
            break;
        case '532':
            throw ValidationException::withMessages(['email' => trans($message)]);
            break;
        case '533':
            throw ValidationException::withMessages(['email' => trans($message)]);
            break;
        case '701':
            throw ValidationException::withMessages(['email' => trans($message)]);
            break;
        case '773':
            throw ValidationException::withMessages(['email' => trans($message)]);
            break;
        case '775':
            throw ValidationException::withMessages(['email' => trans($message)]);
            break;
    }
});

In this way, it will now be much easier to translate messages, just place the translation with the name of "ldap.php" in "\resources\lang\XX", where XX corresponds to the language. I also leave my translation files...

// Language: English
// Folder: \resources\lang\en\
// File Name: ldap.php

return [
    'user_not_found' => 'User not found.',
    'user_not_permitted_at_this_time' => 'Not permitted to logon at this time.',
    'user_not_permitted_to_login' => 'Not permitted to logon at this workstation.',
    'password_expired' => 'Your password has expired.',
    'account_disabled' => 'Your account is disabled.',
    'account_expired' => 'Your account has expired.',
    'user_must_reset_password' => 'You must reset your password before logging in.',
    'user_account_locked' => 'Your account is locked.',
];
// Language: Spanish
// Folder: \resources\lang\es\
// File Name: ldap.php

return [
    'user_not_found' => 'Usuario no encontrado.',
    'user_not_permitted_at_this_time' => 'No está permitido iniciar sesión en este momento.',
    'user_not_permitted_to_login' => 'No se permite iniciar sesión en esta estación de trabajo.',
    'password_expired' => 'Su contraseña ha expirado.',
    'account_disabled' => 'Su cuenta está desactivada.',
    'account_expired' => 'Su cuenta ha expirado.',
    'user_must_reset_password' => 'Debe restablecer su contraseña antes de iniciar sesión.',
    'user_account_locked' => 'Su cuenta esta bloqueada.',
];

Dear @stevebauman, once again thank you very much and congratulations for your great work!

stevebauman commented 2 years ago

Strange! I'm unable to reproduce this on my end on Laravel 8.0. Nevertheless, I'm glad you've got it working the way you want.

Thanks for your kind words and quick responses!

Closing this as resolved 👍