From 31ff741dbf47d4b8f8f824b54e5308f7d065fe4d Mon Sep 17 00:00:00 2001 From: Dennis Elsinga Date: Fri, 23 Aug 2024 11:12:17 +0200 Subject: [PATCH 01/12] Add translations for email --- resources/lang/en.json | 3 ++- resources/lang/nl.json | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/resources/lang/en.json b/resources/lang/en.json index cb405ac..e401025 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -29,5 +29,6 @@ "Your security code is": "Your security code is", "The provided two factor authentication code was invalid.": "The provided two factor authentication code was invalid.", "Generate new recovery codes": "Generate new recovery codes", - "You can disable two factor authentication at any time by using the button below": "You can disable two factor authentication at any time by using the button below" + "You can disable two factor authentication at any time by using the button below": "You can disable two factor authentication at any time by using the button below", + "Hello": "Hello" } \ No newline at end of file diff --git a/resources/lang/nl.json b/resources/lang/nl.json index 7976e14..e2b0d3b 100644 --- a/resources/lang/nl.json +++ b/resources/lang/nl.json @@ -29,5 +29,9 @@ "Your security code is": "Uw beveiligingscode is", "The provided two factor authentication code was invalid.": "De verstrekte tweestaps-verificatiecode was ongeldig.", "Generate new recovery codes": "Genereer nieuwe herstelcodes", - "You can disable two factor authentication at any time by using the button below": "U kunt tweestaps-verificatie op elk moment uitschakelen met de onderstaande knop" + "You can disable two factor authentication at any time by using the button below": "U kunt tweestaps-verificatie op elk moment uitschakelen met de onderstaande knop", + "You recently requested to log in to your account. To complete the login, please use the following two-factor authentication (2FA) code:": "U heeft onlangs gevraagd om in te loggen op uw account. Gebruik de volgende tweestaps-verificatie (2FA) code om de login te voltooien:", + "If you didn't try to log in, please change your password immediately to protect your account.": "Als u niet heeft geprobeerd in te loggen, wijzig dan onmiddellijk uw wachtwoord om uw account te beschermen.", + "Kind regards": "Met vriendelijke groet", + "Hello": "Hallo" } \ No newline at end of file From 00e635b08250f83788be829601de96b492968f81 Mon Sep 17 00:00:00 2001 From: Dennis Elsinga Date: Fri, 23 Aug 2024 11:12:34 +0200 Subject: [PATCH 02/12] Add custom view for mail --- resources/views/mails/two-factor-code.blade.php | 17 +++++++++++++++++ src/Notifications/SendOTP.php | 6 ++++-- 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 resources/views/mails/two-factor-code.blade.php diff --git a/resources/views/mails/two-factor-code.blade.php b/resources/views/mails/two-factor-code.blade.php new file mode 100644 index 0000000..e878c55 --- /dev/null +++ b/resources/views/mails/two-factor-code.blade.php @@ -0,0 +1,17 @@ + +{{ __('Hello') }}, + +{{ __('You recently requested to log in to your account. To complete the login, please use the following two-factor authentication (2FA) code:') }} + +
+ + {{ $code }} + +
+ + +{{ __('If you didn\'t try to log in, please change your password immediately to protect your account.') }} + +{{ __('Kind regards') }},
+{{ config('app.name') }} +
\ No newline at end of file diff --git a/src/Notifications/SendOTP.php b/src/Notifications/SendOTP.php index 0192822..e1470c7 100644 --- a/src/Notifications/SendOTP.php +++ b/src/Notifications/SendOTP.php @@ -53,7 +53,9 @@ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->subject(__('Your security code for :app', ['app' => config('app.name')])) - ->line(__('Your security code is') . ' ' . $this->getTwoFactorCode($notifiable)); + ->markdown('filament-two-factor-auth::mails.two-factor-code', [ + 'code' => $this->getTwoFactorCode($notifiable) + ]); } /** @@ -75,7 +77,7 @@ public function toArray(object $notifiable): array */ public function getTwoFactorCode(User $notifiable): ?string { - if (! $notifiable->two_factor_secret) { + if (!$notifiable->two_factor_secret) { return null; } From 0ef0642ebc99f478a67de21588f15a397424c987 Mon Sep 17 00:00:00 2001 From: Dennis Elsinga Date: Fri, 23 Aug 2024 11:15:51 +0200 Subject: [PATCH 03/12] Add translation --- resources/lang/en.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/lang/en.json b/resources/lang/en.json index e401025..3709ba7 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -30,5 +30,7 @@ "The provided two factor authentication code was invalid.": "The provided two factor authentication code was invalid.", "Generate new recovery codes": "Generate new recovery codes", "You can disable two factor authentication at any time by using the button below": "You can disable two factor authentication at any time by using the button below", + "If you didn't try to log in, please change your password immediately to protect your account.": "If you didn't try to log in, please change your password immediately to protect your account.", + "You recently requested to log in to your account. To complete the login, please use the following two-factor authentication (2FA) code:": "You recently requested to log in to your account. To complete the login, please use the following two-factor authentication (2FA) code:", "Hello": "Hello" } \ No newline at end of file From 936c809cd485679bc51b39674e388afa7b716faa Mon Sep 17 00:00:00 2001 From: Dennis Elsinga Date: Fri, 23 Aug 2024 11:16:12 +0200 Subject: [PATCH 04/12] Add "Kind regards" translation --- resources/lang/en.json | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/en.json b/resources/lang/en.json index 3709ba7..8d67181 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -32,5 +32,6 @@ "You can disable two factor authentication at any time by using the button below": "You can disable two factor authentication at any time by using the button below", "If you didn't try to log in, please change your password immediately to protect your account.": "If you didn't try to log in, please change your password immediately to protect your account.", "You recently requested to log in to your account. To complete the login, please use the following two-factor authentication (2FA) code:": "You recently requested to log in to your account. To complete the login, please use the following two-factor authentication (2FA) code:", + "Kind regards": "Kind regards", "Hello": "Hello" } \ No newline at end of file From 2779c35030faa29b9f7248c8c46474e2db8b7f64 Mon Sep 17 00:00:00 2001 From: Dennis Elsinga Date: Fri, 23 Aug 2024 11:16:59 +0200 Subject: [PATCH 05/12] Pint --- src/Notifications/SendOTP.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Notifications/SendOTP.php b/src/Notifications/SendOTP.php index e1470c7..6b508cc 100644 --- a/src/Notifications/SendOTP.php +++ b/src/Notifications/SendOTP.php @@ -54,7 +54,7 @@ public function toMail(object $notifiable): MailMessage return (new MailMessage) ->subject(__('Your security code for :app', ['app' => config('app.name')])) ->markdown('filament-two-factor-auth::mails.two-factor-code', [ - 'code' => $this->getTwoFactorCode($notifiable) + 'code' => $this->getTwoFactorCode($notifiable), ]); } @@ -77,7 +77,7 @@ public function toArray(object $notifiable): array */ public function getTwoFactorCode(User $notifiable): ?string { - if (!$notifiable->two_factor_secret) { + if (! $notifiable->two_factor_secret) { return null; } From 0f7e8d06498c45bc200710cf30d1492cdd37b30b Mon Sep 17 00:00:00 2001 From: Dennis Elsinga Date: Fri, 23 Aug 2024 11:28:43 +0200 Subject: [PATCH 06/12] Remove view --- resources/views/two-factor.blade.php | 109 --------------------------- 1 file changed, 109 deletions(-) delete mode 100644 resources/views/two-factor.blade.php diff --git a/resources/views/two-factor.blade.php b/resources/views/two-factor.blade.php deleted file mode 100644 index 238598d..0000000 --- a/resources/views/two-factor.blade.php +++ /dev/null @@ -1,109 +0,0 @@ - -
-
-
-

- {{ __('Secure your account') }} -

- - @if (!$showingRecoveryCodes && auth()->user()->two_factor_confirmed_at) -

- {{ __('Your account has been secured with two factor authentication') }}. -

- @else -

- {{ __('Add additional security to your account using two factor authentication') }}. -

- @endif -
- - - - {{ __('You can disable two factor authentication at any time by using the button below') }}. - - - @if (! $showingRecoveryCodes && auth()->user()->two_factor_confirmed_at) - {{ $this->disableAction() }} - @else - - {{ __('You have :amount options to confirm your identity, please choose one of the options below to continue',['amount' => $this->twoFactorOptionsCount]) }}. - - @endif - - @if (!auth()->user()->hasEnabledTwoFactorAuthentication() || $this->showingRecoveryCodes) - @if (!$this->showTwoFactor()) - {{ $this->twoFactorOptionForm }} - -
{{ $this->enableAction() }}
- @endif - - @if ($this->showTwoFactor()) -
-
-
- @if ($this->showQrCode) -
-
- @unless ($showingQrCode) -
- {!! __('Two-Factor Authentication enabled') !!} -
- @else -
- {!! __('Or scan the QR code with your authenticator app') !!}. -
-
- {!! auth()->user()->twoFactorQrCodeSvg() !!} -
-
-

- {!! __('The secret key to setup the authenticator app is') !!}:
- {{ decrypt(auth()->user()->two_factor_secret) }} -

- @endunless -
-
- @endif - - @if ($showingRecoveryCodes) -
- {!! __( - 'Save these recovery codes in a secure place as they can be used to recover access to your account if you lose your device', - ) !!}. -
-
- @foreach ((array) auth()->user()->recoveryCodes() as $index => $code) -

{{ $code }}

- @endforeach -
-
-
- @endif - - @if ($showingConfirmation) -
- {{ $this->otpCodeForm }} -
- @endif - -
- @if (!$showingRecoveryCodes && !auth()->user()->two_factor_confirmed_at) - {{ $this->disableAction() }} - @endif - - @if ($showingRecoveryCodes) - {{ $this->regenerateAction() }} - @elseif ($showingConfirmation) - {{ $this->confirmAction() }} - @endif -
-
-
-
- @endif - @endif -
-
-
-
From bd53d373c9e5927a87711eba5f308d9ab2d09801 Mon Sep 17 00:00:00 2001 From: Dennis Elsinga Date: Fri, 23 Aug 2024 11:29:17 +0200 Subject: [PATCH 07/12] Undo --- resources/views/two-factor.blade.php | 109 +++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 resources/views/two-factor.blade.php diff --git a/resources/views/two-factor.blade.php b/resources/views/two-factor.blade.php new file mode 100644 index 0000000..238598d --- /dev/null +++ b/resources/views/two-factor.blade.php @@ -0,0 +1,109 @@ + +
+
+
+

+ {{ __('Secure your account') }} +

+ + @if (!$showingRecoveryCodes && auth()->user()->two_factor_confirmed_at) +

+ {{ __('Your account has been secured with two factor authentication') }}. +

+ @else +

+ {{ __('Add additional security to your account using two factor authentication') }}. +

+ @endif +
+ + + + {{ __('You can disable two factor authentication at any time by using the button below') }}. + + + @if (! $showingRecoveryCodes && auth()->user()->two_factor_confirmed_at) + {{ $this->disableAction() }} + @else + + {{ __('You have :amount options to confirm your identity, please choose one of the options below to continue',['amount' => $this->twoFactorOptionsCount]) }}. + + @endif + + @if (!auth()->user()->hasEnabledTwoFactorAuthentication() || $this->showingRecoveryCodes) + @if (!$this->showTwoFactor()) + {{ $this->twoFactorOptionForm }} + +
{{ $this->enableAction() }}
+ @endif + + @if ($this->showTwoFactor()) +
+
+
+ @if ($this->showQrCode) +
+
+ @unless ($showingQrCode) +
+ {!! __('Two-Factor Authentication enabled') !!} +
+ @else +
+ {!! __('Or scan the QR code with your authenticator app') !!}. +
+
+ {!! auth()->user()->twoFactorQrCodeSvg() !!} +
+
+

+ {!! __('The secret key to setup the authenticator app is') !!}:
+ {{ decrypt(auth()->user()->two_factor_secret) }} +

+ @endunless +
+
+ @endif + + @if ($showingRecoveryCodes) +
+ {!! __( + 'Save these recovery codes in a secure place as they can be used to recover access to your account if you lose your device', + ) !!}. +
+
+ @foreach ((array) auth()->user()->recoveryCodes() as $index => $code) +

{{ $code }}

+ @endforeach +
+
+
+ @endif + + @if ($showingConfirmation) +
+ {{ $this->otpCodeForm }} +
+ @endif + +
+ @if (!$showingRecoveryCodes && !auth()->user()->two_factor_confirmed_at) + {{ $this->disableAction() }} + @endif + + @if ($showingRecoveryCodes) + {{ $this->regenerateAction() }} + @elseif ($showingConfirmation) + {{ $this->confirmAction() }} + @endif +
+
+
+
+ @endif + @endif +
+
+
+
From 85bff315e1e2cfddce5af116f6f0bdb8095be749 Mon Sep 17 00:00:00 2001 From: Dennis Elsinga Date: Fri, 23 Aug 2024 11:37:15 +0200 Subject: [PATCH 08/12] Rename folder to `emails` --- resources/views/{mails => emails}/two-factor-code.blade.php | 0 src/Notifications/SendOTP.php | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename resources/views/{mails => emails}/two-factor-code.blade.php (100%) diff --git a/resources/views/mails/two-factor-code.blade.php b/resources/views/emails/two-factor-code.blade.php similarity index 100% rename from resources/views/mails/two-factor-code.blade.php rename to resources/views/emails/two-factor-code.blade.php diff --git a/src/Notifications/SendOTP.php b/src/Notifications/SendOTP.php index 6b508cc..c41023c 100644 --- a/src/Notifications/SendOTP.php +++ b/src/Notifications/SendOTP.php @@ -53,7 +53,7 @@ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->subject(__('Your security code for :app', ['app' => config('app.name')])) - ->markdown('filament-two-factor-auth::mails.two-factor-code', [ + ->markdown('filament-two-factor-auth::emails.two-factor-code', [ 'code' => $this->getTwoFactorCode($notifiable), ]); } @@ -77,7 +77,7 @@ public function toArray(object $notifiable): array */ public function getTwoFactorCode(User $notifiable): ?string { - if (! $notifiable->two_factor_secret) { + if (!$notifiable->two_factor_secret) { return null; } From 5949b9335816d4cd13eade679f0460e58a76635c Mon Sep 17 00:00:00 2001 From: Dennis Elsinga Date: Fri, 23 Aug 2024 11:37:51 +0200 Subject: [PATCH 09/12] Format again (sorry) --- src/Notifications/SendOTP.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Notifications/SendOTP.php b/src/Notifications/SendOTP.php index c41023c..8870e80 100644 --- a/src/Notifications/SendOTP.php +++ b/src/Notifications/SendOTP.php @@ -77,7 +77,7 @@ public function toArray(object $notifiable): array */ public function getTwoFactorCode(User $notifiable): ?string { - if (!$notifiable->two_factor_secret) { + if (! $notifiable->two_factor_secret) { return null; } From fa710ab25484e429d2bcbedeff04f2a66f7df7ba Mon Sep 17 00:00:00 2001 From: Dennis Elsinga Date: Fri, 23 Aug 2024 12:56:47 +0200 Subject: [PATCH 10/12] Update README --- README.md | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 04bf894..d495feb 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ [![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/vormkracht10/filament-two-factor-auth/run-tests.yml?branch=main&label=tests&style=flat-square)](https://github.com/vormkracht10/filament-two-factor-auth/actions?query=workflow%3Arun-tests+branch%3Amain) [![Total Downloads](https://img.shields.io/packagist/dt/vormkracht10/filament-two-factor-auth.svg?style=flat-square)](https://packagist.org/packages/vormkracht10/filament-two-factor-auth) - -This package adds Two Factor Authentication for your Laravel Filament app, using the first party package Laravel Fortify. We provide the views and logic to enable Two Factor Authentication (2FA) in your Filament app. Possible authentication methods are: +This package adds Two Factor Authentication for your Laravel Filament app, using the first party package Laravel Fortify. We provide the views and logic to enable Two Factor Authentication (2FA) in +your Filament app. Possible authentication methods are: - Email - SMS @@ -14,20 +14,24 @@ This package adds Two Factor Authentication for your Laravel Filament app, using ## Features and screenshots ### Enable Two Factor Authentication (2FA) + ![Enable Two Factor Authentication (2FA)](./docs/two-factor-page.png) ### Using authenticator app as two factor method + ![Authenticator app](./docs/authenticator-app.png) ### Using email or SMS as two factor method + ![Email or SMS](./docs/email-or-sms.png) ### Recovery codes + ![Recovery codes](./docs/recovery-codes.png) ### Two Factor authentication challenge -![Two Factor challenge](./docs/code-challenge.png) +![Two Factor challenge](./docs/code-challenge.png) ## Installation @@ -108,11 +112,18 @@ protected $listen = [ ], ]; ``` + +If you want to customize the views (including email), you can publish them using the following command: + +```bash +php artisan vendor:publish --tag=filament-two-factor-auth-views +``` + ## Usage ### Configuration -The authentication methods can be configured in the `config/filament-two-factor-auth.php` file (which is published during the install command). +The authentication methods can be configured in the `config/filament-two-factor-auth.php` file (which is published during the install command). You can simply add or remove (comment) the methods you want to use: @@ -128,7 +139,8 @@ return [ ]; ``` -If you want to use the SMS method, you need to provide an SMS service. You can check the [Laravel Notifications documentation](https://laravel-notification-channels.com/about/) for ready-to-use services. +If you want to use the SMS method, you need to provide an SMS service. You can check the [Laravel Notifications documentation](https://laravel-notification-channels.com/about/) for ready-to-use +services. **Also make sure your user model has a `phone` attribute.** From 7e4ede60b53c04f2d9556f01c4e58f0ec46253b7 Mon Sep 17 00:00:00 2001 From: Dennis Elsinga Date: Fri, 23 Aug 2024 13:34:19 +0200 Subject: [PATCH 11/12] Add TwoFactorCodeMail for sending OTP emails --- src/Mail/TwoFactorCodeMail.php | 52 ++++++++++++++++++++++++++++++++++ src/Notifications/SendOTP.php | 13 ++++----- 2 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 src/Mail/TwoFactorCodeMail.php diff --git a/src/Mail/TwoFactorCodeMail.php b/src/Mail/TwoFactorCodeMail.php new file mode 100644 index 0000000..111e394 --- /dev/null +++ b/src/Mail/TwoFactorCodeMail.php @@ -0,0 +1,52 @@ + config('app.name')]), + ); + } + + /** + * Get the message content definition. + */ + public function content(): Content + { + return new Content( + markdown: 'filament-two-factor-auth::emails.two-factor-code', + ); + } + + /** + * Get the attachments for the message. + * + * @return array + */ + public function attachments(): array + { + return []; + } +} diff --git a/src/Notifications/SendOTP.php b/src/Notifications/SendOTP.php index 7980b97..eff1364 100644 --- a/src/Notifications/SendOTP.php +++ b/src/Notifications/SendOTP.php @@ -4,6 +4,7 @@ use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Mail\Mailable; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Notification; use PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException; @@ -11,6 +12,7 @@ use PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException; use Vormkracht10\TwoFactorAuth\Actions\GenerateOTP; use Vormkracht10\TwoFactorAuth\Enums\TwoFactorType; +use Vormkracht10\TwoFactorAuth\Mail\TwoFactorCodeMail; class SendOTP extends Notification implements ShouldQueue { @@ -48,13 +50,10 @@ public function via(object $notifiable): array /** * Get the mail representation of the notification. */ - public function toMail(object $notifiable): MailMessage + public function toMail(object $notifiable): Mailable { - return (new MailMessage) - ->subject(__('Your security code for :app', ['app' => config('app.name')])) - ->markdown('filament-two-factor-auth::emails.two-factor-code', [ - 'code' => $this->getTwoFactorCode($notifiable), - ]); + return (new TwoFactorCodeMail($this->getTwoFactorCode($notifiable))) + ->to($notifiable->email); } /** @@ -76,7 +75,7 @@ public function toArray(object $notifiable): array */ public function getTwoFactorCode(object $notifiable): ?string { - if (! $notifiable->two_factor_secret) { + if (!$notifiable->two_factor_secret) { return null; } From 09b6f315d67302f334b63c320f2c68cac01420b9 Mon Sep 17 00:00:00 2001 From: Dennis Elsinga Date: Fri, 23 Aug 2024 13:36:30 +0200 Subject: [PATCH 12/12] Format --- src/Mail/TwoFactorCodeMail.php | 3 ++- src/Notifications/SendOTP.php | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Mail/TwoFactorCodeMail.php b/src/Mail/TwoFactorCodeMail.php index 111e394..7332eba 100644 --- a/src/Mail/TwoFactorCodeMail.php +++ b/src/Mail/TwoFactorCodeMail.php @@ -10,7 +10,8 @@ class TwoFactorCodeMail extends Mailable { - use Queueable, SerializesModels; + use Queueable; + use SerializesModels; /** * Create a new message instance. diff --git a/src/Notifications/SendOTP.php b/src/Notifications/SendOTP.php index eff1364..76a6b29 100644 --- a/src/Notifications/SendOTP.php +++ b/src/Notifications/SendOTP.php @@ -5,7 +5,6 @@ use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Mail\Mailable; -use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Notification; use PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException; use PragmaRX\Google2FA\Exceptions\InvalidCharactersException; @@ -75,7 +74,7 @@ public function toArray(object $notifiable): array */ public function getTwoFactorCode(object $notifiable): ?string { - if (!$notifiable->two_factor_secret) { + if (! $notifiable->two_factor_secret) { return null; }