scheb/2fa-trusted-device
Adds trusted device support to scheb/2fa so users can skip 2FA on recognized devices for a set time. Stores trust tokens in cookies and persistence, with configurable lifetimes and validation, improving UX without removing 2FA security.
Installation
composer require scheb/2fa-trusted-device
Ensure scheb/2fa-bundle is also installed (this package extends it).
Configuration Publish the config file:
php artisan vendor:publish --provider="Scheb\TwoFactorBundle\SchebTwoFactorBundle" --tag="config"
Update config/scheb_two_factor.php to enable trusted devices:
'trusted_device' => [
'enabled' => true,
'cookie_name' => '2fa_trusted_device',
'cookie_lifetime' => 30, // days
'ip_check' => true, // verify IP consistency
'user_agent_check' => true,
],
First Use Case Trigger the trusted device flow in your login controller:
use Scheb\TwoFactorBundle\Security\TwoFactorAuthenticator;
public function login(Request $request, TwoFactorAuthenticator $twoFactor)
{
if ($twoFactor->isTrustedDeviceEnabled() && $twoFactor->isTrustedDevice($request)) {
// Skip 2FA for trusted devices
return redirect()->intended('/dashboard');
}
// Proceed with 2FA or normal login
}
Login Flow
public function handle($request, Closure $next)
{
if ($request->user() && $this->twoFactor->isTrustedDeviceEnabled()) {
if ($this->twoFactor->isTrustedDevice($request)) {
return $next($request);
}
// Redirect to 2FA or mark as untrusted
}
return $next($request);
}
Trusted Device Management
$twoFactor->trustDevice($request);
$twoFactor->revokeTrustedDevice($request);
Conditional Logic
scheb/2fa-bundle features:
if ($twoFactor->isTrustedDevice($request) || $twoFactor->isTwoFactorAuthEnabled($request->user())) {
// Handle 2FA or trusted flow
}
isTrustedDevice() to include tenant-specific checks.Cookie Security
SameSite and Secure flags are set in your web server config for the 2fa_trusted_device cookie.app/Http/Middleware/TrustProxies.php:
$cookie->setSecure(true);
$cookie->setSameSite('Lax');
IP/User-Agent Mismatches
ip_check or user_agent_check is true, revoking trust may occur unexpectedly (e.g., VPN changes, device updates).$twoFactor->setTrustedDeviceConfig(['ip_check' => false]);
Session Conflicts
session()->put()), ensure cookies are not cleared prematurely.$twoFactor->isTrustedDevice($request); // Returns bool
$twoFactor->getTrustedDeviceData($request); // Returns array (IP, user-agent, etc.)
$twoFactor->onTrustedDeviceTrusted(function ($request) {
\Log::info('Device trusted', ['ip' => $request->ip()]);
});
Custom Trust Logic
Override the isTrustedDevice() check in a service:
public function isTrustedDevice(Request $request)
{
if ($this->customCondition($request)) {
return true;
}
return parent::isTrustedDevice($request);
}
Database Backend
The package uses cookies by default. For persistence, extend the TrustedDeviceStorageInterface:
class DatabaseTrustedDeviceStorage implements TrustedDeviceStorageInterface
{
public function store($userId, $data)
{
DB::table('trusted_devices')->updateOrInsert(
['user_id' => $userId],
['data' => $data]
);
}
// Implement other methods...
}
Multi-Factor Trust
Combine with other packages (e.g., laravel-notifiable) to send notifications when a new device is trusted:
$twoFactor->onTrustedDeviceTrusted(function ($request) use ($user) {
$user->notify(new DeviceTrusted($request->ip()));
});
How can I help you explore Laravel packages today?