Download the PHP package gabrielesbaiz/nova-two-factor without Composer
On this page you can find all versions of the php package gabrielesbaiz/nova-two-factor. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download gabrielesbaiz/nova-two-factor
More information about gabrielesbaiz/nova-two-factor
Files in gabrielesbaiz/nova-two-factor
Package nova-two-factor
Short Description Two-factor authentication for Laravel Nova: authenticator apps, passkeys, email codes, recovery codes, enforcement policies, step-up re-authentication and admin oversight.
License MIT
Homepage https://github.com/gabrielesbaiz/nova-two-factor
Informations about the package nova-two-factor
Nova Two-Factor
Two-factor authentication for Laravel Nova 5: authenticator apps, passkeys, email codes and recovery codes, with enforcement policies, step-up re-authentication, trusted devices and admin oversight.
[!TIP] Every screen, in light and dark: screenshots.
[!IMPORTANT] A ⭐ costs you nothing and helps other developers find this package. Sponsoring keeps it compatible with every new Laravel release.
[!CAUTION] Upgrading from 1.x? Read UPGRADE.md first. 1.x had critical vulnerabilities, including unauthenticated endpoints and TOTP secrets sent to a third-party QR service by default. Treat every 1.x secret as compromised and have users re-enrol.
Contents
- Introduction
- Requirements
- Installation
- Configuration
- Managing Two-Factor Authentication
- Authentication Methods
- Enforcement
- Step-Up Authentication
- Administration
- Security
- Extending
- Troubleshooting
- Artisan Commands
- Testing
- Contributing
- Security Vulnerabilities
- Credits
- Support This Package
- Disclaimer
- License
Introduction
Nova Two-Factor adds a complete second-factor implementation to Laravel Nova: authenticator applications, passkeys, email codes and recovery codes, backed by an enforcement policy, step-up re-authentication for dangerous actions, trusted devices, an audit trail, and three administration pages.
Nova already ships two-factor authentication of its own, through Laravel Fortify. If authenticator applications and recovery codes for users who opt in are all you need, you should use it:
This package exists for what that cannot do:
| Nova + Fortify | This package | |
|---|---|---|
| Authenticator apps (TOTP) | ✅ | ✅ |
| Recovery codes | ✅ | ✅ |
| Passkeys / WebAuthn | — | ✅ |
| Email one-time codes | — | ✅ |
| More than one method per user | — | ✅ |
| Mandatory enrollment, with a grace period | — | ✅ |
| Per-role targeting | — | ✅ |
| Step-up re-auth for sensitive actions | — | ✅ |
| Trusted devices | — | ✅ |
| Audit trail | — | ✅ |
| Admin oversight and compliance reporting | — | ✅ |
| TOTP replay protection | partial | ✅ |
| Recovery codes hashed individually | — | ✅ |
The last two rows are implementation differences rather than missing features, and both are explained in DESIGN.md.
Requirements
- PHP 8.2+ (8.3+ for Laravel 13)
- Laravel 11, 12 or 13
- Nova 5.7+ (5.11+ for Laravel 13)
httpsin production. Passkeys require a secure context;localhostis exempt.
Installation
Install the package, publish its migrations and configuration, and publish the assets used by the screens that render outside Nova:
Next, add the HasTwoFactorAuthentication trait to each authenticatable model
that may hold a second factor:
Then register the tool in your NovaServiceProvider:
Finally, you should ensure Fortify's updatePasswords and
twoFactorAuthentication features remain enabled. This package renders its own
card on Nova's user security page, and Nova only registers that page when at
least one security feature is active. The updatePasswords feature registers
nova.password.confirm, which guards every destructive route in this package:
You should set confirm and confirmPassword to false. Enrollment
confirmation is handled by this package rather than by Fortify's own endpoint.
[!IMPORTANT] This is a requirement, not a recommendation. With every Fortify security feature disabled,
/user-securitydoes not exist: it returns 404 or 403, and the enrollment screen's links dead-end there.
With the feature enabled, Fortify's RedirectIfTwoFactorAuthenticatable would
divert any user holding a users.two_factor_secret to Fortify's own challenge.
This package supersedes that action, so the challenge stays here, where the
method choice, trusted devices and the audit trail live. Credential validation
is untouched. You may turn this off if you would rather Fortify owned the Nova
login challenge:
[!WARNING] With
supersede_challengeoff and atwo_factor_secreton the row, users reach Fortify's challenge and never see this package's methods — a login that works and logs nothing.doctorchecks for it explicitly.
Middleware is registered for you, on both nova.middleware and
nova.api_middleware. Finally, confirm the installation:
[!NOTE] You should run
doctorin your deploy pipeline. It exits non-zero on a misconfiguration, and it checks the things that otherwise fail silently.[!TIP] Installing with an AI assistant? Point it at AGENTS.md, which carries the keys, the pages, and the constraints that keep an agent from "fixing" a failing test by switching the protection off.
Configuration
All configuration lives in config/nova-two-factor.php. The options that
typically differ between environments read from your .env file first, so
vendor:publish --force can pick up new keys without flattening how a given
environment is tuned:
Factors
| Key | Default | What it does |
|---|---|---|
methods.totp.enabled |
true |
Offer authenticator applications. |
methods.totp.digits / .period |
6 / 30 |
Code length and rotation. Changing either invalidates every enrolled application, so treat them as install-time settings. |
methods.totp.window |
1 |
Steps of clock skew accepted either side. 1 is ±30 seconds, and raising it widens the guessing window proportionally. |
methods.totp.secret_bytes |
32 |
Entropy of the shared secret. |
methods.totp.enrollment_ttl |
900 |
Seconds an unconfirmed secret stays valid. |
methods.webauthn.enabled |
true |
Offer passkeys. Requires https. |
methods.webauthn.relying_party.id |
app host | The domain credentials bind to. It must equal the host users browse, or be a registrable parent of it; a mismatch makes every passkey fail. |
methods.webauthn.origins |
app URL | Exact origins accepted, compared scheme-host-port with no prefix matching. |
methods.webauthn.user_verification |
preferred |
Whether the authenticator must verify the human. Always forced to required for step-up. |
methods.webauthn.resident_key |
preferred |
Ask for a discoverable credential, which lets a passkey sign in without a username. |
methods.webauthn.allowed_aaguids |
[] |
Allow-list of authenticator models. Empty means any. |
methods.webauthn.on_counter_regression |
reject |
What to do when a signature counter goes backwards, which may indicate a cloned key. log accepts and records instead. |
methods.email.enabled |
true |
Offer email codes. |
methods.email.ttl |
300 |
Seconds a code lives. |
methods.email.max_attempts |
5 |
Wrong guesses before the challenge is burned. |
methods.email.resend_after |
60 |
Seconds before another code may be requested. |
methods.email.queue |
false |
Queue the mail. Disabled by default, since a queue that is not running turns a login into a dead end. |
Recovery Codes
| Key | Default | What it does |
|---|---|---|
recovery_codes.count |
8 |
How many are issued. |
recovery_codes.length |
10 |
Characters per code. |
recovery_codes.warn_at |
3 |
Remaining count at which the interface offers regeneration. |
Enforcement
| Key | Default | What it does |
|---|---|---|
enforcement.mode |
optional |
optional, encouraged or required. Only required blocks. |
enforcement.grace_enabled |
true |
Whether required grants any runway before it blocks. |
enforcement.grace_mode |
days |
days for a runway per account; date for one deadline everybody shares. |
enforcement.grace_days |
7 |
With grace_mode: days, the runway each account gets from its created_at. |
enforcement.enforced_from |
null |
With grace_mode: date, the deadline for everyone. |
enforcement.remind_every_days |
7 |
Days that "don't remind me again" lasts under encouraged. The preference is stored against the account rather than the browser. |
enforcement.queue_reminders |
true |
Queue the reminder mail an administrator sends. |
enforcement.remind_cooldown_hours |
24 |
Hours before the same recipient may be sent another reminder. The bulk action skips and reports rather than failing the batch. |
enforcement.gate |
null |
Gate ability deciding who is targeted. null targets everyone. |
enforcement.except |
[] |
Extra request patterns that stay reachable for a non-compliant user. |
Step-Up
| Key | Default | What it does |
|---|---|---|
step_up.ttl |
300 |
Seconds a grant stays fresh. |
step_up.protect |
see config | Scopes requiring a fresh factor, matched against Nova actions and routes. |
Trusted Devices
| Key | Default | What it does |
|---|---|---|
trusted_devices.enabled |
true |
Offer "don't ask again on this device". |
trusted_devices.days |
30 |
How long that lasts. Never offered when a recovery code was used. |
trusted_devices.cookie |
nova_two_factor_device |
Cookie name. |
Rate Limits
Each limiter is keyed on both the user and the IP address, and whichever trips
first wins. Rejections carry a Retry-After header, which the interface
countdown reads.
| Key | Per user | Per IP | Window | Lockout |
|---|---|---|---|---|
rate_limits.challenge |
5 | 60 | 60s | 60s, escalating to 900s |
rate_limits.step_up |
5 | 60 | 60s | 60s, escalating to 900s |
rate_limits.recovery |
10, or 3 malformed | 10 | 1 hour | 1 hour, flat |
rate_limits.enroll |
10 | 30 | 10 min | 10 min, escalating to 1 hour |
rate_limits.otp_send |
3 | 10 | 15 min | 15 min, escalating to 1 hour |
rate_limits.webauthn_per_minute |
30 | — | 60s | — |
Two further options control how the challenge bucket is keyed:
rate_limits.per_device (default true) gives a browser that has cleared a
challenge before its own budget, and rate_limits.device_cookie names the
cookie carrying that marker. The reasoning behind the recovery allowance and the
per-browser split is in DESIGN.md.
Other Options
| Key | Default | What it does |
|---|---|---|
enabled |
true |
Turns the whole package off — routes, middleware, card and all. A codebase serving several panels may use this per domain. |
password_confirmation_ttl |
900 |
Seconds a password confirmation stays fresh for destructive operations. |
alerts.lockout_burst.accounts |
0 |
Distinct accounts locked out inside the window before LockoutBurstDetected fires. 0 disables it. |
alerts.lockout_burst.window_minutes |
15 |
The window that count is measured over. |
audit.enabled |
true |
Write the audit trail. |
audit.queue / .prune_after_days |
false / 365 |
Queue audit writes; retention for nova-two-factor:prune. |
routes.prefix |
two-factor |
Path segment under Nova's own path. |
fortify.supersede_challenge |
true |
Take over Nova's login-pipeline divert. |
settings.editable |
false |
Let administrators change policy from the panel. |
settings.pause_max_minutes |
120 |
Longest pause the panel will offer. |
nova.compliance.enabled |
true |
Register the compliance dashboard. |
nova.compliance.models |
[] |
Populations compliance is measured against. Empty means the model behind Nova's guard. |
nova.menu.show |
true |
Add the menu group automatically. |
nova.menu.label / .icon |
Two-factor / lock-closed |
How that group reads. |
nova.menu.badge |
true |
Show the overdue count on the group. |
nova.admin_gate |
nova-two-factor:admin |
Gate guarding the administration pages and the reset action. Undefined abilities deny, so these start closed. null opens them to any Nova user. |
nova.replace_nova_card |
true |
Substitute this package's card for Nova's own. |
ui.show_method_tradeoffs |
true |
Show each factor's trade-off where a user picks one. |
database.connection / .tables.* |
null / defaults |
Where the tables live, for applications keeping auth data on their own connection. |
Managing Two-Factor Authentication
Users manage their own methods on Nova's existing User Security page. This package replaces Nova's two-factor card in place, so there is nothing extra to link to and it inherits Nova's user-menu entry.
The challenge, step-up and enrollment screens are server-rendered Blade pages rather than Inertia pages, and work with JavaScript disabled. The reason is in DESIGN.md.
Wherever a user picks a factor, each option carries a one-line description and, on its own line, its trade-off:
| Passkey | Cannot be phished. |
| Authenticator app | Works offline. |
| Email code | Weakest option — anyone with your inbox has your second factor. |
These trade-offs are shown by default. If you would rather not put them in front of your users, you may disable them:
The descriptions remain; only the trade-off line disappears. Both come from
MethodType, so they are translatable and identical across every screen.
Translations
Every user-facing string passes through __(), including the strings the
pre-authentication JavaScript writes into the page after load. English and
Italian ship with the package. To translate into another language, copy
resources/lang/en.json to lang/vendor/nova-two-factor/{locale}.json in your
application and translate the values.
Authentication Methods
Authenticator Applications
Enabled by default. The QR code is generated locally as an inline SVG and the setup key is always offered as text, so enrollment works on a machine with no camera and with a screen reader.
Passkeys
Passkeys require https and a relying-party ID matching your host:
The relying-party ID is derived from config('app.url'), never from the request
Host header, and is validated at boot as a registrable parent of your
application host. Install ext-sodium if you want to accept Ed25519
authenticators.
Email Codes
Email codes require a working mailer and are labelled in the interface as the weakest option, since anyone with the user's inbox has their second factor.
Adding an email method sends a code to the address and only counts it once that code comes back, so an attacker holding the password cannot point a second factor at their own inbox.
SMS is not included. The OtpTransport contract is the documented extension
point.
Recovery Codes
Recovery codes are generated on first enrollment, shown once, and stored hashed individually. The package cannot show them again, and says so where they are displayed; the user may copy, download or print them at that moment.
The security card tracks them as a row of ticks, struck through as they are
spent, and offers regeneration at recovery_codes.warn_at remaining. Using a
code signs the user in; it does not turn two-factor authentication off.
Links In Mail
Mail sent by this package links to Nova's user security page, and that link is
not built from APP_URL. Where Nova has a domain of its own, APP_URL names
the customer application instead of the panel.
Links resolve to the host the mail was sent from, then nova.domain, then
APP_URL. You should set nova.domain if you send reminders from a job with no
request behind it.
[!TIP] The same assumption affects passkeys.
nova-two-factor:doctorprints the relying party it derived; if that is your customer domain rather than the panel's, setNOVA_TWO_FACTOR_WEBAUTHN_RP_IDandNOVA_TWO_FACTOR_WEBAUTHN_ORIGINS.
Enforcement
| Mode | Behaviour |
|---|---|
optional |
Nothing required, nothing shown. |
encouraged |
A dismissible prompt. Never blocks a request. |
required |
Nova is unreachable until enrolled, once grace expires. |
Under required, grace has two shapes. Set grace_enabled to false and the
wall appears at the next request; otherwise grace_mode decides the deadline:
grace_mode |
Deadline |
|---|---|
days |
Each account's created_at plus grace_days |
date |
enforced_from, for everyone |
During the grace window, users are shown the enrollment page with a countdown to
their deadline. Choosing Set up later dismisses it for the remainder of the
session. Under encouraged users may also silence the prompt for
enforcement.remind_every_days days; under required they may not.
Targeting Specific Users
You may restrict enforcement to a subset of users with a closure:
Or by naming a gate, which keeps role logic in the authorization layer you already use:
[!WARNING]
enforcement.exceptis the most dangerous setting in this package. Patterns are matched withStr::is, so*crosses slashes:['nova-api/*']leaves every resource, action and metric endpoint open while the pages still redirect. Nothing errors and nothing is logged.nova-two-factor:doctorprints the effective list and fails on any pattern that reaches the dashboard, a resource page or the Nova API.
Step-Up Authentication
You may demand a fresh factor in front of a single dangerous action:
Or per route:
A grant is HMAC-signed over the session, user, scope and expiry, so proving
yourself for one scope never unlocks another. XHR requests receive a 423
response with step_up_required, mirroring Laravel's own RequirePassword, and
the original request is replayed once the grant is issued. Passkey users have
user verification forced to required here, whatever the configuration says.
Administration
The package registers three pages, each answering one question:
| Page | URL | Answers |
|---|---|---|
| Overview | /dashboards/two-factor-compliance |
Are we covered, and who do I chase? |
| Settings | /dashboards/two-factor-settings |
What are the rules, and can I change them? |
| Activity | /resources/two-factor-audits |
What happened, and who did it? |
These pages start closed. nova.admin_gate points at nova-two-factor:admin,
an ability no fresh application defines, and Gate::allows() denies an
undefined ability. Until you say who may see them, nobody can, and the menu
entry does not render:
You may point the option at an ability you already have, or set it to null to
open the pages to every user who can reach Nova.
The Menu
Registering the tool adds a Two-factor group to Nova's menu, displaying the
number of users past their grace period as a badge. Settings appears only when
settings.editable is enabled, and Activity is otherwise hidden from
navigation. You may rename the group with nova.menu.label, change its icon
with nova.menu.icon, or remove it with nova.menu.show; the pages stay
registered and reachable by URL.
[!IMPORTANT] If your application calls
Nova::mainMenu(), none of this appears. A custom main menu replaces Nova's default one entirely, and tool menus are only collected for the default, so the group is dropped with no error. Place it yourself using the helpers below.
The Overview Dashboard
The Overview dashboard renders a single card, read from top to bottom:
- An enrollment ring and a coverage strip.
- The method mix and failed attempts over the last thirty days.
- Six resilience figures: single-factor accounts, recovery-code health, time to enrol, stale enrollments, trusted devices in force, and lockouts.
- The phishing-resistant trend and recent recovery-code sign-ins.
- The queue of users to chase, overdue first.
- Recent administrator actions: reminders, resets and exemptions.
Each figure carries a ? describing what it answers, and clicking a
resilience tile filters the queue to the accounts it counts. Each row's … menu
opens the user's Nova resource, sends a reminder, or resets their two-factor —
the last requiring their email address typed out, a written reason, and your
password.
The sections rendered depend on your enforcement mode: figures that cannot be
true in the current mode are neither sent nor computed. Each mode adds one
figure of its own — blocked at the door under required, reminders sent
under encouraged, and new enrollments under optional.
You may disable the dashboard with nova.compliance.enabled, and the menu badge
alone with nova.menu.badge.
Choosing Which Users Are Measured
Every figure is measured against the model behind Nova's guard. On a panel only administrators can reach, that counts people who can never sign in to Nova. You may name the populations instead:
Class names only, since config:cache cannot serialise a closure. To narrow a
population, register it on the tool:
Both sources are merged, and a runtime registration wins over a configured one for the same class.
The Settings Page
The Settings page is disabled by default. A fresh installation should not hand everyone who reaches Nova the ability to weaken two-factor policy:
With it enabled, an administrator may change the enforcement mode and grace, the methods that may be enrolled, the email-code lifetime, trusted devices, the step-up window, and two interface options. Every write is password-confirmed and audited with both values, and the page shows the last five changes.
The form reshapes as you answer it: settings that do nothing in the chosen mode
are not shown, and settings that depend on another appear with it. Switching to
required displays what it would cost before you save — "would block 13 of 14
administrators" — and at least one method must remain enabled, which is refused
in the interface and again in the endpoint.
Panel values take precedence over .env, which takes precedence over the
shipped defaults. Where the panel and your environment disagree, the field is
marked, and Restore defaults clears every stored value at once.
Some options are deliberately not editable from the panel, among them enabled,
nova.admin_gate, webauthn.relying_party.*, database.* and the rate limits.
The allow-list lives in Settings\SettingSchema, and the reasons are in
DESIGN.md.
Pausing Enforcement
The Settings page can pause enforcement: nobody is challenged, while the administration pages keep working. This is the intended way to fix a misconfigured factor, since a broken second factor is exactly when an administrator cannot reach the page that fixes it.
Every pause carries a duration, capped by settings.pause_max_minutes, and
expires on its own. It is stored in the database rather than the cache, so a
cache flush cannot silently re-arm the gate, and it records who paused it and
why. Pausing does not clear anyone's verified session.
The Activity Log
Every audited event is available as a read-only Nova resource at
/resources/two-factor-audits, reached from the two pages above. It is
read-only in all four directions: an audit trail an administrator can edit is
not an audit trail.
The log is filtered to administrator actions by default. Worth a second look narrows it to suspicious events, and Everything removes the filter. Each row reads as a sentence — "Reminder sent to Priya Raman by Alex Morgan" — and the badge is coloured by severity.
Placing The Menu Entry Yourself
Switch the automatic entry off and place it wherever you like. The pages stay registered either way:
menuItems() returns Overview, Settings (when editing is enabled) and Activity;
menuItem() returns the first alone. Every helper carries its destination's own
authorization, so placing an entry by hand cannot expose it to someone the gate
would have refused. NovaTwoFactor::make()->withoutMenu() is the fluent
equivalent of the configuration option.
Resources, Fields and Actions
SendEnrollmentReminder mails the users who have not enrolled, skipping anyone
who has. The mail carries their own grace deadline under required, quotes an
optional note as coming from the administrator who sent it, and every send is
audited.
Security
| Control | Implementation |
|---|---|
| TOTP secrets | encrypted cast, 160-bit, never in a URL or log |
| Recovery codes | SHA-256, individually, unique index, single-use |
| Email codes | HMAC-SHA256 keyed on APP_KEY, single-use, short TTL |
| Passkey credentials | encrypted:json; lookup by SHA-256 of the credential ID |
| Trusted devices | 64-character token, only its hash stored |
| Step-up grants | HMAC over session, user, scope and expiry |
| QR codes | Generated locally. There is no remote code path. |
Routes that issue or destroy a factor require a verified session — a cleared challenge, not merely a confirmed password. The only exception is an account with nothing enrolled yet, which has no second factor to prove.
Removing a method, revealing or regenerating recovery codes, and revoking devices each require a fresh password confirmation, applied as route middleware. Removing the last factor is refused while enforcement requires one.
Every enrollment, challenge, lockout, replay, reset and device change is recorded. Codes, secrets, credentials and destinations never are; a guard throws outside production if a payload even looks like it carries one.
The cryptographic choices, the rate-limiting design and the threat model behind them are documented in DESIGN.md.
Extending
You may register your own factor type:
Implement Contracts\TwoFactorMethodDriver. Enrollment must be idempotent for
the lifetime of a pending enrollment, or refreshing the setup page will
invalidate the QR code the user has just scanned.
Sending email codes over another transport, listening to two-factor events, and alerting on a lockout burst are covered in DESIGN.md.
Troubleshooting
"Everyone is locked out at once"
Several lockouts at once usually means somebody is working through a list of stolen passwords. They cannot get in; under `required` they can keep others out. - **Trusted devices keep working.** A browser that has already cleared a challenge is unaffected. - **Lockouts expire** after `rate_limits.challenge.lockout` seconds, rising to `lockout_ceiling`. Nobody has to clear anything. - **An administrator may free one account now** by resetting its second factor from the Overview dashboard. - **`php artisan nova-two-factor:reset [email protected]`** does the same from the command line, and also clears that user's rate-limit buckets. To hear about it rather than discover it, set a threshold and listen for `LockoutBurstDetected`:"Codes are always invalid"
Clock skew, nearly always. TOTP codes are derived from the current time, so a phone whose clock has drifted generates codes the server rejects. Set the device clock to automatic. You may widen the window if you must — each step is 30 seconds either way:"Passkeys aren't offered"
Run `php artisan nova-two-factor:doctor`. Almost always one of: - `app.url` is not `https` (`localhost` is exempt) - the relying-party ID is not a registrable parent of the host you are browsing - the browser has no platform authenticator"I'm locked out of my own admin panel"
This clears every method, recovery code and trusted device, every rate-limit bucket keyed to that user, every session predating the reset, and any reminder snooze. An audit row is written and attributed. There is deliberately no way to do this from inside the panel you cannot reach."The UI looks unstyled after upgrading"
Republish the assets:Artisan Commands
| Command | Purpose |
|---|---|
nova-two-factor:doctor |
Check the configuration. Non-zero exit on failure. |
nova-two-factor:reset {user} |
Break-glass reset: methods, codes, devices, lockouts, sessions and reminder snooze. Accepts --force and --ip=. |
nova-two-factor:prune |
Remove expired challenges, devices and old audit rows. |
nova-two-factor:upgrade |
Port 1.x nova_twofa data. See UPGRADE.md. |
You should schedule the prune:
Testing
The suite includes a regression test for every vulnerability found in 1.x.
Contributing
Thank you for considering contributing. The guide is in CONTRIBUTING.md.
Security Vulnerabilities
Please review SECURITY.md for reporting a vulnerability. Please do not open a public issue.
Credits
Written and maintained by Gabriele Sbaiz.
This package builds on Laravel, Nova, Fortify, web-auth/webauthn-lib, pragmarx/google2fa, bacon/bacon-qr-code, spatie/laravel-package-tools, and the WebAuthn and TOTP specifications.
Support This Package
I maintain this on evenings and weekends, alongside a full-time job writing
insurance software. Keeping it green across new Laravel and Nova majors is the
unglamorous part, and it is what keeps this installable in your
composer.json next year too.
If it is useful to you:
- ⭐ Star the repo. Free, thirty seconds, and it is the first signal other developers look at.
- ❤️ Become a sponsor. From $5 a month. Company tiers get your logo right here in this README.
- 🐛 Open a good issue. A clear reproduction is worth more than you think.
- 🗣️ Tell another Laravel developer. Word of mouth is how packages survive.
Disclaimer
This package is provided as is, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, title and non-infringement. To the fullest extent permitted by applicable law, in no event shall the authors, copyright holders or contributors be liable for any claim, damages or other liability — whether in an action of contract, tort or otherwise — arising from, out of or in connection with this package or its use, including without limitation any direct, indirect, incidental, special, exemplary, consequential or punitive damages, loss of data, loss of profits, business interruption, account lockouts, unauthorised access, or failure of any authentication control.
Two-factor authentication is a security control: whoever deploys it is
responsible for it. That responsibility includes, and is not limited to,
choosing appropriate configuration, running nova-two-factor:doctor before
relying on it, testing enforcement and recovery on your own infrastructure,
keeping recovery paths available to your users, meeting whatever regulatory or
contractual obligations apply to you, and reviewing the code yourself before
putting it in front of an account you cannot afford to lose. Nothing here
constitutes security, legal or compliance advice, and no claim is made that this
package makes any system, application or organisation secure or compliant with
any standard.
Use of this package is entirely at your own risk.
License
MIT. See LICENSE.md. The MIT licence's warranty disclaimer and limitation of liability apply in full, alongside the section above.
All versions of nova-two-factor with dependencies
ext-json Version *
ext-openssl Version *
bacon/bacon-qr-code Version ^3.0
illuminate/support Version ^11.0|^12.0|^13.0
laravel/fortify Version ^1.25.4
laravel/nova Version ^5.7
pragmarx/google2fa Version ^8.0|^9.0
spatie/laravel-package-tools Version ^1.16
web-auth/webauthn-lib Version ^5.1