GeoNetAgent, LDAPWeb, server-audit, server-connection
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

152 lines
5.0 KiB

<?php
namespace App\Http\Controllers;
use App\Services\AuditLogService;
use App\Services\LdapAuthService;
use App\Services\LdapPasswordResetService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class AuthController extends Controller
{
public function __construct(
private readonly LdapAuthService $ldapAuth,
private readonly LdapPasswordResetService $passwordReset,
private readonly AuditLogService $audit
) {
}
public function showLogin(Request $request): View|RedirectResponse
{
if ($request->session()->get('ldap_authenticated')) {
return $request->session()->get('ldap_is_admin')
? redirect()->route('databases.index')
: redirect()->route('profile.show');
}
return view('auth.login');
}
public function login(Request $request): RedirectResponse
{
$credentials = $request->validate([
'username' => ['required', 'string', 'max:100'],
'password' => ['required', 'string', 'max:255'],
]);
$user = $this->ldapAuth->attempt($credentials['username'], $credentials['password']);
if ($user === null) {
$this->audit->logPublic('auth.login.failed', $credentials['username'], $request, [
'username' => $credentials['username'],
]);
return back()
->withInput($request->only('username'))
->withErrors(['username' => 'Invalid LDAP credentials.']);
}
$request->session()->regenerate();
$request->session()->put([
'ldap_authenticated' => true,
'ldap_is_admin' => $user['is_admin'],
'ldap_username' => $user['username'],
'ldap_display_name' => $user['display_name'],
]);
$this->audit->logWeb('auth.login', $user['username'], $request, [
'is_admin' => $user['is_admin'],
]);
$request->attributes->set('audit_logged', true);
$defaultRoute = $user['is_admin'] ? 'databases.index' : 'profile.show';
return redirect()->intended(route($defaultRoute));
}
public function logout(Request $request): RedirectResponse
{
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect()->route('login');
}
public function showForgotPassword(): View
{
return view('auth.forgot-password');
}
public function sendForgotPassword(Request $request): RedirectResponse
{
$data = $request->validate([
'username' => ['required', 'string', 'max:100', 'regex:/^[a-zA-Z0-9._-]+$/'],
]);
try {
$this->passwordReset->sendResetLink($data['username']);
$this->audit->logPublic('auth.password.forgot', $data['username'], $request, [
'username' => $data['username'],
]);
} catch (\Throwable) {
// Do not reveal whether user exists or mail failed.
}
return back()->with(
'success',
'If the account exists and has an email registered in LDAP, a password reset link has been sent.'
);
}
public function showResetPassword(string $token): View|RedirectResponse
{
$username = $this->passwordReset->validateToken($token);
if ($username === null) {
return redirect()->route('login')->with('error', 'Reset link is invalid or has expired.');
}
return view('auth.reset-password', [
'token' => $token,
'username' => $username,
]);
}
public function resetPassword(Request $request, string $token): RedirectResponse
{
$data = $request->validate([
'password' => ['required', 'string', 'min:8', 'max:128', 'confirmed'],
'confirm_action' => ['required', 'accepted'],
'confirm_username' => ['required', 'string'],
]);
$username = $this->passwordReset->validateToken($token);
if ($username === null) {
return redirect()->route('login')->with('error', 'Reset link is invalid or has expired.');
}
if (mb_strtolower($data['confirm_username']) !== mb_strtolower($username)) {
return back()->withInput()->with('error', 'Username confirmation does not match.');
}
try {
$this->passwordReset->resetPassword($token, $data['password']);
$this->audit->logPublic('auth.password.reset', $username, $request, [
'username' => $username,
]);
return redirect()->route('login')->with(
'success',
'Password has been reset. You can now sign in with your new password.'
);
} catch (\InvalidArgumentException $e) {
return back()->withInput()->with('error', $e->getMessage());
} catch (\Throwable) {
return back()->withInput()->with('error', 'Password reset failed. Please try again.');
}
}
}