1. Go to this page and download the library: Download pijler/user-devices library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
pijler / user-devices example snippets
// config/user-devices.php
return [
'events' => [
'failed' => true, // Track failures, notify when new device
'attempting' => false, // Track attempts, notify when new device
'authenticated' => true, // Save device + send new login notification
],
'credential_key' => 'email', // Key to find user from credentials (attempting/failed)
];
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\URL;
use UserDevices\DeviceCreator;
use UserDevices\Notifications\AuthenticatedLoginNotification;
class AppServiceProvider extends ServiceProvider
{
public function boot(): void
{
// Use custom user model
DeviceCreator::useUserModel(CustomUser::class);
// Use custom user device model
DeviceCreator::useUserDeviceModel(CustomUserDevice::class);
// Customize user agent generation
DeviceCreator::userAgentUsing(fn ($userAgent) => substr($userAgent, 0, 255));
// Control when to send notifications (e.g. disable in local/staging)
DeviceCreator::shouldSendNotificationUsing(function ($user, $device) {
return ! app()->environment('local');
});
// Resolve location from IP (optional)
DeviceCreator::resolveLocationUsing(function (string $ip) {
$geo = geoip($ip);
return $geo->city ? "{$geo->city}, {$geo->country}" : $geo->country;
});
// Customize the notification email
AuthenticatedLoginNotification::toMailUsing(function ($notifiable, $device) {
$expire = Config::get('auth.verification.expire', 60);
$blockUrl = URL::temporarySignedRoute(
name: 'user-devices.block',
expiration: Carbon::now()->addMinutes($expire),
parameters: [
'id' => $device->getKey(),
'hash' => sha1($device->getKey()),
],
);
return (new MailMessage)
->subject('New device detected')
->line('We detected a new login to your account.')
->action('Block device', $blockUrl);
});
// Customize the block device URL
AuthenticatedLoginNotification::createBlockUrlUsing(function ($device) {
return URL::temporarySignedRoute(
name: 'your-custom-route-name',
expiration: Carbon::now()->addMinutes(120),
parameters: [
'id' => $device->getKey(),
'hash' => sha1($device->getKey()),
],
);
});
}
}
use Illuminate\Notifications\Notifiable;
use UserDevices\Traits\HasUserDevices;
class User extends Authenticatable
{
use HasUserDevices;
use Notifiable;
}
use UserDevices\DeviceCreator;
DeviceCreator::ignoreListener();
use UserDevices\Http\Requests\BlockDeviceRequest;
Route::get('/devices/block/{id}/{hash}', function (BlockDeviceRequest $request) {
$request->fulfill();
return redirect()->route('home')->with('message', 'Device blocked successfully.');
})->middleware(['signed', 'throttle:6,1'])->name('user-devices.block');
// In your login logic, after resolving the user from credentials (e.g. email)
$user = User::where('email', $request->email)->first();
if ($user && $user->isCurrentDeviceBlocked()) {
return response()->json(['message' => 'This device has been blocked.'], 423);
}
// Proceed with login attempt...
public function authorize(): bool
{
$user = User::where('email', $this->email)->first();
return ! ($user && $user->isCurrentDeviceBlocked());
}
use UserDevices\Models\UserDevice;
// Get user's devices
$devices = $user->userDevices;
// Block a device (invalidates session if session_id is set)
$device = UserDevice::find($id);
$device->block();
// Unblock a device
$device->unblock();
// Block by ID (static)
UserDevice::markAsBlocked($id);
// Unblock by ID (static)
UserDevice::markAsUnblocked($id);
use UserDevices\Notifications\AttemptingLoginNotification;
use UserDevices\Notifications\FailedLoginNotification;
AttemptingLoginNotification::toMailUsing(fn ($notifiable, $device) => (new MailMessage)
->subject('Login attempt')->line("IP: {$device->ip_address}"));
AttemptingLoginNotification::createBlockUrlUsing(fn ($device) => URL::temporarySignedRoute(/* ... */));
FailedLoginNotification::toMailUsing(fn ($notifiable, $device) => (new MailMessage)
->subject('Failed login')->line("IP: {$device->ip_address}"));
FailedLoginNotification::createBlockUrlUsing(fn ($device) => URL::temporarySignedRoute(/* ... */));
// Configuration
DeviceCreator::useUserModel(string $model): void
DeviceCreator::useUserDeviceModel(string $model): void
DeviceCreator::userAgentUsing(Closure $callback): void
DeviceCreator::resolveLocationUsing(Closure $callback): void // (string $ip) => ?string
DeviceCreator::shouldSendNotificationUsing(Closure $callback): void // (user, device) => bool
// Request context (call before authentication)
DeviceCreator::ignoreListener(): void // Skip saving the device for the current request
DeviceCreator::ignoreNotification(): void // Skip the new login notification for the current request
// Relationships
$device->user(): BelongsTo
// Actions
$device->block(): void // Also invalidates session when session_id is set
$device->unblock(): void
// Static methods
UserDevice::markAsBlocked(mixed $id): void
UserDevice::markAsUnblocked(mixed $id): void
// Methods available on model
$model->userDevices(): HasMany
$model->isCurrentDeviceBlocked(): bool // Check if current request's device is blocked (use before login)
$model->sendFailedLoginNotification(UserDevice $device): void
$model->sendAttemptingLoginNotification(UserDevice $device): void
$model->sendAuthenticatedLoginNotification(UserDevice $device): void