Filament plugin for customizable profile page, two factor authentication & Sanctum token management.
Filament plugin for customizable profile page, two factor authentication & Sanctum token management.
Enhanced security features for Filament (v4) Panels. Includes a customizable My Profile page with personal info & avatar support, update password, two factor authentication, passkey authentication and Sanctum token management. Installs in minutes!
My Profile - Personal info with avatar support
Update password with customizable validation rules
Protected sensitive actions with a password confirmation modal Action
Two factor authentication with recovery codes
Force the user to enable two factor authentication before they can use the app
Create and manage Sanctum personal access tokens
Manage active browser sessions and log out other sessions
Passkeys for passwordless authentication
composer require jeffgreco13/filament-breezy
php artisan breezy:installAdd Breezy to a panel by adding the class to your Filament Panel's plugin() or plugins([]) method.
use Jeffgreco13\FilamentBreezy\BreezyCore;
public function panel(Panel $panel): Panel
{
return $panel
->plugins([
BreezyCore::make()
])
}Filament recommends developers to create a custom theme to better support a plugin's additional Tailwind classes.
After you have created your custom theme, add Breezy's views to your theme's theme.css file usually located in resources/css/filament/admin/theme.css:
@source '../../../../vendor/jeffgreco13/filament-breezy/resources/**/*';php artisan vendor:publish --tag="filament-breezy-views"Breezy will use the authGuard set on the Filament Panel that you create. You may update the authGuard as you please:
use Jeffgreco13\FilamentBreezy\BreezyCore;
class CustomersPanelProvider extends PanelProvider
{
public function panel(Panel $panel): Panel
{
return $panel
...
->authGuard('customers')
->plugin(
BreezyCore::make()
)
}
}NOTE: you must ensure that the model used in your Guard extends the Authenticatable class.
Enable the My Profile page with configuration options.
NOTE: if you are using avatars,
…You can also use a custom My Profile page class by extending the default one, and registering it with the plugin.
BreezyCore::make()
->myProfile()
->customMyProfilePage(AccountSettingsPage::class),The instructions for using custom avatars is found in the Filament v4 docs under Setting up user avatars.
Here is a possible implementation using the example from the docs:
use Illuminate\Support\Facades\Storage;
use Filament\Models\Contracts\HasAvatar;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements FilamentUser, HasAvatar
{
// ...
public function getFilamentAvatarUrl(): ?string
{
return $this->avatar_url ? Storage::url($this->avatar_url) : null;
}
}
use Filament\Forms\Components\FileUpload;
BreezyCore::make()
->avatarUploadComponent(fn($fileUpload) => $fileUpload->disableLabel())
// OR, replace with your own component
->avatarUploadComponent(fn() => FileUpload::make('avatar_url')->disk('profile-photos'))If you wish to have your own avatar, you need to create a column on the users table named avatar_url. It is reccomended that you create a new migration for it, and add the column there:
php artisan make:migration add_avatar_url_column_to_users_tablestring('avatar_url')->nullable();
});
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('avatar_url');
});
}
}; protected $fillable = [
...
'avatar_url',
...
];By default Breezy uses the default password rules defined in your Laravel project.
You may customize the validation rules for the update password component by passing an array of validation strings, or an instance of the Illuminate\Validation\Rules\Password class.
use Illuminate\Validation\Rules\Password;
BreezyCore::make()
->passwordUpdateRules(
rules: [Password::default()->mixedCase()->uncompromised(3)], // you may pass an array of validation rules as well. (default = ['min:8'])
requiresCurrentPassword: true, // when false, the user can update their password without entering their current password. (default = true)
)
If you don't want a default My Profile page component to be used, you can exclude them using the withoutMyProfileComponents helper.
BreezyCore::make()
->withoutMyProfileComponents([
'update_password'
])You can create a custom Livewire components for the My Profile page and append them easily.
php artisan make:livewire MyCustomComponentMyProfileComponent class included with Breezy. This class implements Actions and Forms.…
{{ $this->form }}
use App\Livewire\MyCustomComponent;
BreezyCore::make()
->myProfileComponents([MyCustomComponent::class])You may override the existing MyProfile components to replace them with your own:
use App\Livewire\MyCustomComponent;
BreezyCore::make()
->myProfileComponents([
// 'personal_info' => ,
'update_password' => MyCustomComponent::class, // replaces UpdatePassword component with your own.
// 'two_factor_authentication' => ,
// 'sanctum_tokens' =>
// 'browser_sessions' =>
])[!IMPORTANT] Changing the email address on the personal info form requires the user to re-enter their current password. The confirmation field appears as soon as the email input differs from the user's saved address. This protects against an attacker with access to an authenticated session taking over the account by changing the login email.
If you override
getProfileFormComponents(), please keep$this->getCurrentPasswordComponent()in the returned array.
If you want to customize only the fields and notification in the personal info component, you can extend the original breezy component:
…Now, as mentioned above, give this component to BreezyCore::make()->myProfileComponents to override the original and use your custom component.
Custom MyProfile components can be sorted by setting their static $sort property. This property can be set for existing MyProfile components in any service provider:
TwoFactorAuthentication::setSort(4);A lot of the time this won't be necessary, though, as the default sort order is spaced out in steps of 10, so there should be enough numbers to place any custom components in between.
Jeffgreco13\FilamentBreezy\Traits\TwoFactorAuthenticatable to your Authenticatable model:use Jeffgreco13\FilamentBreezy\Traits\TwoFactorAuthenticatable;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable, TwoFactorAuthenticatable;
// ...
}enableTwoFactorAuthentication() method on the Breezy plugin.BreezyCore::make()
->enableTwoFactorAuthentication(
force: false, // force the user to enable 2FA before they can use the application (default = false)
action: CustomTwoFactorPage::class, // optionally, use a custom 2FA page
authMiddleware: MustTwoFactor::class, // optionally, customize 2FA auth middleware or disable it to register manually by setting false
scopeToPanel: true, // scope the 2FA only to the current panel (default = true)
)The Breezy 2FA page can be swapped for a custom implementation (see above), same as the Filament auth pages. This allows, for example, to define a custom auth layout like so:
use Jeffgreco13\FilamentBreezy\Pages\TwoFactorPage;
class CustomTwoFactorPage extends TwoFactorPage
{
protected static string $layout = 'custom.auth.layout.view';
}Since Laravel 11.x Sanctum is no longer included by default. If you don't already have the package installed follow the installation instructions here.
Enable the Sanctum token management component:
BreezyCore::make()
->enableSanctumTokens(
permissions: ['my','custom','permissions'] // optional, customize the permissions (default = ["create", "view", "update", "delete"])
)This button action will prompt the user to enter their password for sensitive actions (eg. delete). This action uses the same 'password_timeout' number of seconds found in config/auth.php.
use Jeffgreco13\FilamentBreezy\Actions\PasswordButtonAction;
use Filament\Support\Icons\Heroicon;
PasswordButtonAction::make('secure_action')->action('doSecureAction')
// Customize the icon, action, modalHeading and anything else.
PasswordButtonAction::make('secure_action')->label('Delete')->icon(Heroicon::ShieldCheck)->modalHeading('Confirmation')->action(fn() => $this->doAction())Sanctum’s Browser Sessions feature, which is disabled by default, allows users to manage their active sessions on different devices and remotely log out of other browser sessions, enhancing account security.
To enable this feature, you must use the enableBrowserSessions method.
This requires your session driver to be database.
To enable the Browser Sessions feature, use the enableBrowserSessions method in BreezyCore:
BreezyCore::make()
->enableBrowserSessions(condition: true) // Enable the Browser Sessions feature (default = true)On the user's profile page, active sessions are displayed with device information, including:
Users can log out of other active sessions by entering their password for confirmation. This allows them to securely log out of all other active sessions on other devices.
If you want to customize the component or modify its behavior, you can override the browser_sessions component in the myProfileComponents method:
BreezyCore::make()
->myProfileComponents([
'browser_sessions' => \App\Livewire\CustomBrowserSessions::class, // Your custom component
])Passkeys let users securely manage their passkeys and sign in without passwords, providing faster and more secure authentication.
Enable passkey authentication using the enablePasskeys() method on the Breezy plugin.
BreezyCore::make()
->enablNo open issues yet, or sync has not completed.