Closed anchan42 closed 1 year ago
Hi @anchan42,
Can you link the documentation you followed?
Hi Steve,
It this one ldap-error-messages
Thanks @anchan42, can you post your code as well?
Sorry, Steve. I think posted this in the wrong repo. It should have been the one for Laravel.
Please see the code below:
AuthenticatedSessionController:
<?php
namespace App\Http\Controllers\Auth;
use Illuminate\View\View;
use Illuminate\Http\Request;
use Illuminate\Routing\RouteUri;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\RedirectResponse;
use App\Providers\RouteServiceProvider;
use App\Http\Requests\Auth\LoginRequest;
use LdapRecord\Laravel\Auth\ListensForLdapBindFailure;
class AuthenticatedSessionController extends Controller
{
/**
* Display the login view.
*/
use ListensForLdapBindFailure;
protected $username = 'username';
public function __construct()
{
$this->listenForLdapBindFailure();
}
public function create(): View
{
return view('auth.login');
}
/**
* Handle an incoming authentication request.
*/
public function store(LoginRequest $request): RedirectResponse
{
$request->authenticate();
$request->session()->regenerate();
return redirect()->intended(route('bd_reports.index',['status' => '1']));
}
/**
* Destroy an authenticated session.
*/
public function destroy(Request $request): RedirectResponse
{
Auth::guard('web')->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/');
}
}
LoginRequest:
<?php
namespace App\Http\Requests\Auth;
use Illuminate\Auth\Events\Lockout;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
class LoginRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\Rule|array|string>
*/
public function rules(): array
{
return [
'username' => ['required', 'string'],
'password' => ['required', 'string'],
];
}
/**
* Attempt to authenticate the request's credentials.
*
* @throws \Illuminate\Validation\ValidationException
*/
public function authenticate(): void
{
$this->ensureIsNotRateLimited();
$credentials = [
'samaccountname' => $this->username,
'password' => $this->password,
'fallback' => [
'username' => $this->username,
'password' => $this->password,
],
];
if (!Auth::attempt($credentials, $this->filled('remember'))) {
RateLimiter::hit($this->throttleKey());
throw ValidationException::withMessages([
'username' => __('auth.failed'),
]);
}
RateLimiter::clear($this->throttleKey());
}
public function ensureIsNotRateLimited(): void
{
if (!RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
return;
}
event(new Lockout($this));
$seconds = RateLimiter::availableIn($this->throttleKey());
throw ValidationException::withMessages([
'username' => trans('auth.throttle', [
'seconds' => $seconds,
'minutes' => ceil($seconds / 60),
]),
]);
}
/**
* Get the rate limiting throttle key for the request.
*/
public function throttleKey(): string
{
return Str::transliterate(Str::lower($this->input('email')) . '|' . $this->ip());
}
}
No worries @anchan42, I've transferred the issue to the Laravel repo 👍
You're not seeing the exception due to configuring fallback authentication. When you add fallback authentication (by passing in the fallback
array in the user's credentials) any connection exceptions are caught so that LdapRecord-Laravel can fall back to the database and attempt to perform Eloquent authentication. This is described here, but I can update the language to be more explicit:
https://ldaprecord.com/docs/laravel/v3/auth/database/laravel-breeze/#fallback-authentication
Database fallback allows the authentication of local database users if:
- LDAP connectivity is not present.
- Or; An LDAP user cannot be found.
Since fallback sends the authentication request to Eloquent, a typical Eloquent "authentication failed" validation message will appear.
For failed LDAP error messages to appear, you cannot have fallback configured. Try removing the fallback
key from your credentials and then also call LdapRecord::failLoudly()
in your controller constructor:
use LdapRecord\Laravel\LdapRecord
class AuthenticatedSessionController extends Controller
{
/**
* Display the login view.
*/
use ListensForLdapBindFailure;
protected $username = 'username';
public function __construct()
{
LdapRecord::failLoudly();
$this->listenForLdapBindFailure();
}
// ...
}
Once you've done the above, try authenticating again and you should see the connection error message appear 👍
Ok I understand now. Is there any way I can revert the auth order? i.e. using LDAP as a fallback when database auth fails?
No not with LdapRecord-Laravel. You would have to build your own fallback logic with separate auth guards (one for Eloquent and one for LdapRecord), attempt authentication with the Eloquent guard, then fallback to LdapRecord if it fails 👍
Going to close this as your question has been resolved, let me know if otherwise!
Thanks, Steve 👍
Environment:
I followed all the settings in the documentation but when I tried changing the LDAP server settings to non-existence server, the error still show 'These credentials do not match our records.' instead of 'Can't connect to LDAP server'