Adldap2-Laravel
Adldap2-Laravel copied to clipboard
Password Expired Handling
I would like to tell users their password is expired if they attempt to login. Is there any way to do that?
Hi @mackhankins,
I just added the ability to check this: https://github.com/Adldap2/Adldap2-Laravel/commit/c2e7690a5cf218c029755a200fd7c3c1df4165d4
You'll have to create your own AdldapAuthServiceProvider
and AdldapAuthUserProvider
:
namespace App\Providers;
use Adldap\Laravel\AdldapAuthServiceProvider;
class MyLdapAuthServiceProvider extends AdldapAuthServiceProvider
{
protected function newAdldapAuthUserProvider(Hasher $hasher, $model)
{
return new MyLdapAuthUserProvider($hasher, $model);
}
}
namespace App\Providers;
use Adldap\Laravel\AdldapAuthUserProvider;
class MyLdapAuthUserProvider extends AdldapAuthUserProvider
{
/**
* Handle discovered LDAP users before they are authenticated.
*
* @param \Adldap\Models\User $user
*
* @return void
*/
protected function handleDiscoveredUserWithCredentials(User $user)
{
if ((int) $this->getPasswordLastSet() === 0) {
throw new \App\Exceptions\PasswordExpiredException('Your password is expired.');
}
}
}
Hi @stevebauman, is this still the way to go?
Hi @strebl,
With v3.0
you can actually do this, using the auth events that are fired:
// app/Providers/EventServiceProvider.php
namespace App\Providers;
use App\Events\TestEvent;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
Adldap\Laravel\Events\DiscoveredWithCredentials::class => [
App\Listeners\PasswordExpiredListener::class,
],
];
}
// app/Listeners/PasswordExpiredListener.php
namespace App\Listeners;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Adldap\Laravel\Events\DiscoveredWithCredentials;
class PasswordExpiredListener
{
/**
* Handle the event.
*
* @param DiscoveredWithCredentials $event
* @return void
*/
public function handle(DiscoveredWithCredentials $event)
{
if ($event->user->getPasswordLastSet() === 0) {
throw new \Exception("Password Expired");
}
}
}
Then when you authenticate, you can catch this exception:
try {
if (Auth::attempt($credentials)) {
// Passed
}
} catch (\Exception $e) {
return redirect()->back()->with('message', $e->getMessage());
}
Thanks for your answer @stevebauman
I don't really like booth solutions. In my opinion, thats such a standard case. Would you be interested in a PR to simplify that?
Sure! Though how would you go about adding this into the auth driver?
I'm not a fan of adding an exception by default for this case, as developers are use to using just:
if (Auth::attempt($credentials)) {
// Authenticated.
}
If a PR was merged that would generate an exception during authentication using the adldap
driver I'd have to write documentation for it as well as generate a new full version (v4.0.0
) to follow semantic versioning.
I had something like that in my mind:
You can use a RedirectsIfPasswordIsExpired
trait in your User model or in your login controller which handles that case. If you use that trait, you can define a redirect path which would default to '/login' or something like that. It would also set a validation error of the password field to "Your password is expired.".
If you don't use the trait, nothing changes. Therefore a major release wouldn't be necessary.
As I said, thats just in my mind and maybe the implementation won't work.
Do you think that is bad or wouldn't work. Because in my work its fantastic and it works great 😄
I love the idea of a trait. @strebl you have one to share?
This may need to reside in a listener.
This is because we won't actually have the users eloquent model to work with since it's retrieved after LDAP authentication passes (which obviously fails when the users password is expired).
We could use a trait as sort of a configuration option and see if the configured eloquent model contains the trait, but at that point I could simply create a listener that registers itself but only redirects if a configuration option is set to true?
What would everyone prefer?
There's even the option of a custom validation rule we could use here, that would would accept the username field as a parameter and query your LDAP server for their account, and see if it's password is expired.
Though this would cost two queries instead of one (using a listener). but would be convenient.
Is this still the current method?
There's even the option of a custom validation rule we could use here, that would would accept the username field as a parameter and query your LDAP server for their account, and see if it's password is expired.
Though this would cost two queries instead of one (using a listener). but would be convenient.
I think there are two widely used use cases we would like to achieve:
- show a message at the login form (like a validation error)
- redirect to a password change form
A solution for these use cases would be great.