feat: add app and database modules
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Auth\LoginRequest;
|
||||
use App\Models\User;
|
||||
use App\Models\UserTrustedDevice;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class AuthenticatedSessionController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the login view
|
||||
*/
|
||||
public function create(): View
|
||||
{
|
||||
return view('auth.login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming authentication request
|
||||
*/
|
||||
public function store(LoginRequest $request): RedirectResponse
|
||||
{
|
||||
// Batch common auth settings
|
||||
$settings = [
|
||||
'2fa_enabled' => get_setting('two_factor_auth', false),
|
||||
'allow_remember' => get_setting('session_allow_remember_me', true),
|
||||
'remember_duration' => get_setting('session_remember_me_duration', 30),
|
||||
'single_session' => get_setting('session_single_session', false),
|
||||
];
|
||||
|
||||
$credentials = $request->only('email', 'password');
|
||||
$remember = $settings['allow_remember'] && $request->boolean('remember');
|
||||
|
||||
// Check if 2FA is enabled globally
|
||||
if ($settings['2fa_enabled']) {
|
||||
if (Auth::validate($credentials)) {
|
||||
$user = User::where('email', $request->email)->first();
|
||||
|
||||
// Check Trust Device bypass (Secure check)
|
||||
$cookieValue = $request->cookie('2fa_trust_device');
|
||||
$trustedBypass = false;
|
||||
|
||||
if ($cookieValue && str_contains($cookieValue, '|')) {
|
||||
$parts = explode('|', $cookieValue, 2);
|
||||
|
||||
if (count($parts) === 2 && ! empty($parts[0]) && ! empty($parts[1])) {
|
||||
[$uuid, $secret] = $parts;
|
||||
|
||||
$trust = UserTrustedDevice::where('user_id', $user->id)
|
||||
->where('device_id', $uuid)
|
||||
->where('expires_at', '>', now())
|
||||
->first();
|
||||
|
||||
if ($trust && hash_equals($trust->token, hash('sha256', $secret))) {
|
||||
$trustedBypass = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($trustedBypass) {
|
||||
Auth::attempt($credentials, $remember);
|
||||
$request->session()->regenerate();
|
||||
$user->update(['last_session_id' => session()->getId()]);
|
||||
|
||||
return redirect()->intended(route('dashboard', absolute: false));
|
||||
}
|
||||
|
||||
// Generate & Send OTP
|
||||
TwoFactorController::generateAndSendOtp($user);
|
||||
session(['auth.2fa_remember' => $remember]);
|
||||
|
||||
return redirect()->route('2fa.index');
|
||||
}
|
||||
}
|
||||
|
||||
// Authenticate user credentials normally
|
||||
$request->authenticate();
|
||||
$request->session()->regenerate();
|
||||
|
||||
/** @var User $user */
|
||||
$user = Auth::user();
|
||||
$user->update(['last_session_id' => session()->getId()]);
|
||||
|
||||
// Custom duration Remember Me
|
||||
if ($remember) {
|
||||
$minutes = 60 * 24 * $settings['remember_duration'];
|
||||
cookie()->queue(
|
||||
cookie(
|
||||
name: Auth::getRecallerName(),
|
||||
value: cookie()->get(Auth::getRecallerName()),
|
||||
minutes: $minutes,
|
||||
httpOnly: true,
|
||||
secure: app()->environment('production'),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// SINGLE SESSION ENFORCEMENT
|
||||
if ($settings['single_session']) {
|
||||
Auth::logoutOtherDevices($request->password);
|
||||
}
|
||||
|
||||
return redirect()->intended('/dashboard');
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy an authenticated session
|
||||
*/
|
||||
public function destroy(Request $request): RedirectResponse
|
||||
{
|
||||
Auth::guard('web')->logout();
|
||||
|
||||
// Invalidate session for security
|
||||
$request->session()->invalidate();
|
||||
|
||||
// Regenerate CSRF token
|
||||
$request->session()->regenerateToken();
|
||||
|
||||
// Redirect to homepage
|
||||
return redirect('/');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user