Overview
GB App uses Laravel Jetstream with Fortify for authentication, providing:
- Local username/email and password authentication
- Two-factor authentication (2FA)
- LDAP/Active Directory integration (hybrid authentication)
- Password recovery
- Session management
- Remember me functionality
Hybrid Authentication System
GB App implements a hybrid authentication system that supports both local database users and LDAP users.
Authentication Flow
The authentication logic is handled by AuthenticateUserHybrid action:
app/Actions/Fortify/AuthenticateUserHybrid.php
public function authenticate(Request $request)
{
$credentials = $request->only('username', 'password');
$username = $credentials['username'];
$password = $credentials['password'];
// 1. Search for user in local database
$user = User::on('mysql')
->where('username', $username)
->orWhere('email', $username)
->first();
// 2. If exists and is NOT LDAP user, authenticate locally
if ($user && !$user->is_ldap_user) {
if (Hash::check($password, $user->password)) {
Auth::login($user, $request->boolean('remember'));
return $user;
}
throw ValidationException::withMessages([
'username' => ['Las credenciales proporcionadas son incorrectas.'],
]);
}
// 3. If LDAP user or doesn't exist, try LDAP authentication
try {
$ldapConnection = Container::getDefaultConnection();
// Search user in Active Directory
$ldapUser = \App\Ldap\User::where('samaccountname', '=', $username)->first();
if (!$ldapUser) {
throw ValidationException::withMessages([
'username' => ['Usuario no encontrado en Active Directory.'],
]);
}
// Attempt AD authentication
if (!$ldapConnection->auth()->attempt($ldapUser->getDn(), $password)) {
throw ValidationException::withMessages([
'username' => ['Contraseña incorrecta.'],
]);
}
// 4. Successful authentication - Sync/Create local user
$user = $this->syncOrCreateUserFromLdap($ldapUser);
Auth::login($user, $request->boolean('remember'));
return $user;
} catch (\LdapRecord\LdapRecordException $e) {
Log::error('LDAP Authentication Error: ' . $e->getMessage());
throw ValidationException::withMessages([
'username' => ['Error al conectar con Active Directory. Intente más tarde.'],
]);
}
}
LDAP User Synchronization
When an LDAP user logs in, their information is synced to the local database:
app/Actions/Fortify/AuthenticateUserHybrid.php
protected function syncOrCreateUserFromLdap($ldapUser): User
{
$guid = $ldapUser->getConvertedGuid();
// Search by GUID first
$user = User::on('mysql')
->where('guid', $guid)
->first();
if (!$user) {
// Search by username
$user = User::on('mysql')
->where('username', $ldapUser->getFirstAttribute('samaccountname'))
->first();
}
$userData = [
'name' => $ldapUser->getFirstAttribute('cn'),
'username' => $ldapUser->getFirstAttribute('samaccountname'),
'email' => $ldapUser->getFirstAttribute('mail') ?? $ldapUser->getFirstAttribute('samaccountname') . '@' . env('LDAP_DOMAIN', 'domain.com'),
'guid' => $guid,
'domain' => env('LDAP_DOMAIN', 'AD'),
'is_ldap_user' => true,
];
if ($user) {
// Update existing user
$user->update($userData);
} else {
// Create new user
$userData['password'] = Hash::make(uniqid()); // Random password (not used)
$user = User::create($userData);
}
return $user;
}
User Model
The User model includes authentication traits and LDAP support:
use HasApiTokens;
use HasFactory;
use HasProfilePhoto;
use Notifiable;
use TwoFactorAuthenticatable;
use HasRoles;
use AuthenticatesWithLdap;
protected $fillable = [
'name',
'username',
'email',
'password',
'type',
'guid', // LDAP GUID
'domain', // LDAP domain
'is_ldap_user', // Flag for LDAP users
'cedula',
'codigo_vendedor',
'advisor_id',
];
protected $hidden = [
'password',
'remember_token',
'two_factor_recovery_codes',
'two_factor_secret',
];
protected $casts = [
'email_verified_at' => 'datetime',
'created_at' => 'datetime:Y-m-d h:i:s A',
'updated_at' => 'datetime:Y-m-d h:i:s A',
'is_ldap_user' => 'boolean',
];
public function isLdapUser(): bool
{
return $this->is_ldap_user && !empty($this->guid);
}
Login Routes
Authentication routes are handled by Laravel Fortify. The main routes include:
Route::get('/', function () {
return redirect()->route('login');
});
Route::middleware(['auth:sanctum', config('jetstream.auth_session'), 'verified'])->group(function () {
Route::get('dashboard', [DashboardController::class, 'index'])
->name('dashboard');
// ... protected routes
});
Two-Factor Authentication (2FA)
GB App includes Laravel Jetstream’s built-in 2FA functionality:
Enabling 2FA
Users can enable 2FA from their profile:
- Navigate to Profile > Two Factor Authentication
- Click “Enable” to generate a QR code
- Scan the QR code with an authenticator app (Google Authenticator, Authy, etc.)
- Enter the confirmation code
- Save recovery codes in a safe place
2FA Database Fields
The users table includes these 2FA columns:
'two_factor_secret' => 'text', // Encrypted 2FA secret
'two_factor_recovery_codes' => 'text', // Encrypted recovery codes
'two_factor_confirmed_at' => 'timestamp', // When 2FA was confirmed
Two-factor authentication is optional but highly recommended for admin accounts and users with sensitive permissions.
Password Recovery
Reset Password Flow
- User clicks “Forgot Password” on login page
- User enters email address
- System sends password reset email
- User clicks link in email
- User enters new password
- Password is updated using bcrypt hashing
Password Reset Action
app/Actions/Fortify/ResetUserPassword.php
use App\Actions\Fortify\PasswordValidationRules;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
class ResetUserPassword
{
use PasswordValidationRules;
public function reset($user, array $input)
{
Validator::make($input, [
'password' => $this->passwordRules(),
])->validate();
$user->forceFill([
'password' => Hash::make($input['password']),
])->save();
}
}
LDAP users cannot reset their passwords through the application as their passwords are managed by Active Directory.
Session Management
Sessions are stored in the database for better control and security:
SESSION_DRIVER=database
SESSION_LIFETIME=120
The sessions table tracks:
- User ID
- IP address
- User agent
- Last activity timestamp
- Session payload
Authentication Middleware
Protected routes use multiple middleware:
Route::middleware([
'auth:sanctum', // Sanctum authentication
config('jetstream.auth_session'), // Jetstream session
'verified' // Email verification
])->group(function () {
// Protected routes
});
User Types
The system supports different user types defined in the users table:
enum('type', ['customer', 'designer', 'seller'])->nullable()
These types can be used to:
- Customize dashboard views
- Control feature access
- Filter users in administration
Security Features
Password Hashing
All passwords are hashed using bcrypt:
'password' => bcrypt($request->password)
CSRF Protection
All forms include CSRF tokens automatically via Inertia.js and Laravel’s middleware.
Rate Limiting
Authentication endpoints are rate-limited to prevent brute force attacks (configured in app/Http/Kernel.php).
Secure Cookies
Session cookies are HTTP-only and secure when using HTTPS.
Logout
Users can logout from:
- Main navigation menu
- Profile dropdown
- Session management page (logout all other devices)
Next Steps