From 52d2ffb27e8a966b05224c1b9f044831a3aaf161 Mon Sep 17 00:00:00 2001 From: JoanFo1456 Date: Sat, 7 Feb 2026 12:36:07 +0100 Subject: [PATCH 01/18] Passkeys working! --- app/Models/User.php | 15 +- .../Filament/FilamentServiceProvider.php | 2 + app/Providers/Filament/PanelProvider.php | 4 + composer.json | 1 + composer.lock | 927 +++++++++++++++++- ...026_02_07_103629_create_passkeys_table.php | 32 + .../filament-passkeys-styles.css | 2 + .../filament-passkeys-scripts.js | 2 + .../components/authenticate.blade.php | 23 + .../partials/authenticateScript.blade.php | 18 + .../livewire/partials/createScript.blade.php | 11 + .../passkeys/livewire/passkeys.blade.php | 42 + routes/auth.php | 1 + 13 files changed, 1038 insertions(+), 42 deletions(-) create mode 100644 database/migrations/2026_02_07_103629_create_passkeys_table.php create mode 100644 public/css/marcelweidum/filament-passkeys/filament-passkeys-styles.css create mode 100644 public/js/marcelweidum/filament-passkeys/filament-passkeys-scripts.js create mode 100644 resources/views/vendor/passkeys/components/authenticate.blade.php create mode 100644 resources/views/vendor/passkeys/components/partials/authenticateScript.blade.php create mode 100644 resources/views/vendor/passkeys/livewire/partials/createScript.blade.php create mode 100644 resources/views/vendor/passkeys/livewire/passkeys.blade.php diff --git a/app/Models/User.php b/app/Models/User.php index 57b42d45ae..a0727f831f 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -43,6 +43,8 @@ use Illuminate\Support\Str; use Illuminate\Validation\Rules\In; use ResourceBundle; +use Spatie\LaravelPasskeys\Models\Concerns\HasPasskeys; +use Spatie\LaravelPasskeys\Models\Concerns\InteractsWithPasskeys; use Spatie\Permission\Traits\HasRoles; /** @@ -94,7 +96,7 @@ * @method static Builder|User whereUsername($value) * @method static Builder|User whereUuid($value) */ -class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, FilamentUser, HasAppAuthentication, HasAppAuthenticationRecovery, HasAvatar, HasEmailAuthentication, HasName, HasTenants, Validatable +class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, FilamentUser, HasAppAuthentication, HasAppAuthenticationRecovery, HasAvatar, HasEmailAuthentication, HasName, HasTenants, Validatable, HasPasskeys { use Authenticatable; use Authorizable { can as protected canned; } @@ -104,6 +106,7 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac use HasRoles; use HasValidation { getRules as getValidationRules; } use Notifiable; + use HasFactory, Notifiable, InteractsWithPasskeys; public const USER_LEVEL_USER = 0; @@ -504,4 +507,14 @@ public function toggleEmailAuthentication(bool $condition): void { $this->update(['mfa_email_enabled' => $condition]); } + + public function getPasskeyDisplayName(): string + { + return $this->username ?? $this->email; + } + + public function getPasskeyUserId(): string + { + return $this->id; + } } diff --git a/app/Providers/Filament/FilamentServiceProvider.php b/app/Providers/Filament/FilamentServiceProvider.php index 5b30646aa2..581a3f04eb 100644 --- a/app/Providers/Filament/FilamentServiceProvider.php +++ b/app/Providers/Filament/FilamentServiceProvider.php @@ -33,6 +33,7 @@ use Illuminate\Support\ServiceProvider; use Livewire\Component; use Livewire\Livewire; +use MarcelWeidum\Passkeys\Livewire\Passkeys as FilamentPasskeys; use function Livewire\on; use function Livewire\store; @@ -257,6 +258,7 @@ public function boot(): void SchemaIconAlias::COMPONENTS_WIZARD_COMPLETED_STEP => TablerIcon::Check, ]); + Livewire::component('filament-passkeys', FilamentPasskeys::class); } public function register(): void {} diff --git a/app/Providers/Filament/PanelProvider.php b/app/Providers/Filament/PanelProvider.php index 09339d81f3..e82dbc5e31 100644 --- a/app/Providers/Filament/PanelProvider.php +++ b/app/Providers/Filament/PanelProvider.php @@ -22,6 +22,7 @@ use Illuminate\Session\Middleware\AuthenticateSession; use Illuminate\Session\Middleware\StartSession; use Illuminate\View\Middleware\ShareErrorsFromSession; +use MarcelWeidum\Passkeys\PasskeysPlugin; abstract class PanelProvider extends BasePanelProvider { @@ -56,6 +57,9 @@ public function panel(Panel $panel): Panel AppAuthentication::make()->recoverable(), EmailAuthentication::make(), ]) + ->plugins([ + PasskeysPlugin::make(), + ]) ->middleware([ EncryptCookies::class, AddQueuedCookiesToResponse::class, diff --git a/composer.json b/composer.json index b29ac9b5f8..d78a082a4e 100644 --- a/composer.json +++ b/composer.json @@ -24,6 +24,7 @@ "lcobucci/jwt": "^5.6", "league/flysystem-aws-s3-v3": "^3.31", "league/flysystem-memory": "^3.31", + "marcelweidum/filament-passkeys": "^2.0", "phiki/phiki": "^2.0", "phpseclib/phpseclib": "~3.0.18", "predis/predis": "^2.3", diff --git a/composer.lock b/composer.lock index 13aed6b43e..e99516d6dc 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "15f89930db77693b2d692dbadf22fb9f", + "content-hash": "65473c308a5b557676d504355e4d2d5d", "packages": [ { "name": "anourvalar/eloquent-serialize", @@ -4337,6 +4337,79 @@ ], "time": "2026-01-23T05:41:38+00:00" }, + { + "name": "marcelweidum/filament-passkeys", + "version": "v2.0.2", + "source": { + "type": "git", + "url": "https://github.com/MarcelWeidum/filament-passkeys.git", + "reference": "ccb80dcda3a0bcc4aacb42043d88c528b17bc7fa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MarcelWeidum/filament-passkeys/zipball/ccb80dcda3a0bcc4aacb42043d88c528b17bc7fa", + "reference": "ccb80dcda3a0bcc4aacb42043d88c528b17bc7fa", + "shasum": "" + }, + "require": { + "filament/filament": "^4.0|^5.0", + "php": "^8.2", + "spatie/laravel-package-tools": "^1.15.0", + "spatie/laravel-passkeys": "^1.5.3", + "web-auth/webauthn-lib": "5.2.3" + }, + "require-dev": { + "laravel/pint": "^1.0", + "spatie/laravel-ray": "^1.26" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Passkeys": "MarcelWeidum\\Passkeys\\Facades\\Passkeys" + }, + "providers": [ + "MarcelWeidum\\Passkeys\\PasskeysServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "MarcelWeidum\\Passkeys\\": "src/", + "MarcelWeidum\\Passkeys\\Database\\Factories\\": "database/factories/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "MarcelWeidum", + "role": "Developer" + } + ], + "description": "Use passkeys in your filamentphp app", + "homepage": "https://github.com/marcelweidum/filament-passkeys", + "keywords": [ + "MarcelWeidum", + "filament", + "filament-passkeys", + "filamentphp", + "laravel" + ], + "support": { + "issues": "https://github.com/marcelweidum/filament-passkeys/issues", + "source": "https://github.com/marcelweidum/filament-passkeys" + }, + "funding": [ + { + "url": "https://www.buymeacoffee.com/MarcelWeidum", + "type": "buy_me_a_coffee" + } + ], + "time": "2026-01-17T13:21:33+00:00" + }, { "name": "masterminds/html5", "version": "2.10.0", @@ -7809,6 +7882,84 @@ ], "time": "2025-07-17T15:46:43+00:00" }, + { + "name": "spatie/laravel-passkeys", + "version": "1.5.3", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-passkeys.git", + "reference": "641217418497ffa9fdb6c2f5f67a1332b58a6012" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-passkeys/zipball/641217418497ffa9fdb6c2f5f67a1332b58a6012", + "reference": "641217418497ffa9fdb6c2f5f67a1332b58a6012", + "shasum": "" + }, + "require": { + "illuminate/contracts": "^11.0|^12.0", + "php": "^8.2|^8.3|^8.4", + "spatie/laravel-package-tools": "^1.16", + "web-auth/webauthn-lib": "^5.0" + }, + "require-dev": { + "larastan/larastan": "^3.4", + "laravel/pint": "^1.14", + "livewire/livewire": "^3.5", + "nunomaduro/collision": "^8.1.1", + "orchestra/testbench": "^10.0", + "pestphp/pest": "^3.0", + "pestphp/pest-plugin-arch": "^3.0", + "pestphp/pest-plugin-laravel": "^3.0", + "phpstan/extension-installer": "^1.3", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "spatie/laravel-ray": "^1.35" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\LaravelPasskeys\\LaravelPasskeysServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\LaravelPasskeys\\": "src/", + "Spatie\\LaravelPasskeys\\Database\\Factories\\": "database/factories/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "role": "Developer" + } + ], + "description": "Use passkeys in your Laravel app", + "homepage": "https://github.com/spatie/laravel-passkeys", + "keywords": [ + "laravel", + "laravel-passkeys", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-passkeys/issues", + "source": "https://github.com/spatie/laravel-passkeys/tree/1.5.3" + }, + "funding": [ + { + "url": "https://github.com/Spatie", + "type": "github" + } + ], + "time": "2026-01-12T08:33:46+00:00" + }, { "name": "spatie/laravel-permission", "version": "6.24.0", @@ -8236,6 +8387,186 @@ ], "time": "2026-01-12T07:42:22+00:00" }, + { + "name": "spomky-labs/cbor-php", + "version": "3.2.2", + "source": { + "type": "git", + "url": "https://github.com/Spomky-Labs/cbor-php.git", + "reference": "2a5fb86aacfe1004611370ead6caa2bfc88435d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/2a5fb86aacfe1004611370ead6caa2bfc88435d0", + "reference": "2a5fb86aacfe1004611370ead6caa2bfc88435d0", + "shasum": "" + }, + "require": { + "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14", + "ext-mbstring": "*", + "php": ">=8.0" + }, + "require-dev": { + "ext-json": "*", + "roave/security-advisories": "dev-latest", + "symfony/error-handler": "^6.4|^7.1|^8.0", + "symfony/var-dumper": "^6.4|^7.1|^8.0" + }, + "suggest": { + "ext-bcmath": "GMP or BCMath extensions will drastically improve the library performance. BCMath extension needed to handle the Big Float and Decimal Fraction Tags", + "ext-gmp": "GMP or BCMath extensions will drastically improve the library performance" + }, + "type": "library", + "autoload": { + "psr-4": { + "CBOR\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/Spomky-Labs/cbor-php/contributors" + } + ], + "description": "CBOR Encoder/Decoder for PHP", + "keywords": [ + "Concise Binary Object Representation", + "RFC7049", + "cbor" + ], + "support": { + "issues": "https://github.com/Spomky-Labs/cbor-php/issues", + "source": "https://github.com/Spomky-Labs/cbor-php/tree/3.2.2" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2025-11-13T13:00:34+00:00" + }, + { + "name": "spomky-labs/pki-framework", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/Spomky-Labs/pki-framework.git", + "reference": "f0e9a548df4e3942886adc9b7830581a46334631" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/f0e9a548df4e3942886adc9b7830581a46334631", + "reference": "f0e9a548df4e3942886adc9b7830581a46334631", + "shasum": "" + }, + "require": { + "brick/math": "^0.10|^0.11|^0.12|^0.13|^0.14", + "ext-mbstring": "*", + "php": ">=8.1" + }, + "require-dev": { + "ekino/phpstan-banned-code": "^1.0|^2.0|^3.0", + "ext-gmp": "*", + "ext-openssl": "*", + "infection/infection": "^0.28|^0.29|^0.31", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpstan/extension-installer": "^1.3|^2.0", + "phpstan/phpstan": "^1.8|^2.0", + "phpstan/phpstan-deprecation-rules": "^1.0|^2.0", + "phpstan/phpstan-phpunit": "^1.1|^2.0", + "phpstan/phpstan-strict-rules": "^1.3|^2.0", + "phpunit/phpunit": "^10.1|^11.0|^12.0", + "rector/rector": "^1.0|^2.0", + "roave/security-advisories": "dev-latest", + "symfony/string": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0", + "symplify/easy-coding-standard": "^12.0" + }, + "suggest": { + "ext-bcmath": "For better performance (or GMP)", + "ext-gmp": "For better performance (or BCMath)", + "ext-openssl": "For OpenSSL based cyphering" + }, + "type": "library", + "autoload": { + "psr-4": { + "SpomkyLabs\\Pki\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Joni Eskelinen", + "email": "jonieske@gmail.com", + "role": "Original developer" + }, + { + "name": "Florent Morselli", + "email": "florent.morselli@spomky-labs.com", + "role": "Spomky-Labs PKI Framework developer" + } + ], + "description": "A PHP framework for managing Public Key Infrastructures. It comprises X.509 public key certificates, attribute certificates, certification requests and certification path validation.", + "homepage": "https://github.com/spomky-labs/pki-framework", + "keywords": [ + "DER", + "Private Key", + "ac", + "algorithm identifier", + "asn.1", + "asn1", + "attribute certificate", + "certificate", + "certification request", + "cryptography", + "csr", + "decrypt", + "ec", + "encrypt", + "pem", + "pkcs", + "public key", + "rsa", + "sign", + "signature", + "verify", + "x.509", + "x.690", + "x509", + "x690" + ], + "support": { + "issues": "https://github.com/Spomky-Labs/pki-framework/issues", + "source": "https://github.com/Spomky-Labs/pki-framework/tree/1.4.1" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2025-12-20T12:57:40+00:00" + }, { "name": "symfony/clock", "version": "v7.4.0", @@ -10598,40 +10929,31 @@ "time": "2026-01-26T15:07:59+00:00" }, { - "name": "symfony/routing", + "name": "symfony/property-access", "version": "v7.4.4", "source": { "type": "git", - "url": "https://github.com/symfony/routing.git", - "reference": "0798827fe2c79caeed41d70b680c2c3507d10147" + "url": "https://github.com/symfony/property-access.git", + "reference": "fa49bf1ca8fce1ba0e2dba4e4658554cfb9364b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/0798827fe2c79caeed41d70b680c2c3507d10147", - "reference": "0798827fe2c79caeed41d70b680c2c3507d10147", + "url": "https://api.github.com/repos/symfony/property-access/zipball/fa49bf1ca8fce1ba0e2dba4e4658554cfb9364b1", + "reference": "fa49bf1ca8fce1ba0e2dba4e4658554cfb9364b1", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/config": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/yaml": "<6.4" + "symfony/property-info": "^6.4.32|~7.3.10|^7.4.4|^8.0.4" }, "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/http-foundation": "^6.4|^7.0|^8.0", - "symfony/yaml": "^6.4|^7.0|^8.0" + "symfony/cache": "^6.4|^7.0|^8.0", + "symfony/var-exporter": "^6.4.1|^7.0.1|^8.0" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Routing\\": "" + "Symfony\\Component\\PropertyAccess\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -10651,16 +10973,21 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Maps an HTTP request to a set of configuration variables", + "description": "Provides functions to read and write from/to an object or array using a simple string notation", "homepage": "https://symfony.com", "keywords": [ - "router", - "routing", - "uri", - "url" + "access", + "array", + "extraction", + "index", + "injection", + "object", + "property", + "property-path", + "reflection" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.4.4" + "source": "https://github.com/symfony/property-access/tree/v7.4.4" }, "funding": [ { @@ -10680,35 +11007,313 @@ "type": "tidelift" } ], - "time": "2026-01-12T12:19:02+00:00" + "time": "2026-01-05T08:47:25+00:00" }, { - "name": "symfony/service-contracts", - "version": "v3.6.1", + "name": "symfony/property-info", + "version": "v7.4.5", "source": { "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" + "url": "https://github.com/symfony/property-info.git", + "reference": "1c9d326bd69602561e2ea467a16c09b5972eee21" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", + "url": "https://api.github.com/repos/symfony/property-info/zipball/1c9d326bd69602561e2ea467a16c09b5972eee21", + "reference": "1c9d326bd69602561e2ea467a16c09b5972eee21", "shasum": "" }, "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/string": "^6.4|^7.0|^8.0", + "symfony/type-info": "~7.3.10|^7.4.4|^8.0.4" }, "conflict": { - "ext-psr": "<1.1|>=2" + "phpdocumentor/reflection-docblock": "<5.2|>=6", + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/cache": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/serializer": "<6.4" + }, + "require-dev": { + "phpdocumentor/reflection-docblock": "^5.2", + "phpstan/phpdoc-parser": "^1.0|^2.0", + "symfony/cache": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4|^7.0|^8.0" }, "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyInfo\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Extracts information about PHP class' properties using metadata of popular sources", + "homepage": "https://symfony.com", + "keywords": [ + "doctrine", + "phpdoc", + "property", + "symfony", + "type", + "validator" + ], + "support": { + "source": "https://github.com/symfony/property-info/tree/v7.4.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-01-27T16:16:02+00:00" + }, + { + "name": "symfony/routing", + "version": "v7.4.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "0798827fe2c79caeed41d70b680c2c3507d10147" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/0798827fe2c79caeed41d70b680c2c3507d10147", + "reference": "0798827fe2c79caeed41d70b680c2c3507d10147", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/config": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/yaml": "<6.4" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Maps an HTTP request to a set of configuration variables", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "support": { + "source": "https://github.com/symfony/routing/tree/v7.4.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-01-12T12:19:02+00:00" + }, + { + "name": "symfony/serializer", + "version": "v7.4.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/serializer.git", + "reference": "480cd1237c98ab1219c20945b92c9d4480a44f47" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/serializer/zipball/480cd1237c98ab1219c20945b92c9d4480a44f47", + "reference": "480cd1237c98ab1219c20945b92c9d4480a44f47", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php84": "^1.30" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "<5.2|>=6", + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/dependency-injection": "<6.4", + "symfony/property-access": "<6.4", + "symfony/property-info": "<6.4", + "symfony/uid": "<6.4", + "symfony/validator": "<6.4", + "symfony/yaml": "<6.4" + }, + "require-dev": { + "phpdocumentor/reflection-docblock": "^5.2", + "phpstan/phpdoc-parser": "^1.0|^2.0", + "seld/jsonlint": "^1.10", + "symfony/cache": "^6.4|^7.0|^8.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^7.2|^8.0", + "symfony/error-handler": "^6.4|^7.0|^8.0", + "symfony/filesystem": "^6.4|^7.0|^8.0", + "symfony/form": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/mime": "^6.4|^7.0|^8.0", + "symfony/property-access": "^6.4|^7.0|^8.0", + "symfony/property-info": "^6.4|^7.0|^8.0", + "symfony/translation-contracts": "^2.5|^3", + "symfony/type-info": "^7.1.8|^8.0", + "symfony/uid": "^6.4|^7.0|^8.0", + "symfony/validator": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0", + "symfony/var-exporter": "^6.4|^7.0|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Serializer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/serializer/tree/v7.4.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-01-27T08:59:58+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.6.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" }, "branch-alias": { "dev-main": "3.6-dev" @@ -11042,6 +11647,89 @@ ], "time": "2025-07-15T13:41:35+00:00" }, + { + "name": "symfony/type-info", + "version": "v7.4.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/type-info.git", + "reference": "f83c725e72b39b2704b9d6fc85070ad6ac7a5889" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/type-info/zipball/f83c725e72b39b2704b9d6fc85070ad6ac7a5889", + "reference": "f83c725e72b39b2704b9d6fc85070ad6ac7a5889", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "phpstan/phpdoc-parser": "<1.30" + }, + "require-dev": { + "phpstan/phpdoc-parser": "^1.30|^2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\TypeInfo\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mathias Arlaud", + "email": "mathias.arlaud@gmail.com" + }, + { + "name": "Baptiste LEDUC", + "email": "baptiste.leduc@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Extracts PHP types information.", + "homepage": "https://symfony.com", + "keywords": [ + "PHPStan", + "phpdoc", + "symfony", + "type" + ], + "support": { + "source": "https://github.com/symfony/type-info/tree/v7.4.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-01-09T12:14:21+00:00" + }, { "name": "symfony/uid", "version": "v7.4.4", @@ -11565,6 +12253,163 @@ ], "time": "2024-11-21T01:49:47+00:00" }, + { + "name": "web-auth/cose-lib", + "version": "4.5.0", + "source": { + "type": "git", + "url": "https://github.com/web-auth/cose-lib.git", + "reference": "5adac6fe126994a3ee17ed9950efb4947ab132a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/5adac6fe126994a3ee17ed9950efb4947ab132a9", + "reference": "5adac6fe126994a3ee17ed9950efb4947ab132a9", + "shasum": "" + }, + "require": { + "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14", + "ext-json": "*", + "ext-openssl": "*", + "php": ">=8.1", + "spomky-labs/pki-framework": "^1.0" + }, + "require-dev": { + "spomky-labs/cbor-php": "^3.2.2" + }, + "suggest": { + "ext-bcmath": "For better performance, please install either GMP (recommended) or BCMath extension", + "ext-gmp": "For better performance, please install either GMP (recommended) or BCMath extension", + "spomky-labs/cbor-php": "For COSE Signature support" + }, + "type": "library", + "autoload": { + "psr-4": { + "Cose\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-auth/cose/contributors" + } + ], + "description": "CBOR Object Signing and Encryption (COSE) For PHP", + "homepage": "https://github.com/web-auth", + "keywords": [ + "COSE", + "RFC8152" + ], + "support": { + "issues": "https://github.com/web-auth/cose-lib/issues", + "source": "https://github.com/web-auth/cose-lib/tree/4.5.0" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2026-01-03T14:43:18+00:00" + }, + { + "name": "web-auth/webauthn-lib", + "version": "5.2.3", + "source": { + "type": "git", + "url": "https://github.com/web-auth/webauthn-lib.git", + "reference": "8782f575032fedc36e2eb27c39c736054e2b6867" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/web-auth/webauthn-lib/zipball/8782f575032fedc36e2eb27c39c736054e2b6867", + "reference": "8782f575032fedc36e2eb27c39c736054e2b6867", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-openssl": "*", + "paragonie/constant_time_encoding": "^2.6|^3.0", + "php": ">=8.2", + "phpdocumentor/reflection-docblock": "^5.3", + "psr/clock": "^1.0", + "psr/event-dispatcher": "^1.0", + "psr/log": "^1.0|^2.0|^3.0", + "spomky-labs/cbor-php": "^3.0", + "spomky-labs/pki-framework": "^1.0", + "symfony/clock": "^6.4|^7.0", + "symfony/deprecation-contracts": "^3.2", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", + "web-auth/cose-lib": "^4.2.3" + }, + "suggest": { + "psr/log-implementation": "Recommended to receive logs from the library", + "symfony/event-dispatcher": "Recommended to use dispatched events", + "web-token/jwt-library": "Mandatory for fetching Metadata Statement from distant sources" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/web-auth/webauthn-framework", + "name": "web-auth/webauthn-framework" + } + }, + "autoload": { + "psr-4": { + "Webauthn\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-auth/webauthn-library/contributors" + } + ], + "description": "FIDO2/Webauthn Support For PHP", + "homepage": "https://github.com/web-auth", + "keywords": [ + "FIDO2", + "fido", + "webauthn" + ], + "support": { + "source": "https://github.com/web-auth/webauthn-lib/tree/5.2.3" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2025-12-20T10:54:02+00:00" + }, { "name": "webmozart/assert", "version": "1.11.0", @@ -15457,5 +16302,5 @@ "platform-overrides": { "php": "8.2" }, - "plugin-api-version": "2.9.0" + "plugin-api-version": "2.6.0" } diff --git a/database/migrations/2026_02_07_103629_create_passkeys_table.php b/database/migrations/2026_02_07_103629_create_passkeys_table.php new file mode 100644 index 0000000000..9d1924aac3 --- /dev/null +++ b/database/migrations/2026_02_07_103629_create_passkeys_table.php @@ -0,0 +1,32 @@ +getTable(); + + Schema::create('passkeys', function (Blueprint $table) use ($authenticatableTableName,$authenticatableClass) { + $table->id(); + + $table + ->unsignedInteger('authenticatable_id') + ->constrained(table: $authenticatableTableName, indexName: 'passkeys_authenticatable_fk') + ->cascadeOnDelete(); + + $table->text('name'); + $table->text('credential_id'); + $table->json('data'); + + $table->timestamp('last_used_at')->nullable(); + $table->timestamps(); + }); + } +}; diff --git a/public/css/marcelweidum/filament-passkeys/filament-passkeys-styles.css b/public/css/marcelweidum/filament-passkeys/filament-passkeys-styles.css new file mode 100644 index 0000000000..8d30ec486d --- /dev/null +++ b/public/css/marcelweidum/filament-passkeys/filament-passkeys-styles.css @@ -0,0 +1,2 @@ +/*! tailwindcss v4.1.11 | MIT License | https://tailwindcss.com */ +@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-font-weight:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-500:oklch(63.7% .237 25.331);--color-gray-400:oklch(70.7% .022 261.325);--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-bold:700;--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.static{position:static}.mt-0{margin-top:calc(var(--spacing)*0)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-4{margin-top:calc(var(--spacing)*4)}.mt-6{margin-top:calc(var(--spacing)*6)}.mr-2{margin-right:calc(var(--spacing)*2)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.ml-auto{margin-left:auto}.contents{display:contents}.flex{display:flex}.inline{display:inline}.w-full{width:100%}.flex-col{flex-direction:column}.items-center{align-items:center}.items-start{align-items:flex-start}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-x-2>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing)*2)*var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-x-reverse)))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-font-weight{syntax:"*";inherits:false} \ No newline at end of file diff --git a/public/js/marcelweidum/filament-passkeys/filament-passkeys-scripts.js b/public/js/marcelweidum/filament-passkeys/filament-passkeys-scripts.js new file mode 100644 index 0000000000..99391ac10f --- /dev/null +++ b/public/js/marcelweidum/filament-passkeys/filament-passkeys-scripts.js @@ -0,0 +1,2 @@ +function l(e){let t=new Uint8Array(e),r="";for(let n of t)r+=String.fromCharCode(n);return btoa(r).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function h(e){let t=e.replace(/-/g,"+").replace(/_/g,"/"),r=(4-t.length%4)%4,i=t.padEnd(t.length+r,"="),n=atob(i),c=new ArrayBuffer(n.length),f=new Uint8Array(c);for(let a=0;ae};function w(e){let{id:t}=e;return{...e,id:h(t),transports:e.transports}}function R(e){return e==="localhost"||/^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/i.test(e)}var o=class extends Error{constructor({message:t,code:r,cause:i,name:n}){super(t,{cause:i}),Object.defineProperty(this,"code",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.name=n??i.name,this.code=r}};function _({error:e,options:t}){let{publicKey:r}=t;if(!r)throw Error("options was missing required publicKey property");if(e.name==="AbortError"){if(t.signal instanceof AbortSignal)return new o({message:"Registration ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:e})}else if(e.name==="ConstraintError"){if(r.authenticatorSelection?.requireResidentKey===!0)return new o({message:"Discoverable credentials were required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT",cause:e});if(t.mediation==="conditional"&&r.authenticatorSelection?.userVerification==="required")return new o({message:"User verification was required during automatic registration but it could not be performed",code:"ERROR_AUTO_REGISTER_USER_VERIFICATION_FAILURE",cause:e});if(r.authenticatorSelection?.userVerification==="required")return new o({message:"User verification was required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT",cause:e})}else{if(e.name==="InvalidStateError")return new o({message:"The authenticator was previously registered",code:"ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED",cause:e});if(e.name==="NotAllowedError")return new o({message:e.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:e});if(e.name==="NotSupportedError")return r.pubKeyCredParams.filter(n=>n.type==="public-key").length===0?new o({message:'No entry in pubKeyCredParams was of type "public-key"',code:"ERROR_MALFORMED_PUBKEYCREDPARAMS",cause:e}):new o({message:"No available authenticator supported any of the specified pubKeyCredParams algorithms",code:"ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG",cause:e});if(e.name==="SecurityError"){let i=globalThis.location.hostname;if(R(i)){if(r.rp.id!==i)return new o({message:`The RP ID "${r.rp.id}" is invalid for this domain`,code:"ERROR_INVALID_RP_ID",cause:e})}else return new o({message:`${globalThis.location.hostname} is an invalid domain`,code:"ERROR_INVALID_DOMAIN",cause:e})}else if(e.name==="TypeError"){if(r.user.id.byteLength<1||r.user.id.byteLength>64)return new o({message:"User ID was not between 1 and 64 characters",code:"ERROR_INVALID_USER_ID_LENGTH",cause:e})}else if(e.name==="UnknownError")return new o({message:"The authenticator was unable to process the specified options, or could not create a new credential",code:"ERROR_AUTHENTICATOR_GENERAL_ERROR",cause:e})}return e}var S=class{constructor(){Object.defineProperty(this,"controller",{enumerable:!0,configurable:!0,writable:!0,value:void 0})}createNewAbortSignal(){if(this.controller){let r=new Error("Cancelling existing WebAuthn API call for new one");r.name="AbortError",this.controller.abort(r)}let t=new AbortController;return this.controller=t,t.signal}cancelCeremony(){if(this.controller){let t=new Error("Manually cancelling existing WebAuthn API call");t.name="AbortError",this.controller.abort(t),this.controller=void 0}}},A=new S;var x=["cross-platform","platform"];function E(e){if(e&&!(x.indexOf(e)<0))return e}async function I(e){!e.optionsJSON&&e.challenge&&(console.warn("startRegistration() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information."),e={optionsJSON:e});let{optionsJSON:t,useAutoRegister:r=!1}=e;if(!p())throw new Error("WebAuthn is not supported in this browser");let i={...t,challenge:h(t.challenge),user:{...t.user,id:h(t.user.id)},excludeCredentials:t.excludeCredentials?.map(w)},n={};r&&(n.mediation="conditional"),n.publicKey=i,n.signal=A.createNewAbortSignal();let c;try{c=await navigator.credentials.create(n)}catch(u){throw _({error:u,options:n})}if(!c)throw new Error("Registration was not completed");let{id:f,rawId:a,response:s,type:y}=c,d;typeof s.getTransports=="function"&&(d=s.getTransports());let g;if(typeof s.getPublicKeyAlgorithm=="function")try{g=s.getPublicKeyAlgorithm()}catch(u){O("getPublicKeyAlgorithm()",u)}let m;if(typeof s.getPublicKey=="function")try{let u=s.getPublicKey();u!==null&&(m=l(u))}catch(u){O("getPublicKey()",u)}let b;if(typeof s.getAuthenticatorData=="function")try{b=l(s.getAuthenticatorData())}catch(u){O("getAuthenticatorData()",u)}return{id:f,rawId:l(a),response:{attestationObject:l(s.attestationObject),clientDataJSON:l(s.clientDataJSON),transports:d,publicKeyAlgorithm:g,publicKey:m,authenticatorData:b},type:y,clientExtensionResults:c.getClientExtensionResults(),authenticatorAttachment:E(c.authenticatorAttachment)}}function O(e,t){console.warn(`The browser extension that intercepted this WebAuthn API call incorrectly implemented ${e}. You should report this error to them. +`,t)}function P(){if(!p())return T.stubThis(new Promise(t=>t(!1)));let e=globalThis.PublicKeyCredential;return e?.isConditionalMediationAvailable===void 0?T.stubThis(new Promise(t=>t(!1))):T.stubThis(e.isConditionalMediationAvailable())}var T={stubThis:e=>e};function C({error:e,options:t}){let{publicKey:r}=t;if(!r)throw Error("options was missing required publicKey property");if(e.name==="AbortError"){if(t.signal instanceof AbortSignal)return new o({message:"Authentication ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:e})}else{if(e.name==="NotAllowedError")return new o({message:e.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:e});if(e.name==="SecurityError"){let i=globalThis.location.hostname;if(R(i)){if(r.rpId!==i)return new o({message:`The RP ID "${r.rpId}" is invalid for this domain`,code:"ERROR_INVALID_RP_ID",cause:e})}else return new o({message:`${globalThis.location.hostname} is an invalid domain`,code:"ERROR_INVALID_DOMAIN",cause:e})}else if(e.name==="UnknownError")return new o({message:"The authenticator was unable to process the specified options, or could not create a new assertion signature",code:"ERROR_AUTHENTICATOR_GENERAL_ERROR",cause:e})}return e}async function N(e){!e.optionsJSON&&e.challenge&&(console.warn("startAuthentication() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information."),e={optionsJSON:e});let{optionsJSON:t,useBrowserAutofill:r=!1,verifyBrowserAutofillInput:i=!0}=e;if(!p())throw new Error("WebAuthn is not supported in this browser");let n;t.allowCredentials?.length!==0&&(n=t.allowCredentials?.map(w));let c={...t,challenge:h(t.challenge),allowCredentials:n},f={};if(r){if(!await P())throw Error("Browser does not support WebAuthn autofill");if(document.querySelectorAll("input[autocomplete$='webauthn']").length<1&&i)throw Error('No with "webauthn" as the only or last value in its `autocomplete` attribute was detected');f.mediation="conditional",c.allowCredentials=[]}f.publicKey=c,f.signal=A.createNewAbortSignal();let a;try{a=await navigator.credentials.get(f)}catch(b){throw C({error:b,options:f})}if(!a)throw new Error("Authentication was not completed");let{id:s,rawId:y,response:d,type:g}=a,m;return d.userHandle&&(m=l(d.userHandle)),{id:s,rawId:l(y),response:{authenticatorData:l(d.authenticatorData),clientDataJSON:l(d.clientDataJSON),signature:l(d.signature),userHandle:m},type:g,clientExtensionResults:a.getClientExtensionResults(),authenticatorAttachment:E(a.authenticatorAttachment)}}window.browserSupportsWebAuthn=p;window.startAuthentication=N;window.startRegistration=I; diff --git a/resources/views/vendor/passkeys/components/authenticate.blade.php b/resources/views/vendor/passkeys/components/authenticate.blade.php new file mode 100644 index 0000000000..abbeb13480 --- /dev/null +++ b/resources/views/vendor/passkeys/components/authenticate.blade.php @@ -0,0 +1,23 @@ +
+ @include('passkeys::components.partials.authenticateScript') + +
+ @csrf +
+ + @if($message = session()->get('authenticatePasskey::message')) +
+ {{ $message }} +
+ @endif + +
+ @if ($slot->isEmpty()) +
+ {{ __('passkeys::passkeys.authenticate_using_passkey') }} +
+ @else + {{ $slot }} + @endif +
+
diff --git a/resources/views/vendor/passkeys/components/partials/authenticateScript.blade.php b/resources/views/vendor/passkeys/components/partials/authenticateScript.blade.php new file mode 100644 index 0000000000..c0098f0a24 --- /dev/null +++ b/resources/views/vendor/passkeys/components/partials/authenticateScript.blade.php @@ -0,0 +1,18 @@ + diff --git a/resources/views/vendor/passkeys/livewire/partials/createScript.blade.php b/resources/views/vendor/passkeys/livewire/partials/createScript.blade.php new file mode 100644 index 0000000000..4d5a17bb9e --- /dev/null +++ b/resources/views/vendor/passkeys/livewire/partials/createScript.blade.php @@ -0,0 +1,11 @@ +@script + +@endscript diff --git a/resources/views/vendor/passkeys/livewire/passkeys.blade.php b/resources/views/vendor/passkeys/livewire/passkeys.blade.php new file mode 100644 index 0000000000..2450b0240b --- /dev/null +++ b/resources/views/vendor/passkeys/livewire/passkeys.blade.php @@ -0,0 +1,42 @@ +
+

{{ __('passkeys::passkeys.passkeys') }}

+
+
+
+ + + @error('name') + {{ $message }} + @enderror +
+ + +
+
+ +
+
    + @foreach($passkeys as $passkey) +
  • +
    + {{ $passkey->name }} +
    +
    + {{ __('passkeys::passkeys.last_used') }}: {{ $passkey->last_used_at?->diffForHumans() ?? __('passkeys::passkeys.not_used_yet') }} +
    + + +
    + +
    +
  • + @endforeach +
+
+
+ +@include('passkeys::livewire.partials.createScript') diff --git a/routes/auth.php b/routes/auth.php index 0406b11bde..16ed0934f5 100644 --- a/routes/auth.php +++ b/routes/auth.php @@ -9,3 +9,4 @@ Route::get('/redirect/{driver}', [OAuthController::class, 'redirect'])->name('auth.oauth.redirect'); Route::get('/callback/{driver}', [OAuthController::class, 'callback'])->name('auth.oauth.callback')->withoutMiddleware('guest'); }); +Route::passkeys(); From e60784bc8d1b480dfe3b788d4dbf7738f648c856 Mon Sep 17 00:00:00 2001 From: JoanFo1456 Date: Sat, 7 Feb 2026 12:39:59 +0100 Subject: [PATCH 02/18] Phpstan and pint --- app/Models/User.php | 6 +++--- .../migrations/2026_02_07_103629_create_passkeys_table.php | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/Models/User.php b/app/Models/User.php index a0727f831f..7ce38f69a4 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -96,17 +96,17 @@ * @method static Builder|User whereUsername($value) * @method static Builder|User whereUuid($value) */ -class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, FilamentUser, HasAppAuthentication, HasAppAuthenticationRecovery, HasAvatar, HasEmailAuthentication, HasName, HasTenants, Validatable, HasPasskeys +class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, FilamentUser, HasAppAuthentication, HasAppAuthenticationRecovery, HasAvatar, HasEmailAuthentication, HasName, HasPasskeys, HasTenants, Validatable { use Authenticatable; use Authorizable { can as protected canned; } use CanResetPassword; use HasAccessTokens; use HasFactory; + use HasFactory, InteractsWithPasskeys, Notifiable; use HasRoles; use HasValidation { getRules as getValidationRules; } use Notifiable; - use HasFactory, Notifiable, InteractsWithPasskeys; public const USER_LEVEL_USER = 0; @@ -513,7 +513,7 @@ public function getPasskeyDisplayName(): string return $this->username ?? $this->email; } - public function getPasskeyUserId(): string + public function getPasskeyUserId(): int { return $this->id; } diff --git a/database/migrations/2026_02_07_103629_create_passkeys_table.php b/database/migrations/2026_02_07_103629_create_passkeys_table.php index 9d1924aac3..652244b2ea 100644 --- a/database/migrations/2026_02_07_103629_create_passkeys_table.php +++ b/database/migrations/2026_02_07_103629_create_passkeys_table.php @@ -11,9 +11,9 @@ public function up() { $authenticatableClass = Config::getAuthenticatableModel(); - $authenticatableTableName = (new $authenticatableClass)->getTable(); + $authenticatableTableName = (new $authenticatableClass())->getTable(); - Schema::create('passkeys', function (Blueprint $table) use ($authenticatableTableName,$authenticatableClass) { + Schema::create('passkeys', function (Blueprint $table) use ($authenticatableTableName) { $table->id(); $table From d051f4c224f1d38a1159993ec18477662fbcac10 Mon Sep 17 00:00:00 2001 From: JoanFo1456 Date: Sat, 7 Feb 2026 12:56:14 +0100 Subject: [PATCH 03/18] Duplicated code on user --- app/Models/User.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Models/User.php b/app/Models/User.php index 7ce38f69a4..e9944994e8 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -103,7 +103,7 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac use CanResetPassword; use HasAccessTokens; use HasFactory; - use HasFactory, InteractsWithPasskeys, Notifiable; + use InteractsWithPasskeys; use HasRoles; use HasValidation { getRules as getValidationRules; } use Notifiable; From 13961c8042338e19bad905107db8f6cf89859d04 Mon Sep 17 00:00:00 2001 From: JoanFo1456 Date: Sat, 7 Feb 2026 12:59:02 +0100 Subject: [PATCH 04/18] ... --- app/Models/User.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Models/User.php b/app/Models/User.php index e9944994e8..c8e3ce90ec 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -103,9 +103,9 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac use CanResetPassword; use HasAccessTokens; use HasFactory; - use InteractsWithPasskeys; use HasRoles; use HasValidation { getRules as getValidationRules; } + use InteractsWithPasskeys; use Notifiable; public const USER_LEVEL_USER = 0; From 02e56448e656a19c7dab44edc93ff3960944f684 Mon Sep 17 00:00:00 2001 From: JoanFo1456 Date: Sat, 7 Feb 2026 16:14:54 +0100 Subject: [PATCH 05/18] Well, merged the package to codebase --- app/Filament/Pages/Auth/EditProfile.php | 12 + app/Passkeys/Livewire/Passkeys.php | 61 + app/Passkeys/PasskeysPlugin.php | 52 + .../Filament/FilamentServiceProvider.php | 4 +- app/Providers/Filament/PanelProvider.php | 2 +- composer.json | 1 - composer.lock | 1264 +++-------------- config/passkeys.php | 41 + lang/en/passkeys.php | 20 + package.json | 1 + resources/js/app.js | 3 +- resources/js/passkeys/index.js | 9 + .../components/authenticate.blade.php | 17 + .../passkeys/livewire/passkeys-tab.blade.php | 1 + .../passkeys/livewire/passkeys.blade.php | 51 + resources/views/passkeys/login.blade.php | 5 + resources/views/passkeys/profile.blade.php | 11 + .../components/authenticate.blade.php | 23 - .../partials/authenticateScript.blade.php | 18 - .../livewire/partials/createScript.blade.php | 11 - .../passkeys/livewire/passkeys.blade.php | 42 - yarn.lock | 5 + 22 files changed, 507 insertions(+), 1147 deletions(-) create mode 100644 app/Passkeys/Livewire/Passkeys.php create mode 100644 app/Passkeys/PasskeysPlugin.php create mode 100644 config/passkeys.php create mode 100644 lang/en/passkeys.php create mode 100644 resources/js/passkeys/index.js create mode 100644 resources/views/passkeys/components/authenticate.blade.php create mode 100644 resources/views/passkeys/livewire/passkeys-tab.blade.php create mode 100644 resources/views/passkeys/livewire/passkeys.blade.php create mode 100644 resources/views/passkeys/login.blade.php create mode 100644 resources/views/passkeys/profile.blade.php delete mode 100644 resources/views/vendor/passkeys/components/authenticate.blade.php delete mode 100644 resources/views/vendor/passkeys/components/partials/authenticateScript.blade.php delete mode 100644 resources/views/vendor/passkeys/livewire/partials/createScript.blade.php delete mode 100644 resources/views/vendor/passkeys/livewire/passkeys.blade.php diff --git a/app/Filament/Pages/Auth/EditProfile.php b/app/Filament/Pages/Auth/EditProfile.php index 0ab26c4f61..1b4fa904c8 100644 --- a/app/Filament/Pages/Auth/EditProfile.php +++ b/app/Filament/Pages/Auth/EditProfile.php @@ -234,6 +234,18 @@ protected function getDefaultTabs(): array ->map(fn (MultiFactorAuthenticationProvider $multiFactorAuthenticationProvider) => Group::make($multiFactorAuthenticationProvider->getManagementSchemaComponents()) ->statePath($multiFactorAuthenticationProvider->getId())) ->all()), + Tab::make('passkeys') + ->label(trans('passkeys.passkeys')) + ->icon(TablerIcon::Fingerprint) + ->schema([ + Section::make(trans('passkeys.passkeys')) + ->description(trans('passkeys.description')) + ->schema([ + Group::make([ + view('passkeys.livewire.passkeys-tab'), + ]), + ]), + ]), Tab::make('api_keys') ->label(trans('profile.tabs.api_keys')) ->icon(TablerIcon::Key) diff --git a/app/Passkeys/Livewire/Passkeys.php b/app/Passkeys/Livewire/Passkeys.php new file mode 100644 index 0000000000..8d64c8b1d6 --- /dev/null +++ b/app/Passkeys/Livewire/Passkeys.php @@ -0,0 +1,61 @@ +mountAction('deleteAction', ['passkey' => $passkeyId]); + } + + public function deleteAction(): Action + { + return Action::make('deleteAction') + ->label(__('passkeys.delete')) + ->color('danger') + ->requiresConfirmation() + ->action(fn (array $arguments) => $this->deletePasskey($arguments['passkey'])); + } + + public function deletePasskey(int $passkeyId): void + { + parent::deletePasskey($passkeyId); + + Notification::make() + ->title(__('passkeys.deleted_notification_title')) + ->success() + ->send(); + } + + public function storePasskey(string $passkey): void + { + parent::storePasskey($passkey); + + Notification::make() + ->title(__('passkeys.created_notification_title')) + ->success() + ->send(); + } + + public function render(): View + { + return view('passkeys.livewire.passkeys', data: [ + 'passkeys' => $this->currentUser()->passkeys()->get(), + ]); + } +} diff --git a/app/Passkeys/PasskeysPlugin.php b/app/Passkeys/PasskeysPlugin.php new file mode 100644 index 0000000000..68f1f04981 --- /dev/null +++ b/app/Passkeys/PasskeysPlugin.php @@ -0,0 +1,52 @@ +getId()); + + return $plugin; + } + + public function getId(): string + { + return 'filament-passkeys'; + } + + public function register(Panel $panel): void + { + // + } + + public function boot(Panel $panel): void + { + FilamentView::registerRenderHook( + PanelsRenderHook::AUTH_LOGIN_FORM_AFTER, + fn (): View => view('passkeys.login'), + ); + + Livewire::component('filament-passkeys', Passkeys::class); + } +} diff --git a/app/Providers/Filament/FilamentServiceProvider.php b/app/Providers/Filament/FilamentServiceProvider.php index 581a3f04eb..a9895110d3 100644 --- a/app/Providers/Filament/FilamentServiceProvider.php +++ b/app/Providers/Filament/FilamentServiceProvider.php @@ -33,7 +33,7 @@ use Illuminate\Support\ServiceProvider; use Livewire\Component; use Livewire\Livewire; -use MarcelWeidum\Passkeys\Livewire\Passkeys as FilamentPasskeys; +use App\Passkeys\Livewire\Passkeys; use function Livewire\on; use function Livewire\store; @@ -258,7 +258,7 @@ public function boot(): void SchemaIconAlias::COMPONENTS_WIZARD_COMPLETED_STEP => TablerIcon::Check, ]); - Livewire::component('filament-passkeys', FilamentPasskeys::class); + Livewire::component('filament-passkeys', Passkeys::class); } public function register(): void {} diff --git a/app/Providers/Filament/PanelProvider.php b/app/Providers/Filament/PanelProvider.php index e82dbc5e31..61607bd6db 100644 --- a/app/Providers/Filament/PanelProvider.php +++ b/app/Providers/Filament/PanelProvider.php @@ -22,7 +22,7 @@ use Illuminate\Session\Middleware\AuthenticateSession; use Illuminate\Session\Middleware\StartSession; use Illuminate\View\Middleware\ShareErrorsFromSession; -use MarcelWeidum\Passkeys\PasskeysPlugin; +use App\Passkeys\PasskeysPlugin; abstract class PanelProvider extends BasePanelProvider { diff --git a/composer.json b/composer.json index d78a082a4e..b29ac9b5f8 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,6 @@ "lcobucci/jwt": "^5.6", "league/flysystem-aws-s3-v3": "^3.31", "league/flysystem-memory": "^3.31", - "marcelweidum/filament-passkeys": "^2.0", "phiki/phiki": "^2.0", "phpseclib/phpseclib": "~3.0.18", "predis/predis": "^2.3", diff --git a/composer.lock b/composer.lock index e99516d6dc..b0cb04d2e3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "65473c308a5b557676d504355e4d2d5d", + "content-hash": "15f89930db77693b2d692dbadf22fb9f", "packages": [ { "name": "anourvalar/eloquent-serialize", @@ -128,16 +128,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.369.24", + "version": "3.369.29", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "17f404a47879c1fb47175ac2b61881ab0dc2dc5c" + "reference": "068195b2980cf5cf4ade2515850d461186db3310" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/17f404a47879c1fb47175ac2b61881ab0dc2dc5c", - "reference": "17f404a47879c1fb47175ac2b61881ab0dc2dc5c", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/068195b2980cf5cf4ade2515850d461186db3310", + "reference": "068195b2980cf5cf4ade2515850d461186db3310", "shasum": "" }, "require": { @@ -219,9 +219,9 @@ "support": { "forum": "https://github.com/aws/aws-sdk-php/discussions", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.369.24" + "source": "https://github.com/aws/aws-sdk-php/tree/3.369.29" }, - "time": "2026-01-30T19:14:32+00:00" + "time": "2026-02-06T19:08:50+00:00" }, { "name": "blade-ui-kit/blade-heroicons", @@ -375,16 +375,16 @@ }, { "name": "brick/math", - "version": "0.14.2", + "version": "0.14.7", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "55c950aa71a2cabc1d8f2bec1f8a7020bd244aa2" + "reference": "07ff363b16ef8aca9692bba3be9e73fe63f34e50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/55c950aa71a2cabc1d8f2bec1f8a7020bd244aa2", - "reference": "55c950aa71a2cabc1d8f2bec1f8a7020bd244aa2", + "url": "https://api.github.com/repos/brick/math/zipball/07ff363b16ef8aca9692bba3be9e73fe63f34e50", + "reference": "07ff363b16ef8aca9692bba3be9e73fe63f34e50", "shasum": "" }, "require": { @@ -423,7 +423,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.14.2" + "source": "https://github.com/brick/math/tree/0.14.7" }, "funding": [ { @@ -431,7 +431,7 @@ "type": "github" } ], - "time": "2026-01-30T14:03:11+00:00" + "time": "2026-02-07T10:57:35+00:00" }, { "name": "calebporzio/sushi", @@ -822,16 +822,16 @@ }, { "name": "dedoc/scramble", - "version": "v0.13.11", + "version": "v0.13.12", "source": { "type": "git", "url": "https://github.com/dedoc/scramble.git", - "reference": "871dbac4888e3d22d7f04c2c7b3d7bb810e87005" + "reference": "1788ab68ae51ae2fce34e16add1387ee1ac5d88b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dedoc/scramble/zipball/871dbac4888e3d22d7f04c2c7b3d7bb810e87005", - "reference": "871dbac4888e3d22d7f04c2c7b3d7bb810e87005", + "url": "https://api.github.com/repos/dedoc/scramble/zipball/1788ab68ae51ae2fce34e16add1387ee1ac5d88b", + "reference": "1788ab68ae51ae2fce34e16add1387ee1ac5d88b", "shasum": "" }, "require": { @@ -890,7 +890,7 @@ ], "support": { "issues": "https://github.com/dedoc/scramble/issues", - "source": "https://github.com/dedoc/scramble/tree/v0.13.11" + "source": "https://github.com/dedoc/scramble/tree/v0.13.12" }, "funding": [ { @@ -898,7 +898,7 @@ "type": "github" } ], - "time": "2026-01-28T14:02:15+00:00" + "time": "2026-02-05T07:47:09+00:00" }, { "name": "dflydev/dot-access-data", @@ -977,29 +977,29 @@ }, { "name": "doctrine/deprecations", - "version": "1.1.5", + "version": "1.1.6", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" + "reference": "d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", - "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca", + "reference": "d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "conflict": { - "phpunit/phpunit": "<=7.5 || >=13" + "phpunit/phpunit": "<=7.5 || >=14" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^12 || ^13", - "phpstan/phpstan": "1.4.10 || 2.1.11", + "doctrine/coding-standard": "^9 || ^12 || ^14", + "phpstan/phpstan": "1.4.10 || 2.1.30", "phpstan/phpstan-phpunit": "^1.0 || ^2", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12.4 || ^13.0", "psr/log": "^1 || ^2 || ^3" }, "suggest": { @@ -1019,9 +1019,9 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.5" + "source": "https://github.com/doctrine/deprecations/tree/1.1.6" }, - "time": "2025-04-07T20:06:18+00:00" + "time": "2026-02-07T07:09:04+00:00" }, { "name": "doctrine/inflector", @@ -1323,16 +1323,16 @@ }, { "name": "filament/actions", - "version": "v4.6.3", + "version": "v4.7.0", "source": { "type": "git", "url": "https://github.com/filamentphp/actions.git", - "reference": "4a3896cd956fcb7d132a51453bc8110d47023433" + "reference": "fff2f4db8fa8c4f9142eda762f2db099bd65a44f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/actions/zipball/4a3896cd956fcb7d132a51453bc8110d47023433", - "reference": "4a3896cd956fcb7d132a51453bc8110d47023433", + "url": "https://api.github.com/repos/filamentphp/actions/zipball/fff2f4db8fa8c4f9142eda762f2db099bd65a44f", + "reference": "fff2f4db8fa8c4f9142eda762f2db099bd65a44f", "shasum": "" }, "require": { @@ -1368,20 +1368,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2026-01-30T12:51:27+00:00" + "time": "2026-02-04T16:09:51+00:00" }, { "name": "filament/filament", - "version": "v4.6.3", + "version": "v4.7.0", "source": { "type": "git", "url": "https://github.com/filamentphp/panels.git", - "reference": "24aababf2777f82014887199f9cd029b5e6251d5" + "reference": "b9dcd1dc287d6affea1f678fb9128227486eb4a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/panels/zipball/24aababf2777f82014887199f9cd029b5e6251d5", - "reference": "24aababf2777f82014887199f9cd029b5e6251d5", + "url": "https://api.github.com/repos/filamentphp/panels/zipball/b9dcd1dc287d6affea1f678fb9128227486eb4a7", + "reference": "b9dcd1dc287d6affea1f678fb9128227486eb4a7", "shasum": "" }, "require": { @@ -1425,20 +1425,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2026-01-30T12:47:54+00:00" + "time": "2026-02-04T16:15:24+00:00" }, { "name": "filament/forms", - "version": "v4.6.3", + "version": "v4.7.0", "source": { "type": "git", "url": "https://github.com/filamentphp/forms.git", - "reference": "137090f3d2b1dc6e4234ad2325c9acb34276d5b5" + "reference": "3839d9c939a5d8583f2e059fc549cdfd55b86d51" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/forms/zipball/137090f3d2b1dc6e4234ad2325c9acb34276d5b5", - "reference": "137090f3d2b1dc6e4234ad2325c9acb34276d5b5", + "url": "https://api.github.com/repos/filamentphp/forms/zipball/3839d9c939a5d8583f2e059fc549cdfd55b86d51", + "reference": "3839d9c939a5d8583f2e059fc549cdfd55b86d51", "shasum": "" }, "require": { @@ -1475,11 +1475,11 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2026-01-30T12:47:37+00:00" + "time": "2026-02-04T16:14:02+00:00" }, { "name": "filament/infolists", - "version": "v4.6.3", + "version": "v4.7.0", "source": { "type": "git", "url": "https://github.com/filamentphp/infolists.git", @@ -1524,16 +1524,16 @@ }, { "name": "filament/notifications", - "version": "v4.6.3", + "version": "v4.7.0", "source": { "type": "git", "url": "https://github.com/filamentphp/notifications.git", - "reference": "af01c113555d26ba73e75331ca19772b92a34dcf" + "reference": "53b004187380aebbf176cb9fc5cb78c5717a9285" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/notifications/zipball/af01c113555d26ba73e75331ca19772b92a34dcf", - "reference": "af01c113555d26ba73e75331ca19772b92a34dcf", + "url": "https://api.github.com/repos/filamentphp/notifications/zipball/53b004187380aebbf176cb9fc5cb78c5717a9285", + "reference": "53b004187380aebbf176cb9fc5cb78c5717a9285", "shasum": "" }, "require": { @@ -1567,20 +1567,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2026-01-23T10:54:41+00:00" + "time": "2026-02-04T16:10:32+00:00" }, { "name": "filament/query-builder", - "version": "v4.6.3", + "version": "v4.7.0", "source": { "type": "git", "url": "https://github.com/filamentphp/query-builder.git", - "reference": "132ad55f85eaa427bb786b4a8184ac6e24a7e676" + "reference": "49c374bf3a3d9dab96afd8bf42420fbc571e8e26" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/query-builder/zipball/132ad55f85eaa427bb786b4a8184ac6e24a7e676", - "reference": "132ad55f85eaa427bb786b4a8184ac6e24a7e676", + "url": "https://api.github.com/repos/filamentphp/query-builder/zipball/49c374bf3a3d9dab96afd8bf42420fbc571e8e26", + "reference": "49c374bf3a3d9dab96afd8bf42420fbc571e8e26", "shasum": "" }, "require": { @@ -1613,20 +1613,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2026-01-30T12:51:18+00:00" + "time": "2026-02-04T16:14:57+00:00" }, { "name": "filament/schemas", - "version": "v4.6.3", + "version": "v4.7.0", "source": { "type": "git", "url": "https://github.com/filamentphp/schemas.git", - "reference": "e1bdda85e9fb5d65774df153e0357eb41c7c7a3d" + "reference": "cf38af2040c585b134d43c3ca3b1c218afb27431" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/schemas/zipball/e1bdda85e9fb5d65774df153e0357eb41c7c7a3d", - "reference": "e1bdda85e9fb5d65774df153e0357eb41c7c7a3d", + "url": "https://api.github.com/repos/filamentphp/schemas/zipball/cf38af2040c585b134d43c3ca3b1c218afb27431", + "reference": "cf38af2040c585b134d43c3ca3b1c218afb27431", "shasum": "" }, "require": { @@ -1658,20 +1658,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2026-01-29T21:01:33+00:00" + "time": "2026-02-04T16:10:11+00:00" }, { "name": "filament/support", - "version": "v4.6.3", + "version": "v4.7.0", "source": { "type": "git", "url": "https://github.com/filamentphp/support.git", - "reference": "67a017956b2fe3d37425a2df0d1f8e18c30b42e2" + "reference": "bed43ce30c778ff8cfbfb69498c34da79fa473b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/support/zipball/67a017956b2fe3d37425a2df0d1f8e18c30b42e2", - "reference": "67a017956b2fe3d37425a2df0d1f8e18c30b42e2", + "url": "https://api.github.com/repos/filamentphp/support/zipball/bed43ce30c778ff8cfbfb69498c34da79fa473b2", + "reference": "bed43ce30c778ff8cfbfb69498c34da79fa473b2", "shasum": "" }, "require": { @@ -1688,7 +1688,7 @@ "spatie/invade": "^2.0", "spatie/laravel-package-tools": "^1.9", "symfony/console": "^7.0", - "symfony/html-sanitizer": "^7.0" + "symfony/html-sanitizer": "^7.0|^8.0" }, "type": "library", "extra": { @@ -1716,20 +1716,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2026-01-29T21:00:17+00:00" + "time": "2026-02-04T16:09:55+00:00" }, { "name": "filament/tables", - "version": "v4.6.3", + "version": "v4.7.0", "source": { "type": "git", "url": "https://github.com/filamentphp/tables.git", - "reference": "e3cb9c71e150a6a2b7e8601c363e7731ddfc9518" + "reference": "6c637ffe6b03ccd2f9960a83ac979b9bda9649e3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/tables/zipball/e3cb9c71e150a6a2b7e8601c363e7731ddfc9518", - "reference": "e3cb9c71e150a6a2b7e8601c363e7731ddfc9518", + "url": "https://api.github.com/repos/filamentphp/tables/zipball/6c637ffe6b03ccd2f9960a83ac979b9bda9649e3", + "reference": "6c637ffe6b03ccd2f9960a83ac979b9bda9649e3", "shasum": "" }, "require": { @@ -1762,20 +1762,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2026-01-30T12:51:42+00:00" + "time": "2026-02-04T16:14:21+00:00" }, { "name": "filament/widgets", - "version": "v4.6.3", + "version": "v4.7.0", "source": { "type": "git", "url": "https://github.com/filamentphp/widgets.git", - "reference": "d9b5a35a04048bea86563223d2505d11aea5a7e0" + "reference": "eaeeffe0ca8b8a3bdc416b03dd216a3e5333986b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/widgets/zipball/d9b5a35a04048bea86563223d2505d11aea5a7e0", - "reference": "d9b5a35a04048bea86563223d2505d11aea5a7e0", + "url": "https://api.github.com/repos/filamentphp/widgets/zipball/eaeeffe0ca8b8a3bdc416b03dd216a3e5333986b", + "reference": "eaeeffe0ca8b8a3bdc416b03dd216a3e5333986b", "shasum": "" }, "require": { @@ -1806,7 +1806,7 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2026-01-29T20:48:44+00:00" + "time": "2026-02-04T16:10:11+00:00" }, { "name": "firebase/php-jwt", @@ -1944,16 +1944,16 @@ }, { "name": "gboquizosanchez/filament-log-viewer", - "version": "2.2.2", + "version": "2.2.3", "source": { "type": "git", "url": "https://github.com/gboquizosanchez/filament-log-viewer.git", - "reference": "b11e8ee8be0720c02e25095449e758b4aab52817" + "reference": "eae98cd4fda986b65d78a38ef967c4a639626c1f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/gboquizosanchez/filament-log-viewer/zipball/b11e8ee8be0720c02e25095449e758b4aab52817", - "reference": "b11e8ee8be0720c02e25095449e758b4aab52817", + "url": "https://api.github.com/repos/gboquizosanchez/filament-log-viewer/zipball/eae98cd4fda986b65d78a38ef967c4a639626c1f", + "reference": "eae98cd4fda986b65d78a38ef967c4a639626c1f", "shasum": "" }, "require": { @@ -2002,9 +2002,9 @@ ], "support": { "issues": "https://github.com/gboquizosanchez/filament-log-viewer/issues", - "source": "https://github.com/gboquizosanchez/filament-log-viewer/tree/2.2.2" + "source": "https://github.com/gboquizosanchez/filament-log-viewer/tree/2.2.3" }, - "time": "2026-01-18T01:00:25+00:00" + "time": "2026-02-03T00:08:41+00:00" }, { "name": "graham-campbell/result-type", @@ -2544,16 +2544,16 @@ }, { "name": "laravel/framework", - "version": "v12.49.0", + "version": "v12.50.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "4bde4530545111d8bdd1de6f545fa8824039fcb5" + "reference": "174ffed91d794a35a541a5eb7c3785a02a34aaba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/4bde4530545111d8bdd1de6f545fa8824039fcb5", - "reference": "4bde4530545111d8bdd1de6f545fa8824039fcb5", + "url": "https://api.github.com/repos/laravel/framework/zipball/174ffed91d794a35a541a5eb7c3785a02a34aaba", + "reference": "174ffed91d794a35a541a5eb7c3785a02a34aaba", "shasum": "" }, "require": { @@ -2762,7 +2762,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2026-01-28T03:40:49+00:00" + "time": "2026-02-04T18:34:13+00:00" }, { "name": "laravel/helpers", @@ -2823,30 +2823,30 @@ }, { "name": "laravel/prompts", - "version": "v0.3.11", + "version": "v0.3.12", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "dd2a2ed95acacbcccd32fd98dee4c946ae7a7217" + "reference": "4861ded9003b7f8a158176a0b7666f74ee761be8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/dd2a2ed95acacbcccd32fd98dee4c946ae7a7217", - "reference": "dd2a2ed95acacbcccd32fd98dee4c946ae7a7217", + "url": "https://api.github.com/repos/laravel/prompts/zipball/4861ded9003b7f8a158176a0b7666f74ee761be8", + "reference": "4861ded9003b7f8a158176a0b7666f74ee761be8", "shasum": "" }, "require": { "composer-runtime-api": "^2.2", "ext-mbstring": "*", "php": "^8.1", - "symfony/console": "^6.2|^7.0" + "symfony/console": "^6.2|^7.0|^8.0" }, "conflict": { "illuminate/console": ">=10.17.0 <10.25.0", "laravel/framework": ">=10.17.0 <10.25.0" }, "require-dev": { - "illuminate/collections": "^10.0|^11.0|^12.0", + "illuminate/collections": "^10.0|^11.0|^12.0|^13.0", "mockery/mockery": "^1.5", "pestphp/pest": "^2.3|^3.4|^4.0", "phpstan/phpstan": "^1.12.28", @@ -2876,9 +2876,9 @@ "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.3.11" + "source": "https://github.com/laravel/prompts/tree/v0.3.12" }, - "time": "2026-01-27T02:55:06+00:00" + "time": "2026-02-03T06:57:26+00:00" }, { "name": "laravel/sanctum", @@ -2945,27 +2945,27 @@ }, { "name": "laravel/serializable-closure", - "version": "v2.0.8", + "version": "v2.0.9", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "7581a4407012f5f53365e11bafc520fd7f36bc9b" + "reference": "8f631589ab07b7b52fead814965f5a800459cb3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/7581a4407012f5f53365e11bafc520fd7f36bc9b", - "reference": "7581a4407012f5f53365e11bafc520fd7f36bc9b", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/8f631589ab07b7b52fead814965f5a800459cb3e", + "reference": "8f631589ab07b7b52fead814965f5a800459cb3e", "shasum": "" }, "require": { "php": "^8.1" }, "require-dev": { - "illuminate/support": "^10.0|^11.0|^12.0", + "illuminate/support": "^10.0|^11.0|^12.0|^13.0", "nesbot/carbon": "^2.67|^3.0", "pestphp/pest": "^2.36|^3.0|^4.0", "phpstan/phpstan": "^2.0", - "symfony/var-dumper": "^6.2.0|^7.0.0" + "symfony/var-dumper": "^6.2.0|^7.0.0|^8.0.0" }, "type": "library", "extra": { @@ -3002,7 +3002,7 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2026-01-08T16:22:46+00:00" + "time": "2026-02-03T06:55:34+00:00" }, { "name": "laravel/socialite", @@ -4263,16 +4263,16 @@ }, { "name": "livewire/livewire", - "version": "v3.7.6", + "version": "v3.7.9", "source": { "type": "git", "url": "https://github.com/livewire/livewire.git", - "reference": "276ac156f6ae414990784854a2673e3d23c68b24" + "reference": "112b27e41e87e89d828a96e37b257aff2a058c7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/livewire/livewire/zipball/276ac156f6ae414990784854a2673e3d23c68b24", - "reference": "276ac156f6ae414990784854a2673e3d23c68b24", + "url": "https://api.github.com/repos/livewire/livewire/zipball/112b27e41e87e89d828a96e37b257aff2a058c7a", + "reference": "112b27e41e87e89d828a96e37b257aff2a058c7a", "shasum": "" }, "require": { @@ -4327,7 +4327,7 @@ "description": "A front-end framework for Laravel.", "support": { "issues": "https://github.com/livewire/livewire/issues", - "source": "https://github.com/livewire/livewire/tree/v3.7.6" + "source": "https://github.com/livewire/livewire/tree/v3.7.9" }, "funding": [ { @@ -4335,80 +4335,7 @@ "type": "github" } ], - "time": "2026-01-23T05:41:38+00:00" - }, - { - "name": "marcelweidum/filament-passkeys", - "version": "v2.0.2", - "source": { - "type": "git", - "url": "https://github.com/MarcelWeidum/filament-passkeys.git", - "reference": "ccb80dcda3a0bcc4aacb42043d88c528b17bc7fa" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/MarcelWeidum/filament-passkeys/zipball/ccb80dcda3a0bcc4aacb42043d88c528b17bc7fa", - "reference": "ccb80dcda3a0bcc4aacb42043d88c528b17bc7fa", - "shasum": "" - }, - "require": { - "filament/filament": "^4.0|^5.0", - "php": "^8.2", - "spatie/laravel-package-tools": "^1.15.0", - "spatie/laravel-passkeys": "^1.5.3", - "web-auth/webauthn-lib": "5.2.3" - }, - "require-dev": { - "laravel/pint": "^1.0", - "spatie/laravel-ray": "^1.26" - }, - "type": "library", - "extra": { - "laravel": { - "aliases": { - "Passkeys": "MarcelWeidum\\Passkeys\\Facades\\Passkeys" - }, - "providers": [ - "MarcelWeidum\\Passkeys\\PasskeysServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "MarcelWeidum\\Passkeys\\": "src/", - "MarcelWeidum\\Passkeys\\Database\\Factories\\": "database/factories/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "MarcelWeidum", - "role": "Developer" - } - ], - "description": "Use passkeys in your filamentphp app", - "homepage": "https://github.com/marcelweidum/filament-passkeys", - "keywords": [ - "MarcelWeidum", - "filament", - "filament-passkeys", - "filamentphp", - "laravel" - ], - "support": { - "issues": "https://github.com/marcelweidum/filament-passkeys/issues", - "source": "https://github.com/marcelweidum/filament-passkeys" - }, - "funding": [ - { - "url": "https://www.buymeacoffee.com/MarcelWeidum", - "type": "buy_me_a_coffee" - } - ], - "time": "2026-01-17T13:21:33+00:00" + "time": "2026-02-05T23:27:27+00:00" }, { "name": "masterminds/html5", @@ -4950,16 +4877,16 @@ }, { "name": "nette/utils", - "version": "v4.1.1", + "version": "v4.1.2", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72" + "reference": "f76b5dc3d6c6d3043c8d937df2698515b99cbaf5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/c99059c0315591f1a0db7ad6002000288ab8dc72", - "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72", + "url": "https://api.github.com/repos/nette/utils/zipball/f76b5dc3d6c6d3043c8d937df2698515b99cbaf5", + "reference": "f76b5dc3d6c6d3043c8d937df2698515b99cbaf5", "shasum": "" }, "require": { @@ -4972,7 +4899,7 @@ "require-dev": { "jetbrains/phpstorm-attributes": "^1.2", "nette/tester": "^2.5", - "phpstan/phpstan-nette": "^2.0@stable", + "phpstan/phpstan": "^2.0@stable", "tracy/tracy": "^2.9" }, "suggest": { @@ -5033,9 +4960,9 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.1.1" + "source": "https://github.com/nette/utils/tree/v4.1.2" }, - "time": "2025-12-22T12:14:32+00:00" + "time": "2026-02-03T17:21:09+00:00" }, { "name": "nikic/php-parser", @@ -7145,16 +7072,16 @@ }, { "name": "socialiteproviders/authentik", - "version": "5.2.0", + "version": "5.3.0", "source": { "type": "git", "url": "https://github.com/SocialiteProviders/Authentik.git", - "reference": "4cf129cf04728a38e0531c54454464b162f0fa66" + "reference": "4ef0ca226d3be29dc0523f3afc86b63fd6b755b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/Authentik/zipball/4cf129cf04728a38e0531c54454464b162f0fa66", - "reference": "4cf129cf04728a38e0531c54454464b162f0fa66", + "url": "https://api.github.com/repos/SocialiteProviders/Authentik/zipball/4ef0ca226d3be29dc0523f3afc86b63fd6b755b4", + "reference": "4ef0ca226d3be29dc0523f3afc86b63fd6b755b4", "shasum": "" }, "require": { @@ -7191,7 +7118,7 @@ "issues": "https://github.com/socialiteproviders/providers/issues", "source": "https://github.com/socialiteproviders/providers" }, - "time": "2023-11-07T22:21:16+00:00" + "time": "2026-02-04T14:27:03+00:00" }, { "name": "socialiteproviders/discord", @@ -7730,16 +7657,16 @@ }, { "name": "spatie/laravel-health", - "version": "1.34.10", + "version": "1.35.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-health.git", - "reference": "db30de065dd4d41132b9262f2685ffd28f9af8b2" + "reference": "40c1b0688a8fa4a4fde13f883982e6b3a9d00a8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-health/zipball/db30de065dd4d41132b9262f2685ffd28f9af8b2", - "reference": "db30de065dd4d41132b9262f2685ffd28f9af8b2", + "url": "https://api.github.com/repos/spatie/laravel-health/zipball/40c1b0688a8fa4a4fde13f883982e6b3a9d00a8c", + "reference": "40c1b0688a8fa4a4fde13f883982e6b3a9d00a8c", "shasum": "" }, "require": { @@ -7811,7 +7738,7 @@ "spatie" ], "support": { - "source": "https://github.com/spatie/laravel-health/tree/1.34.10" + "source": "https://github.com/spatie/laravel-health/tree/1.35.0" }, "funding": [ { @@ -7819,7 +7746,7 @@ "type": "github" } ], - "time": "2025-12-22T10:06:29+00:00" + "time": "2026-02-01T08:13:12+00:00" }, { "name": "spatie/laravel-package-tools", @@ -7882,84 +7809,6 @@ ], "time": "2025-07-17T15:46:43+00:00" }, - { - "name": "spatie/laravel-passkeys", - "version": "1.5.3", - "source": { - "type": "git", - "url": "https://github.com/spatie/laravel-passkeys.git", - "reference": "641217418497ffa9fdb6c2f5f67a1332b58a6012" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-passkeys/zipball/641217418497ffa9fdb6c2f5f67a1332b58a6012", - "reference": "641217418497ffa9fdb6c2f5f67a1332b58a6012", - "shasum": "" - }, - "require": { - "illuminate/contracts": "^11.0|^12.0", - "php": "^8.2|^8.3|^8.4", - "spatie/laravel-package-tools": "^1.16", - "web-auth/webauthn-lib": "^5.0" - }, - "require-dev": { - "larastan/larastan": "^3.4", - "laravel/pint": "^1.14", - "livewire/livewire": "^3.5", - "nunomaduro/collision": "^8.1.1", - "orchestra/testbench": "^10.0", - "pestphp/pest": "^3.0", - "pestphp/pest-plugin-arch": "^3.0", - "pestphp/pest-plugin-laravel": "^3.0", - "phpstan/extension-installer": "^1.3", - "phpstan/phpstan-deprecation-rules": "^2.0", - "phpstan/phpstan-phpunit": "^2.0", - "spatie/laravel-ray": "^1.35" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Spatie\\LaravelPasskeys\\LaravelPasskeysServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Spatie\\LaravelPasskeys\\": "src/", - "Spatie\\LaravelPasskeys\\Database\\Factories\\": "database/factories/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Freek Van der Herten", - "email": "freek@spatie.be", - "role": "Developer" - } - ], - "description": "Use passkeys in your Laravel app", - "homepage": "https://github.com/spatie/laravel-passkeys", - "keywords": [ - "laravel", - "laravel-passkeys", - "spatie" - ], - "support": { - "issues": "https://github.com/spatie/laravel-passkeys/issues", - "source": "https://github.com/spatie/laravel-passkeys/tree/1.5.3" - }, - "funding": [ - { - "url": "https://github.com/Spatie", - "type": "github" - } - ], - "time": "2026-01-12T08:33:46+00:00" - }, { "name": "spatie/laravel-permission", "version": "6.24.0", @@ -8263,22 +8112,22 @@ }, { "name": "spatie/shiki-php", - "version": "2.3.2", + "version": "2.3.3", "source": { "type": "git", "url": "https://github.com/spatie/shiki-php.git", - "reference": "a2e78a9ff8a1290b25d550be8fbf8285c13175c5" + "reference": "9d50ff4d9825d87d3283a6695c65ae9c3c3caa6b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/shiki-php/zipball/a2e78a9ff8a1290b25d550be8fbf8285c13175c5", - "reference": "a2e78a9ff8a1290b25d550be8fbf8285c13175c5", + "url": "https://api.github.com/repos/spatie/shiki-php/zipball/9d50ff4d9825d87d3283a6695c65ae9c3c3caa6b", + "reference": "9d50ff4d9825d87d3283a6695c65ae9c3c3caa6b", "shasum": "" }, "require": { "ext-json": "*", "php": "^8.0", - "symfony/process": "^5.4|^6.4|^7.1" + "symfony/process": "^5.4|^6.4|^7.1|^8.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^v3.0", @@ -8316,7 +8165,7 @@ "spatie" ], "support": { - "source": "https://github.com/spatie/shiki-php/tree/2.3.2" + "source": "https://github.com/spatie/shiki-php/tree/2.3.3" }, "funding": [ { @@ -8324,7 +8173,7 @@ "type": "github" } ], - "time": "2025-02-21T14:16:57+00:00" + "time": "2026-02-01T09:30:04+00:00" }, { "name": "spatie/temporary-directory", @@ -8387,186 +8236,6 @@ ], "time": "2026-01-12T07:42:22+00:00" }, - { - "name": "spomky-labs/cbor-php", - "version": "3.2.2", - "source": { - "type": "git", - "url": "https://github.com/Spomky-Labs/cbor-php.git", - "reference": "2a5fb86aacfe1004611370ead6caa2bfc88435d0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/2a5fb86aacfe1004611370ead6caa2bfc88435d0", - "reference": "2a5fb86aacfe1004611370ead6caa2bfc88435d0", - "shasum": "" - }, - "require": { - "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14", - "ext-mbstring": "*", - "php": ">=8.0" - }, - "require-dev": { - "ext-json": "*", - "roave/security-advisories": "dev-latest", - "symfony/error-handler": "^6.4|^7.1|^8.0", - "symfony/var-dumper": "^6.4|^7.1|^8.0" - }, - "suggest": { - "ext-bcmath": "GMP or BCMath extensions will drastically improve the library performance. BCMath extension needed to handle the Big Float and Decimal Fraction Tags", - "ext-gmp": "GMP or BCMath extensions will drastically improve the library performance" - }, - "type": "library", - "autoload": { - "psr-4": { - "CBOR\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Florent Morselli", - "homepage": "https://github.com/Spomky" - }, - { - "name": "All contributors", - "homepage": "https://github.com/Spomky-Labs/cbor-php/contributors" - } - ], - "description": "CBOR Encoder/Decoder for PHP", - "keywords": [ - "Concise Binary Object Representation", - "RFC7049", - "cbor" - ], - "support": { - "issues": "https://github.com/Spomky-Labs/cbor-php/issues", - "source": "https://github.com/Spomky-Labs/cbor-php/tree/3.2.2" - }, - "funding": [ - { - "url": "https://github.com/Spomky", - "type": "github" - }, - { - "url": "https://www.patreon.com/FlorentMorselli", - "type": "patreon" - } - ], - "time": "2025-11-13T13:00:34+00:00" - }, - { - "name": "spomky-labs/pki-framework", - "version": "1.4.1", - "source": { - "type": "git", - "url": "https://github.com/Spomky-Labs/pki-framework.git", - "reference": "f0e9a548df4e3942886adc9b7830581a46334631" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/f0e9a548df4e3942886adc9b7830581a46334631", - "reference": "f0e9a548df4e3942886adc9b7830581a46334631", - "shasum": "" - }, - "require": { - "brick/math": "^0.10|^0.11|^0.12|^0.13|^0.14", - "ext-mbstring": "*", - "php": ">=8.1" - }, - "require-dev": { - "ekino/phpstan-banned-code": "^1.0|^2.0|^3.0", - "ext-gmp": "*", - "ext-openssl": "*", - "infection/infection": "^0.28|^0.29|^0.31", - "php-parallel-lint/php-parallel-lint": "^1.3", - "phpstan/extension-installer": "^1.3|^2.0", - "phpstan/phpstan": "^1.8|^2.0", - "phpstan/phpstan-deprecation-rules": "^1.0|^2.0", - "phpstan/phpstan-phpunit": "^1.1|^2.0", - "phpstan/phpstan-strict-rules": "^1.3|^2.0", - "phpunit/phpunit": "^10.1|^11.0|^12.0", - "rector/rector": "^1.0|^2.0", - "roave/security-advisories": "dev-latest", - "symfony/string": "^6.4|^7.0|^8.0", - "symfony/var-dumper": "^6.4|^7.0|^8.0", - "symplify/easy-coding-standard": "^12.0" - }, - "suggest": { - "ext-bcmath": "For better performance (or GMP)", - "ext-gmp": "For better performance (or BCMath)", - "ext-openssl": "For OpenSSL based cyphering" - }, - "type": "library", - "autoload": { - "psr-4": { - "SpomkyLabs\\Pki\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Joni Eskelinen", - "email": "jonieske@gmail.com", - "role": "Original developer" - }, - { - "name": "Florent Morselli", - "email": "florent.morselli@spomky-labs.com", - "role": "Spomky-Labs PKI Framework developer" - } - ], - "description": "A PHP framework for managing Public Key Infrastructures. It comprises X.509 public key certificates, attribute certificates, certification requests and certification path validation.", - "homepage": "https://github.com/spomky-labs/pki-framework", - "keywords": [ - "DER", - "Private Key", - "ac", - "algorithm identifier", - "asn.1", - "asn1", - "attribute certificate", - "certificate", - "certification request", - "cryptography", - "csr", - "decrypt", - "ec", - "encrypt", - "pem", - "pkcs", - "public key", - "rsa", - "sign", - "signature", - "verify", - "x.509", - "x.690", - "x509", - "x690" - ], - "support": { - "issues": "https://github.com/Spomky-Labs/pki-framework/issues", - "source": "https://github.com/Spomky-Labs/pki-framework/tree/1.4.1" - }, - "funding": [ - { - "url": "https://github.com/Spomky", - "type": "github" - }, - { - "url": "https://www.patreon.com/FlorentMorselli", - "type": "patreon" - } - ], - "time": "2025-12-20T12:57:40+00:00" - }, { "name": "symfony/clock", "version": "v7.4.0", @@ -10929,31 +10598,40 @@ "time": "2026-01-26T15:07:59+00:00" }, { - "name": "symfony/property-access", + "name": "symfony/routing", "version": "v7.4.4", "source": { "type": "git", - "url": "https://github.com/symfony/property-access.git", - "reference": "fa49bf1ca8fce1ba0e2dba4e4658554cfb9364b1" + "url": "https://github.com/symfony/routing.git", + "reference": "0798827fe2c79caeed41d70b680c2c3507d10147" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/fa49bf1ca8fce1ba0e2dba4e4658554cfb9364b1", - "reference": "fa49bf1ca8fce1ba0e2dba4e4658554cfb9364b1", + "url": "https://api.github.com/repos/symfony/routing/zipball/0798827fe2c79caeed41d70b680c2c3507d10147", + "reference": "0798827fe2c79caeed41d70b680c2c3507d10147", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/property-info": "^6.4.32|~7.3.10|^7.4.4|^8.0.4" + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/config": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/yaml": "<6.4" }, "require-dev": { - "symfony/cache": "^6.4|^7.0|^8.0", - "symfony/var-exporter": "^6.4.1|^7.0.1|^8.0" + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\PropertyAccess\\": "" + "Symfony\\Component\\Routing\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -10973,21 +10651,16 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Provides functions to read and write from/to an object or array using a simple string notation", + "description": "Maps an HTTP request to a set of configuration variables", "homepage": "https://symfony.com", "keywords": [ - "access", - "array", - "extraction", - "index", - "injection", - "object", - "property", - "property-path", - "reflection" + "router", + "routing", + "uri", + "url" ], "support": { - "source": "https://github.com/symfony/property-access/tree/v7.4.4" + "source": "https://github.com/symfony/routing/tree/v7.4.4" }, "funding": [ { @@ -11007,307 +10680,29 @@ "type": "tidelift" } ], - "time": "2026-01-05T08:47:25+00:00" + "time": "2026-01-12T12:19:02+00:00" }, { - "name": "symfony/property-info", - "version": "v7.4.5", + "name": "symfony/service-contracts", + "version": "v3.6.1", "source": { "type": "git", - "url": "https://github.com/symfony/property-info.git", - "reference": "1c9d326bd69602561e2ea467a16c09b5972eee21" + "url": "https://github.com/symfony/service-contracts.git", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/1c9d326bd69602561e2ea467a16c09b5972eee21", - "reference": "1c9d326bd69602561e2ea467a16c09b5972eee21", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/string": "^6.4|^7.0|^8.0", - "symfony/type-info": "~7.3.10|^7.4.4|^8.0.4" + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { - "phpdocumentor/reflection-docblock": "<5.2|>=6", - "phpdocumentor/type-resolver": "<1.5.1", - "symfony/cache": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/serializer": "<6.4" - }, - "require-dev": { - "phpdocumentor/reflection-docblock": "^5.2", - "phpstan/phpdoc-parser": "^1.0|^2.0", - "symfony/cache": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/serializer": "^6.4|^7.0|^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\PropertyInfo\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Kévin Dunglas", - "email": "dunglas@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Extracts information about PHP class' properties using metadata of popular sources", - "homepage": "https://symfony.com", - "keywords": [ - "doctrine", - "phpdoc", - "property", - "symfony", - "type", - "validator" - ], - "support": { - "source": "https://github.com/symfony/property-info/tree/v7.4.5" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2026-01-27T16:16:02+00:00" - }, - { - "name": "symfony/routing", - "version": "v7.4.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/routing.git", - "reference": "0798827fe2c79caeed41d70b680c2c3507d10147" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/0798827fe2c79caeed41d70b680c2c3507d10147", - "reference": "0798827fe2c79caeed41d70b680c2c3507d10147", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/config": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/yaml": "<6.4" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/http-foundation": "^6.4|^7.0|^8.0", - "symfony/yaml": "^6.4|^7.0|^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Routing\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Maps an HTTP request to a set of configuration variables", - "homepage": "https://symfony.com", - "keywords": [ - "router", - "routing", - "uri", - "url" - ], - "support": { - "source": "https://github.com/symfony/routing/tree/v7.4.4" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2026-01-12T12:19:02+00:00" - }, - { - "name": "symfony/serializer", - "version": "v7.4.5", - "source": { - "type": "git", - "url": "https://github.com/symfony/serializer.git", - "reference": "480cd1237c98ab1219c20945b92c9d4480a44f47" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/480cd1237c98ab1219c20945b92c9d4480a44f47", - "reference": "480cd1237c98ab1219c20945b92c9d4480a44f47", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-php84": "^1.30" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "<5.2|>=6", - "phpdocumentor/type-resolver": "<1.5.1", - "symfony/dependency-injection": "<6.4", - "symfony/property-access": "<6.4", - "symfony/property-info": "<6.4", - "symfony/uid": "<6.4", - "symfony/validator": "<6.4", - "symfony/yaml": "<6.4" - }, - "require-dev": { - "phpdocumentor/reflection-docblock": "^5.2", - "phpstan/phpdoc-parser": "^1.0|^2.0", - "seld/jsonlint": "^1.10", - "symfony/cache": "^6.4|^7.0|^8.0", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/console": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^7.2|^8.0", - "symfony/error-handler": "^6.4|^7.0|^8.0", - "symfony/filesystem": "^6.4|^7.0|^8.0", - "symfony/form": "^6.4|^7.0|^8.0", - "symfony/http-foundation": "^6.4|^7.0|^8.0", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/messenger": "^6.4|^7.0|^8.0", - "symfony/mime": "^6.4|^7.0|^8.0", - "symfony/property-access": "^6.4|^7.0|^8.0", - "symfony/property-info": "^6.4|^7.0|^8.0", - "symfony/translation-contracts": "^2.5|^3", - "symfony/type-info": "^7.1.8|^8.0", - "symfony/uid": "^6.4|^7.0|^8.0", - "symfony/validator": "^6.4|^7.0|^8.0", - "symfony/var-dumper": "^6.4|^7.0|^8.0", - "symfony/var-exporter": "^6.4|^7.0|^8.0", - "symfony/yaml": "^6.4|^7.0|^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Serializer\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/serializer/tree/v7.4.5" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2026-01-27T08:59:58+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v3.6.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" + "ext-psr": "<1.1|>=2" }, "type": "library", "extra": { @@ -11647,89 +11042,6 @@ ], "time": "2025-07-15T13:41:35+00:00" }, - { - "name": "symfony/type-info", - "version": "v7.4.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/type-info.git", - "reference": "f83c725e72b39b2704b9d6fc85070ad6ac7a5889" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/type-info/zipball/f83c725e72b39b2704b9d6fc85070ad6ac7a5889", - "reference": "f83c725e72b39b2704b9d6fc85070ad6ac7a5889", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "conflict": { - "phpstan/phpdoc-parser": "<1.30" - }, - "require-dev": { - "phpstan/phpdoc-parser": "^1.30|^2.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\TypeInfo\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mathias Arlaud", - "email": "mathias.arlaud@gmail.com" - }, - { - "name": "Baptiste LEDUC", - "email": "baptiste.leduc@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Extracts PHP types information.", - "homepage": "https://symfony.com", - "keywords": [ - "PHPStan", - "phpdoc", - "symfony", - "type" - ], - "support": { - "source": "https://github.com/symfony/type-info/tree/v7.4.4" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2026-01-09T12:14:21+00:00" - }, { "name": "symfony/uid", "version": "v7.4.4", @@ -12253,163 +11565,6 @@ ], "time": "2024-11-21T01:49:47+00:00" }, - { - "name": "web-auth/cose-lib", - "version": "4.5.0", - "source": { - "type": "git", - "url": "https://github.com/web-auth/cose-lib.git", - "reference": "5adac6fe126994a3ee17ed9950efb4947ab132a9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/5adac6fe126994a3ee17ed9950efb4947ab132a9", - "reference": "5adac6fe126994a3ee17ed9950efb4947ab132a9", - "shasum": "" - }, - "require": { - "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14", - "ext-json": "*", - "ext-openssl": "*", - "php": ">=8.1", - "spomky-labs/pki-framework": "^1.0" - }, - "require-dev": { - "spomky-labs/cbor-php": "^3.2.2" - }, - "suggest": { - "ext-bcmath": "For better performance, please install either GMP (recommended) or BCMath extension", - "ext-gmp": "For better performance, please install either GMP (recommended) or BCMath extension", - "spomky-labs/cbor-php": "For COSE Signature support" - }, - "type": "library", - "autoload": { - "psr-4": { - "Cose\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Florent Morselli", - "homepage": "https://github.com/Spomky" - }, - { - "name": "All contributors", - "homepage": "https://github.com/web-auth/cose/contributors" - } - ], - "description": "CBOR Object Signing and Encryption (COSE) For PHP", - "homepage": "https://github.com/web-auth", - "keywords": [ - "COSE", - "RFC8152" - ], - "support": { - "issues": "https://github.com/web-auth/cose-lib/issues", - "source": "https://github.com/web-auth/cose-lib/tree/4.5.0" - }, - "funding": [ - { - "url": "https://github.com/Spomky", - "type": "github" - }, - { - "url": "https://www.patreon.com/FlorentMorselli", - "type": "patreon" - } - ], - "time": "2026-01-03T14:43:18+00:00" - }, - { - "name": "web-auth/webauthn-lib", - "version": "5.2.3", - "source": { - "type": "git", - "url": "https://github.com/web-auth/webauthn-lib.git", - "reference": "8782f575032fedc36e2eb27c39c736054e2b6867" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/web-auth/webauthn-lib/zipball/8782f575032fedc36e2eb27c39c736054e2b6867", - "reference": "8782f575032fedc36e2eb27c39c736054e2b6867", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-openssl": "*", - "paragonie/constant_time_encoding": "^2.6|^3.0", - "php": ">=8.2", - "phpdocumentor/reflection-docblock": "^5.3", - "psr/clock": "^1.0", - "psr/event-dispatcher": "^1.0", - "psr/log": "^1.0|^2.0|^3.0", - "spomky-labs/cbor-php": "^3.0", - "spomky-labs/pki-framework": "^1.0", - "symfony/clock": "^6.4|^7.0", - "symfony/deprecation-contracts": "^3.2", - "symfony/property-access": "^6.4|^7.0", - "symfony/property-info": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", - "symfony/uid": "^6.4|^7.0", - "web-auth/cose-lib": "^4.2.3" - }, - "suggest": { - "psr/log-implementation": "Recommended to receive logs from the library", - "symfony/event-dispatcher": "Recommended to use dispatched events", - "web-token/jwt-library": "Mandatory for fetching Metadata Statement from distant sources" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/web-auth/webauthn-framework", - "name": "web-auth/webauthn-framework" - } - }, - "autoload": { - "psr-4": { - "Webauthn\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Florent Morselli", - "homepage": "https://github.com/Spomky" - }, - { - "name": "All contributors", - "homepage": "https://github.com/web-auth/webauthn-library/contributors" - } - ], - "description": "FIDO2/Webauthn Support For PHP", - "homepage": "https://github.com/web-auth", - "keywords": [ - "FIDO2", - "fido", - "webauthn" - ], - "support": { - "source": "https://github.com/web-auth/webauthn-lib/tree/5.2.3" - }, - "funding": [ - { - "url": "https://github.com/Spomky", - "type": "github" - }, - { - "url": "https://www.patreon.com/FlorentMorselli", - "type": "patreon" - } - ], - "time": "2025-12-20T10:54:02+00:00" - }, { "name": "webmozart/assert", "version": "1.11.0", @@ -13105,16 +12260,16 @@ }, { "name": "iamcal/sql-parser", - "version": "v0.6", + "version": "v0.7", "source": { "type": "git", "url": "https://github.com/iamcal/SQLParser.git", - "reference": "947083e2dca211a6f12fb1beb67a01e387de9b62" + "reference": "610392f38de49a44dab08dc1659960a29874c4b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/iamcal/SQLParser/zipball/947083e2dca211a6f12fb1beb67a01e387de9b62", - "reference": "947083e2dca211a6f12fb1beb67a01e387de9b62", + "url": "https://api.github.com/repos/iamcal/SQLParser/zipball/610392f38de49a44dab08dc1659960a29874c4b8", + "reference": "610392f38de49a44dab08dc1659960a29874c4b8", "shasum": "" }, "require-dev": { @@ -13140,9 +12295,9 @@ "description": "MySQL schema parser", "support": { "issues": "https://github.com/iamcal/SQLParser/issues", - "source": "https://github.com/iamcal/SQLParser/tree/v0.6" + "source": "https://github.com/iamcal/SQLParser/tree/v0.7" }, - "time": "2025-03-17T16:59:46+00:00" + "time": "2026-01-28T22:20:33+00:00" }, { "name": "jean85/pretty-package-versions", @@ -13206,21 +12361,21 @@ }, { "name": "larastan/larastan", - "version": "v3.9.1", + "version": "v3.9.2", "source": { "type": "git", "url": "https://github.com/larastan/larastan.git", - "reference": "4b92d9627f779fd32bdc16f53f8ce88c50446ff5" + "reference": "2e9ed291bdc1969e7f270fb33c9cdf3c912daeb2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/larastan/larastan/zipball/4b92d9627f779fd32bdc16f53f8ce88c50446ff5", - "reference": "4b92d9627f779fd32bdc16f53f8ce88c50446ff5", + "url": "https://api.github.com/repos/larastan/larastan/zipball/2e9ed291bdc1969e7f270fb33c9cdf3c912daeb2", + "reference": "2e9ed291bdc1969e7f270fb33c9cdf3c912daeb2", "shasum": "" }, "require": { "ext-json": "*", - "iamcal/sql-parser": "^0.6.0", + "iamcal/sql-parser": "^0.7.0", "illuminate/console": "^11.44.2 || ^12.4.1", "illuminate/container": "^11.44.2 || ^12.4.1", "illuminate/contracts": "^11.44.2 || ^12.4.1", @@ -13284,7 +12439,7 @@ ], "support": { "issues": "https://github.com/larastan/larastan/issues", - "source": "https://github.com/larastan/larastan/tree/v3.9.1" + "source": "https://github.com/larastan/larastan/tree/v3.9.2" }, "funding": [ { @@ -13292,41 +12447,42 @@ "type": "github" } ], - "time": "2026-01-21T09:15:17+00:00" + "time": "2026-01-30T15:16:32+00:00" }, { "name": "laravel/pail", - "version": "v1.2.4", + "version": "v1.2.5", "source": { "type": "git", "url": "https://github.com/laravel/pail.git", - "reference": "49f92285ff5d6fc09816e976a004f8dec6a0ea30" + "reference": "fdb73f5eacf03db576c710d5a00101ba185f2254" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pail/zipball/49f92285ff5d6fc09816e976a004f8dec6a0ea30", - "reference": "49f92285ff5d6fc09816e976a004f8dec6a0ea30", + "url": "https://api.github.com/repos/laravel/pail/zipball/fdb73f5eacf03db576c710d5a00101ba185f2254", + "reference": "fdb73f5eacf03db576c710d5a00101ba185f2254", "shasum": "" }, "require": { "ext-mbstring": "*", - "illuminate/console": "^10.24|^11.0|^12.0", - "illuminate/contracts": "^10.24|^11.0|^12.0", - "illuminate/log": "^10.24|^11.0|^12.0", - "illuminate/process": "^10.24|^11.0|^12.0", - "illuminate/support": "^10.24|^11.0|^12.0", + "illuminate/console": "^10.24|^11.0|^12.0|^13.0", + "illuminate/contracts": "^10.24|^11.0|^12.0|^13.0", + "illuminate/log": "^10.24|^11.0|^12.0|^13.0", + "illuminate/process": "^10.24|^11.0|^12.0|^13.0", + "illuminate/support": "^10.24|^11.0|^12.0|^13.0", "nunomaduro/termwind": "^1.15|^2.0", "php": "^8.2", - "symfony/console": "^6.0|^7.0" + "symfony/console": "^6.0|^7.0|^8.0" }, "require-dev": { - "laravel/framework": "^10.24|^11.0|^12.0", + "laravel/framework": "^10.24|^11.0|^12.0|^13.0", "laravel/pint": "^1.13", - "orchestra/testbench-core": "^8.13|^9.17|^10.8", + "orchestra/testbench-core": "^8.13|^9.17|^10.8|^11.0", "pestphp/pest": "^2.20|^3.0|^4.0", "pestphp/pest-plugin-type-coverage": "^2.3|^3.0|^4.0", "phpstan/phpstan": "^1.12.27", - "symfony/var-dumper": "^6.3|^7.0" + "symfony/var-dumper": "^6.3|^7.0|^8.0", + "symfony/yaml": "^6.3|^7.0|^8.0" }, "type": "library", "extra": { @@ -13371,7 +12527,7 @@ "issues": "https://github.com/laravel/pail/issues", "source": "https://github.com/laravel/pail" }, - "time": "2025-11-20T16:29:35+00:00" + "time": "2026-02-04T15:10:32+00:00" }, { "name": "laravel/pint", @@ -14403,28 +13559,28 @@ }, { "name": "phpunit/php-file-iterator", - "version": "5.1.0", + "version": "5.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" + "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", - "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/2f3a64888c814fc235386b7387dd5b5ed92ad903", + "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -14452,15 +13608,27 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-file-iterator", + "type": "tidelift" } ], - "time": "2024-08-27T05:02:59+00:00" + "time": "2026-02-02T13:52:54+00:00" }, { "name": "phpunit/php-invoker", diff --git a/config/passkeys.php b/config/passkeys.php new file mode 100644 index 0000000000..bf6940f5d0 --- /dev/null +++ b/config/passkeys.php @@ -0,0 +1,41 @@ + '/', + + /* + * These class are responsible for performing core tasks regarding passkeys. + * You can customize them by creating a class that extends the default, and + * by specifying your custom class name here. + */ + 'actions' => [ + 'generate_passkey_register_options' => Spatie\LaravelPasskeys\Actions\GeneratePasskeyRegisterOptionsAction::class, + 'store_passkey' => Spatie\LaravelPasskeys\Actions\StorePasskeyAction::class, + 'generate_passkey_authentication_options' => \Spatie\LaravelPasskeys\Actions\GeneratePasskeyAuthenticationOptionsAction::class, + 'find_passkey' => Spatie\LaravelPasskeys\Actions\FindPasskeyToAuthenticateAction::class, + 'configure_ceremony_step_manager_factory' => Spatie\LaravelPasskeys\Actions\ConfigureCeremonyStepManagerFactoryAction::class, + ], + + /* + * These properties will be used to generate the passkey. + */ + 'relying_party' => [ + 'name' => config('app.name'), + 'id' => parse_url(config('app.url'), PHP_URL_HOST), + 'icon' => null, + ], + + /* + * The models used by the package. + * + * You can override this by specifying your own models + */ + 'models' => [ + 'passkey' => Spatie\LaravelPasskeys\Models\Passkey::class, + 'authenticatable' => env('AUTH_MODEL', App\Models\User::class), + ], +]; diff --git a/lang/en/passkeys.php b/lang/en/passkeys.php new file mode 100644 index 0000000000..975421434c --- /dev/null +++ b/lang/en/passkeys.php @@ -0,0 +1,20 @@ + __('passkeys::passkeys.authenticate_using_passkey'), + 'create' => __('passkeys::passkeys.create'), + 'delete' => __('passkeys::passkeys.delete'), + 'error_something_went_wrong_generating_the_passkey' => __('passkeys::passkeys.error_something_went_wrong_generating_the_passkey'), + 'invalid' => __('passkeys::passkeys.invalid'), + 'last_used' => __('passkeys::passkeys.last_used'), + 'name' => __('passkeys::passkeys.name'), + 'name_placeholder' => __('passkeys::passkeys.name_placeholder'), + 'no_passkeys_registered' => __('passkeys::passkeys.no_passkeys_registered'), + 'not_used_yet' => __('passkeys::passkeys.not_used_yet'), + 'passkeys' => __('passkeys::passkeys.passkeys'), + 'description' => 'Passkeys let you log in without needing a password. Instead of a password, you can generate a passkey which will be stored in 1Pass, MacOS\' password app, or alternative app on your favourite OS.', + 'created_notification_title' => 'Your passkey has been created', + 'deleted_notification_title' => 'Your passkey has been deleted', +]; diff --git a/package.json b/package.json index 47ca60a886..c76c6503c8 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "vite": "7.1.11" }, "dependencies": { + "@simplewebauthn/browser": "^13.2.2", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-search": "^0.15.0", "@xterm/addon-web-links": "^0.11.0", diff --git a/resources/js/app.js b/resources/js/app.js index e0dc6dc922..fa5c05b141 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -14,4 +14,5 @@ document.body.removeChild(textarea); success ? resolve() : reject('Fallback copy failed'); }); -})(); \ No newline at end of file +})(); +import './passkeys/index.js'; \ No newline at end of file diff --git a/resources/js/passkeys/index.js b/resources/js/passkeys/index.js new file mode 100644 index 0000000000..abec0ad6e5 --- /dev/null +++ b/resources/js/passkeys/index.js @@ -0,0 +1,9 @@ +import { + browserSupportsWebAuthn, + startAuthentication, + startRegistration, +} from '@simplewebauthn/browser' + +window.browserSupportsWebAuthn = browserSupportsWebAuthn; +window.startAuthentication = startAuthentication; +window.startRegistration = startRegistration; diff --git a/resources/views/passkeys/components/authenticate.blade.php b/resources/views/passkeys/components/authenticate.blade.php new file mode 100644 index 0000000000..3af69a17c9 --- /dev/null +++ b/resources/views/passkeys/components/authenticate.blade.php @@ -0,0 +1,17 @@ +
+ @include('passkeys::components.partials.authenticateScript') + +
+ @csrf +
+ + @if($message = session()->get('authenticatePasskey::message')) + @php + \Filament\Notifications\Notification::make() + ->title($message) + ->danger() + ->send(); + session()->forget('authenticatePasskey::message'); + @endphp + @endif +
diff --git a/resources/views/passkeys/livewire/passkeys-tab.blade.php b/resources/views/passkeys/livewire/passkeys-tab.blade.php new file mode 100644 index 0000000000..298db9f604 --- /dev/null +++ b/resources/views/passkeys/livewire/passkeys-tab.blade.php @@ -0,0 +1 @@ + diff --git a/resources/views/passkeys/livewire/passkeys.blade.php b/resources/views/passkeys/livewire/passkeys.blade.php new file mode 100644 index 0000000000..bf1e7cad8c --- /dev/null +++ b/resources/views/passkeys/livewire/passkeys.blade.php @@ -0,0 +1,51 @@ +
+
+
+ + + + + @error('name') +

{{ $message }}

+ @enderror +
+ + + {{ __('passkeys.create') }} + +
+ + @if($passkeys->isNotEmpty()) +
+ {{ __('passkeys.passkeys') }} +
    + @foreach($passkeys as $passkey) + +
    +
    + {{ $passkey->name }} + {{ __('passkeys.last_used') }}: {{ $passkey->last_used_at?->diffForHumans() ?? __('passkeys.not_used_yet') }} +
    + + + {{ __('passkeys.delete') }} + +
    +
    + @endforeach +
+
+ @endif + + +
+ +@include('passkeys::livewire.partials.createScript') diff --git a/resources/views/passkeys/login.blade.php b/resources/views/passkeys/login.blade.php new file mode 100644 index 0000000000..df13aa8c3c --- /dev/null +++ b/resources/views/passkeys/login.blade.php @@ -0,0 +1,5 @@ +@include('passkeys.components.authenticate') + + + {{ __('passkeys.authenticate_using_passkey') }} + diff --git a/resources/views/passkeys/profile.blade.php b/resources/views/passkeys/profile.blade.php new file mode 100644 index 0000000000..2a7cd479df --- /dev/null +++ b/resources/views/passkeys/profile.blade.php @@ -0,0 +1,11 @@ + + + {{ __('passkeys.passkeys') }} + + + + {{ __('passkeys.description') }} + + + + diff --git a/resources/views/vendor/passkeys/components/authenticate.blade.php b/resources/views/vendor/passkeys/components/authenticate.blade.php deleted file mode 100644 index abbeb13480..0000000000 --- a/resources/views/vendor/passkeys/components/authenticate.blade.php +++ /dev/null @@ -1,23 +0,0 @@ -
- @include('passkeys::components.partials.authenticateScript') - -
- @csrf -
- - @if($message = session()->get('authenticatePasskey::message')) -
- {{ $message }} -
- @endif - -
- @if ($slot->isEmpty()) -
- {{ __('passkeys::passkeys.authenticate_using_passkey') }} -
- @else - {{ $slot }} - @endif -
-
diff --git a/resources/views/vendor/passkeys/components/partials/authenticateScript.blade.php b/resources/views/vendor/passkeys/components/partials/authenticateScript.blade.php deleted file mode 100644 index c0098f0a24..0000000000 --- a/resources/views/vendor/passkeys/components/partials/authenticateScript.blade.php +++ /dev/null @@ -1,18 +0,0 @@ - diff --git a/resources/views/vendor/passkeys/livewire/partials/createScript.blade.php b/resources/views/vendor/passkeys/livewire/partials/createScript.blade.php deleted file mode 100644 index 4d5a17bb9e..0000000000 --- a/resources/views/vendor/passkeys/livewire/partials/createScript.blade.php +++ /dev/null @@ -1,11 +0,0 @@ -@script - -@endscript diff --git a/resources/views/vendor/passkeys/livewire/passkeys.blade.php b/resources/views/vendor/passkeys/livewire/passkeys.blade.php deleted file mode 100644 index 2450b0240b..0000000000 --- a/resources/views/vendor/passkeys/livewire/passkeys.blade.php +++ /dev/null @@ -1,42 +0,0 @@ -
-

{{ __('passkeys::passkeys.passkeys') }}

-
-
-
- - - @error('name') - {{ $message }} - @enderror -
- - -
-
- -
-
    - @foreach($passkeys as $passkey) -
  • -
    - {{ $passkey->name }} -
    -
    - {{ __('passkeys::passkeys.last_used') }}: {{ $passkey->last_used_at?->diffForHumans() ?? __('passkeys::passkeys.not_used_yet') }} -
    - - -
    - -
    -
  • - @endforeach -
-
-
- -@include('passkeys::livewire.partials.createScript') diff --git a/yarn.lock b/yarn.lock index 866904019b..0f6faa19a7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -292,6 +292,11 @@ resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.1.tgz#56eeb602545ec03ce84633b331c2e3ece07b99c3" integrity sha512-rLarc1Ofcs3DHtgSzFO31pZsCh8g05R2azN1q3fF+H423Co87My0R+tazOEvYVKXSLh8C4LerMK41/K7wlklcg== +"@simplewebauthn/browser@^13.2.2": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@simplewebauthn/browser/-/browser-13.2.2.tgz#4cde38c4c6969a039c23c2a3d931ecb69f937910" + integrity sha512-FNW1oLQpTJyqG5kkDg5ZsotvWgmBaC6jCHR7Ej0qUNep36Wl9tj2eZu7J5rP+uhXgHaLk+QQ3lqcw2vS5MX1IA== + "@tailwindcss/forms@^0.5.9": version "0.5.10" resolved "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.10.tgz" From 3aaba31b7c76ffc4382653f87cb50f59ffbfb7b9 Mon Sep 17 00:00:00 2001 From: JoanFo1456 Date: Sat, 7 Feb 2026 16:17:19 +0100 Subject: [PATCH 06/18] Moved everything to Livewire --- app/{Passkeys => Filament}/PasskeysPlugin.php | 4 ++-- app/{Passkeys => }/Livewire/Passkeys.php | 2 +- app/Providers/Filament/FilamentServiceProvider.php | 2 +- app/Providers/Filament/PanelProvider.php | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename app/{Passkeys => Filament}/PasskeysPlugin.php (94%) rename app/{Passkeys => }/Livewire/Passkeys.php (98%) diff --git a/app/Passkeys/PasskeysPlugin.php b/app/Filament/PasskeysPlugin.php similarity index 94% rename from app/Passkeys/PasskeysPlugin.php rename to app/Filament/PasskeysPlugin.php index 68f1f04981..7ddfe2106b 100644 --- a/app/Passkeys/PasskeysPlugin.php +++ b/app/Filament/PasskeysPlugin.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace App\Passkeys; +namespace App\Filament; use Filament\Auth\Pages\EditProfile; use Filament\Contracts\Plugin; @@ -11,7 +11,7 @@ use Filament\View\PanelsRenderHook; use Illuminate\View\View; use Livewire\Livewire; -use App\Passkeys\Livewire\Passkeys; +use App\Livewire\Passkeys; final class PasskeysPlugin implements Plugin { diff --git a/app/Passkeys/Livewire/Passkeys.php b/app/Livewire/Passkeys.php similarity index 98% rename from app/Passkeys/Livewire/Passkeys.php rename to app/Livewire/Passkeys.php index 8d64c8b1d6..f24cf5450a 100644 --- a/app/Passkeys/Livewire/Passkeys.php +++ b/app/Livewire/Passkeys.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace App\Passkeys\Livewire; +namespace App\Livewire; use Filament\Actions\Action; use Filament\Actions\Concerns\InteractsWithActions; diff --git a/app/Providers/Filament/FilamentServiceProvider.php b/app/Providers/Filament/FilamentServiceProvider.php index a9895110d3..307036cf01 100644 --- a/app/Providers/Filament/FilamentServiceProvider.php +++ b/app/Providers/Filament/FilamentServiceProvider.php @@ -33,7 +33,7 @@ use Illuminate\Support\ServiceProvider; use Livewire\Component; use Livewire\Livewire; -use App\Passkeys\Livewire\Passkeys; +use App\Livewire\Passkeys; use function Livewire\on; use function Livewire\store; diff --git a/app/Providers/Filament/PanelProvider.php b/app/Providers/Filament/PanelProvider.php index 61607bd6db..a914fb5e74 100644 --- a/app/Providers/Filament/PanelProvider.php +++ b/app/Providers/Filament/PanelProvider.php @@ -22,7 +22,7 @@ use Illuminate\Session\Middleware\AuthenticateSession; use Illuminate\Session\Middleware\StartSession; use Illuminate\View\Middleware\ShareErrorsFromSession; -use App\Passkeys\PasskeysPlugin; +use App\Filament\PasskeysPlugin; abstract class PanelProvider extends BasePanelProvider { From 64799cdb4ba1a96b9f9525ab0986134db46cf60f Mon Sep 17 00:00:00 2001 From: JoanFo1456 Date: Sat, 7 Feb 2026 16:23:32 +0100 Subject: [PATCH 07/18] Pint --- app/Filament/PasskeysPlugin.php | 3 +-- app/Providers/Filament/FilamentServiceProvider.php | 2 +- app/Providers/Filament/PanelProvider.php | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/Filament/PasskeysPlugin.php b/app/Filament/PasskeysPlugin.php index 7ddfe2106b..7f4f4bcb1f 100644 --- a/app/Filament/PasskeysPlugin.php +++ b/app/Filament/PasskeysPlugin.php @@ -4,14 +4,13 @@ namespace App\Filament; -use Filament\Auth\Pages\EditProfile; +use App\Livewire\Passkeys; use Filament\Contracts\Plugin; use Filament\Panel; use Filament\Support\Facades\FilamentView; use Filament\View\PanelsRenderHook; use Illuminate\View\View; use Livewire\Livewire; -use App\Livewire\Passkeys; final class PasskeysPlugin implements Plugin { diff --git a/app/Providers/Filament/FilamentServiceProvider.php b/app/Providers/Filament/FilamentServiceProvider.php index 307036cf01..a3934d4133 100644 --- a/app/Providers/Filament/FilamentServiceProvider.php +++ b/app/Providers/Filament/FilamentServiceProvider.php @@ -4,6 +4,7 @@ use App\Enums\CustomizationKey; use App\Enums\TablerIcon; +use App\Livewire\Passkeys; use Filament\Actions\Action; use Filament\Actions\CreateAction; use Filament\Actions\DeleteAction; @@ -33,7 +34,6 @@ use Illuminate\Support\ServiceProvider; use Livewire\Component; use Livewire\Livewire; -use App\Livewire\Passkeys; use function Livewire\on; use function Livewire\store; diff --git a/app/Providers/Filament/PanelProvider.php b/app/Providers/Filament/PanelProvider.php index a914fb5e74..02441601d6 100644 --- a/app/Providers/Filament/PanelProvider.php +++ b/app/Providers/Filament/PanelProvider.php @@ -5,6 +5,7 @@ use App\Enums\CustomizationKey; use App\Filament\Pages\Auth\EditProfile; use App\Filament\Pages\Auth\Login; +use App\Filament\PasskeysPlugin; use App\Http\Middleware\LanguageMiddleware; use App\Http\Middleware\RequireTwoFactorAuthentication; use Filament\Actions\Action; @@ -22,7 +23,6 @@ use Illuminate\Session\Middleware\AuthenticateSession; use Illuminate\Session\Middleware\StartSession; use Illuminate\View\Middleware\ShareErrorsFromSession; -use App\Filament\PasskeysPlugin; abstract class PanelProvider extends BasePanelProvider { From 816ad1feb887620cb8fd2e6bce4113c523d6e175 Mon Sep 17 00:00:00 2001 From: JoanFo1456 Date: Sat, 7 Feb 2026 16:26:29 +0100 Subject: [PATCH 08/18] I swear it worked!! --- routes/auth.php | 1 - 1 file changed, 1 deletion(-) diff --git a/routes/auth.php b/routes/auth.php index 16ed0934f5..0406b11bde 100644 --- a/routes/auth.php +++ b/routes/auth.php @@ -9,4 +9,3 @@ Route::get('/redirect/{driver}', [OAuthController::class, 'redirect'])->name('auth.oauth.redirect'); Route::get('/callback/{driver}', [OAuthController::class, 'callback'])->name('auth.oauth.callback')->withoutMiddleware('guest'); }); -Route::passkeys(); From d87aa2dba79179c72d7a7ce1db345f1ddf1feb4f Mon Sep 17 00:00:00 2001 From: JoanFo <161775222+JoanFo1456@users.noreply.github.com> Date: Sat, 7 Feb 2026 16:29:04 +0100 Subject: [PATCH 09/18] Apply suggestion from @lancepioch Co-authored-by: Lance Pioch --- routes/auth.php | 1 + 1 file changed, 1 insertion(+) diff --git a/routes/auth.php b/routes/auth.php index 16ed0934f5..0b8a1efbb1 100644 --- a/routes/auth.php +++ b/routes/auth.php @@ -9,4 +9,5 @@ Route::get('/redirect/{driver}', [OAuthController::class, 'redirect'])->name('auth.oauth.redirect'); Route::get('/callback/{driver}', [OAuthController::class, 'callback'])->name('auth.oauth.callback')->withoutMiddleware('guest'); }); + Route::passkeys(); From 6906381a9adcf60f18c3e972d30065819bbbff83 Mon Sep 17 00:00:00 2001 From: JoanFo1456 Date: Sat, 7 Feb 2026 16:35:06 +0100 Subject: [PATCH 10/18] Lance's suggested changes --- .../migrations/2026_02_07_103629_create_passkeys_table.php | 5 +++++ .../filament-passkeys/filament-passkeys-styles.css | 2 -- .../filament-passkeys/filament-passkeys-scripts.js | 2 -- routes/auth.php | 7 +++++++ 4 files changed, 12 insertions(+), 4 deletions(-) delete mode 100644 public/css/marcelweidum/filament-passkeys/filament-passkeys-styles.css delete mode 100644 public/js/marcelweidum/filament-passkeys/filament-passkeys-scripts.js diff --git a/database/migrations/2026_02_07_103629_create_passkeys_table.php b/database/migrations/2026_02_07_103629_create_passkeys_table.php index 652244b2ea..1b6995d5e8 100644 --- a/database/migrations/2026_02_07_103629_create_passkeys_table.php +++ b/database/migrations/2026_02_07_103629_create_passkeys_table.php @@ -29,4 +29,9 @@ public function up() $table->timestamps(); }); } + + public function down() + { + Schema::dropIfExists('passkeys'); + } }; diff --git a/public/css/marcelweidum/filament-passkeys/filament-passkeys-styles.css b/public/css/marcelweidum/filament-passkeys/filament-passkeys-styles.css deleted file mode 100644 index 8d30ec486d..0000000000 --- a/public/css/marcelweidum/filament-passkeys/filament-passkeys-styles.css +++ /dev/null @@ -1,2 +0,0 @@ -/*! tailwindcss v4.1.11 | MIT License | https://tailwindcss.com */ -@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-font-weight:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-500:oklch(63.7% .237 25.331);--color-gray-400:oklch(70.7% .022 261.325);--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-bold:700;--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.static{position:static}.mt-0{margin-top:calc(var(--spacing)*0)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-4{margin-top:calc(var(--spacing)*4)}.mt-6{margin-top:calc(var(--spacing)*6)}.mr-2{margin-right:calc(var(--spacing)*2)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.ml-auto{margin-left:auto}.contents{display:contents}.flex{display:flex}.inline{display:inline}.w-full{width:100%}.flex-col{flex-direction:column}.items-center{align-items:center}.items-start{align-items:flex-start}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-x-2>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing)*2)*var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-x-reverse)))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-font-weight{syntax:"*";inherits:false} \ No newline at end of file diff --git a/public/js/marcelweidum/filament-passkeys/filament-passkeys-scripts.js b/public/js/marcelweidum/filament-passkeys/filament-passkeys-scripts.js deleted file mode 100644 index 99391ac10f..0000000000 --- a/public/js/marcelweidum/filament-passkeys/filament-passkeys-scripts.js +++ /dev/null @@ -1,2 +0,0 @@ -function l(e){let t=new Uint8Array(e),r="";for(let n of t)r+=String.fromCharCode(n);return btoa(r).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function h(e){let t=e.replace(/-/g,"+").replace(/_/g,"/"),r=(4-t.length%4)%4,i=t.padEnd(t.length+r,"="),n=atob(i),c=new ArrayBuffer(n.length),f=new Uint8Array(c);for(let a=0;ae};function w(e){let{id:t}=e;return{...e,id:h(t),transports:e.transports}}function R(e){return e==="localhost"||/^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/i.test(e)}var o=class extends Error{constructor({message:t,code:r,cause:i,name:n}){super(t,{cause:i}),Object.defineProperty(this,"code",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.name=n??i.name,this.code=r}};function _({error:e,options:t}){let{publicKey:r}=t;if(!r)throw Error("options was missing required publicKey property");if(e.name==="AbortError"){if(t.signal instanceof AbortSignal)return new o({message:"Registration ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:e})}else if(e.name==="ConstraintError"){if(r.authenticatorSelection?.requireResidentKey===!0)return new o({message:"Discoverable credentials were required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT",cause:e});if(t.mediation==="conditional"&&r.authenticatorSelection?.userVerification==="required")return new o({message:"User verification was required during automatic registration but it could not be performed",code:"ERROR_AUTO_REGISTER_USER_VERIFICATION_FAILURE",cause:e});if(r.authenticatorSelection?.userVerification==="required")return new o({message:"User verification was required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT",cause:e})}else{if(e.name==="InvalidStateError")return new o({message:"The authenticator was previously registered",code:"ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED",cause:e});if(e.name==="NotAllowedError")return new o({message:e.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:e});if(e.name==="NotSupportedError")return r.pubKeyCredParams.filter(n=>n.type==="public-key").length===0?new o({message:'No entry in pubKeyCredParams was of type "public-key"',code:"ERROR_MALFORMED_PUBKEYCREDPARAMS",cause:e}):new o({message:"No available authenticator supported any of the specified pubKeyCredParams algorithms",code:"ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG",cause:e});if(e.name==="SecurityError"){let i=globalThis.location.hostname;if(R(i)){if(r.rp.id!==i)return new o({message:`The RP ID "${r.rp.id}" is invalid for this domain`,code:"ERROR_INVALID_RP_ID",cause:e})}else return new o({message:`${globalThis.location.hostname} is an invalid domain`,code:"ERROR_INVALID_DOMAIN",cause:e})}else if(e.name==="TypeError"){if(r.user.id.byteLength<1||r.user.id.byteLength>64)return new o({message:"User ID was not between 1 and 64 characters",code:"ERROR_INVALID_USER_ID_LENGTH",cause:e})}else if(e.name==="UnknownError")return new o({message:"The authenticator was unable to process the specified options, or could not create a new credential",code:"ERROR_AUTHENTICATOR_GENERAL_ERROR",cause:e})}return e}var S=class{constructor(){Object.defineProperty(this,"controller",{enumerable:!0,configurable:!0,writable:!0,value:void 0})}createNewAbortSignal(){if(this.controller){let r=new Error("Cancelling existing WebAuthn API call for new one");r.name="AbortError",this.controller.abort(r)}let t=new AbortController;return this.controller=t,t.signal}cancelCeremony(){if(this.controller){let t=new Error("Manually cancelling existing WebAuthn API call");t.name="AbortError",this.controller.abort(t),this.controller=void 0}}},A=new S;var x=["cross-platform","platform"];function E(e){if(e&&!(x.indexOf(e)<0))return e}async function I(e){!e.optionsJSON&&e.challenge&&(console.warn("startRegistration() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information."),e={optionsJSON:e});let{optionsJSON:t,useAutoRegister:r=!1}=e;if(!p())throw new Error("WebAuthn is not supported in this browser");let i={...t,challenge:h(t.challenge),user:{...t.user,id:h(t.user.id)},excludeCredentials:t.excludeCredentials?.map(w)},n={};r&&(n.mediation="conditional"),n.publicKey=i,n.signal=A.createNewAbortSignal();let c;try{c=await navigator.credentials.create(n)}catch(u){throw _({error:u,options:n})}if(!c)throw new Error("Registration was not completed");let{id:f,rawId:a,response:s,type:y}=c,d;typeof s.getTransports=="function"&&(d=s.getTransports());let g;if(typeof s.getPublicKeyAlgorithm=="function")try{g=s.getPublicKeyAlgorithm()}catch(u){O("getPublicKeyAlgorithm()",u)}let m;if(typeof s.getPublicKey=="function")try{let u=s.getPublicKey();u!==null&&(m=l(u))}catch(u){O("getPublicKey()",u)}let b;if(typeof s.getAuthenticatorData=="function")try{b=l(s.getAuthenticatorData())}catch(u){O("getAuthenticatorData()",u)}return{id:f,rawId:l(a),response:{attestationObject:l(s.attestationObject),clientDataJSON:l(s.clientDataJSON),transports:d,publicKeyAlgorithm:g,publicKey:m,authenticatorData:b},type:y,clientExtensionResults:c.getClientExtensionResults(),authenticatorAttachment:E(c.authenticatorAttachment)}}function O(e,t){console.warn(`The browser extension that intercepted this WebAuthn API call incorrectly implemented ${e}. You should report this error to them. -`,t)}function P(){if(!p())return T.stubThis(new Promise(t=>t(!1)));let e=globalThis.PublicKeyCredential;return e?.isConditionalMediationAvailable===void 0?T.stubThis(new Promise(t=>t(!1))):T.stubThis(e.isConditionalMediationAvailable())}var T={stubThis:e=>e};function C({error:e,options:t}){let{publicKey:r}=t;if(!r)throw Error("options was missing required publicKey property");if(e.name==="AbortError"){if(t.signal instanceof AbortSignal)return new o({message:"Authentication ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:e})}else{if(e.name==="NotAllowedError")return new o({message:e.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:e});if(e.name==="SecurityError"){let i=globalThis.location.hostname;if(R(i)){if(r.rpId!==i)return new o({message:`The RP ID "${r.rpId}" is invalid for this domain`,code:"ERROR_INVALID_RP_ID",cause:e})}else return new o({message:`${globalThis.location.hostname} is an invalid domain`,code:"ERROR_INVALID_DOMAIN",cause:e})}else if(e.name==="UnknownError")return new o({message:"The authenticator was unable to process the specified options, or could not create a new assertion signature",code:"ERROR_AUTHENTICATOR_GENERAL_ERROR",cause:e})}return e}async function N(e){!e.optionsJSON&&e.challenge&&(console.warn("startAuthentication() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information."),e={optionsJSON:e});let{optionsJSON:t,useBrowserAutofill:r=!1,verifyBrowserAutofillInput:i=!0}=e;if(!p())throw new Error("WebAuthn is not supported in this browser");let n;t.allowCredentials?.length!==0&&(n=t.allowCredentials?.map(w));let c={...t,challenge:h(t.challenge),allowCredentials:n},f={};if(r){if(!await P())throw Error("Browser does not support WebAuthn autofill");if(document.querySelectorAll("input[autocomplete$='webauthn']").length<1&&i)throw Error('No with "webauthn" as the only or last value in its `autocomplete` attribute was detected');f.mediation="conditional",c.allowCredentials=[]}f.publicKey=c,f.signal=A.createNewAbortSignal();let a;try{a=await navigator.credentials.get(f)}catch(b){throw C({error:b,options:f})}if(!a)throw new Error("Authentication was not completed");let{id:s,rawId:y,response:d,type:g}=a,m;return d.userHandle&&(m=l(d.userHandle)),{id:s,rawId:l(y),response:{authenticatorData:l(d.authenticatorData),clientDataJSON:l(d.clientDataJSON),signature:l(d.signature),userHandle:m},type:g,clientExtensionResults:a.getClientExtensionResults(),authenticatorAttachment:E(a.authenticatorAttachment)}}window.browserSupportsWebAuthn=p;window.startAuthentication=N;window.startRegistration=I; diff --git a/routes/auth.php b/routes/auth.php index 0406b11bde..57841346b6 100644 --- a/routes/auth.php +++ b/routes/auth.php @@ -2,6 +2,8 @@ use App\Http\Controllers\Auth\OAuthController; use Illuminate\Support\Facades\Route; +use Spatie\LaravelPasskeys\Http\Controllers\AuthenticateUsingPasskeyController; +use Spatie\LaravelPasskeys\Http\Controllers\GeneratePasskeyAuthenticationOptionsController; Route::redirect('/login', '/login')->name('auth.login'); @@ -9,3 +11,8 @@ Route::get('/redirect/{driver}', [OAuthController::class, 'redirect'])->name('auth.oauth.redirect'); Route::get('/callback/{driver}', [OAuthController::class, 'callback'])->name('auth.oauth.callback')->withoutMiddleware('guest'); }); + +Route::prefix('auth/passkeys')->group(function () { + Route::get('/authentication-options', GeneratePasskeyAuthenticationOptionsController::class)->name('passkeys.authentication_options'); + Route::post('/authenticate', AuthenticateUsingPasskeyController::class)->name('passkeys.login'); +}); From c57a54fa374a9c1d26c542ab0d236fe0675be796 Mon Sep 17 00:00:00 2001 From: JoanFo1456 Date: Sat, 7 Feb 2026 17:19:25 +0100 Subject: [PATCH 11/18] Added translation --- app/Filament/Pages/Auth/EditProfile.php | 6 +++--- lang/en/profile.php | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/Filament/Pages/Auth/EditProfile.php b/app/Filament/Pages/Auth/EditProfile.php index 1b4fa904c8..28b2288c11 100644 --- a/app/Filament/Pages/Auth/EditProfile.php +++ b/app/Filament/Pages/Auth/EditProfile.php @@ -235,11 +235,11 @@ protected function getDefaultTabs(): array ->statePath($multiFactorAuthenticationProvider->getId())) ->all()), Tab::make('passkeys') - ->label(trans('passkeys.passkeys')) + ->label(trans('profile.tabs.passkeys')) ->icon(TablerIcon::Fingerprint) ->schema([ - Section::make(trans('passkeys.passkeys')) - ->description(trans('passkeys.description')) + Section::make(trans('profile.tabs.passkeys')) + ->description(trans('profile.passkeys_description')) ->schema([ Group::make([ view('passkeys.livewire.passkeys-tab'), diff --git a/lang/en/profile.php b/lang/en/profile.php index f6a6095c17..ec549b1864 100644 --- a/lang/en/profile.php +++ b/lang/en/profile.php @@ -11,6 +11,7 @@ 'keys' => 'Keys', '2fa' => '2FA', 'customization' => 'Customization', + 'passkeys' => 'Passkeys', ], 'username' => 'Username', 'admin' => 'Admin', @@ -67,4 +68,5 @@ 'no_oauth' => 'No Accounts Linked', 'no_api_keys' => 'No API Keys', 'no_ssh_keys' => 'No SSH Keys', + 'passkeys_description' => 'Passkeys let you log in without needing a password. Instead of a password, you can generate a passkey which will be stored in 1Pass, MacOS password app, or alternative app on your favourite OS.', ]; From 378c4ddd4df79b9b1e19c7502ce698ac8fb5fb7e Mon Sep 17 00:00:00 2001 From: JoanFo1456 <161775222+JoanFo1456@users.noreply.github.com> Date: Sat, 7 Feb 2026 21:33:01 +0000 Subject: [PATCH 12/18] Composer should work now... --- composer.json | 1 + composer.lock | 924 +++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 849 insertions(+), 76 deletions(-) diff --git a/composer.json b/composer.json index b29ac9b5f8..c2bccf5cf8 100644 --- a/composer.json +++ b/composer.json @@ -35,6 +35,7 @@ "spatie/laravel-data": "^4.19", "spatie/laravel-fractal": "^6.3", "spatie/laravel-health": "^1.34", + "spatie/laravel-passkeys": "^1.5", "spatie/laravel-permission": "^6.24", "spatie/laravel-query-builder": "^6.4", "spatie/temporary-directory": "^2.3", diff --git a/composer.lock b/composer.lock index b0cb04d2e3..5d44908d77 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "15f89930db77693b2d692dbadf22fb9f", + "content-hash": "fe7b314eca9ee093ebf78c54c7c91942", "packages": [ { "name": "anourvalar/eloquent-serialize", @@ -7809,6 +7809,84 @@ ], "time": "2025-07-17T15:46:43+00:00" }, + { + "name": "spatie/laravel-passkeys", + "version": "1.5.3", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-passkeys.git", + "reference": "641217418497ffa9fdb6c2f5f67a1332b58a6012" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-passkeys/zipball/641217418497ffa9fdb6c2f5f67a1332b58a6012", + "reference": "641217418497ffa9fdb6c2f5f67a1332b58a6012", + "shasum": "" + }, + "require": { + "illuminate/contracts": "^11.0|^12.0", + "php": "^8.2|^8.3|^8.4", + "spatie/laravel-package-tools": "^1.16", + "web-auth/webauthn-lib": "^5.0" + }, + "require-dev": { + "larastan/larastan": "^3.4", + "laravel/pint": "^1.14", + "livewire/livewire": "^3.5", + "nunomaduro/collision": "^8.1.1", + "orchestra/testbench": "^10.0", + "pestphp/pest": "^3.0", + "pestphp/pest-plugin-arch": "^3.0", + "pestphp/pest-plugin-laravel": "^3.0", + "phpstan/extension-installer": "^1.3", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "spatie/laravel-ray": "^1.35" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\LaravelPasskeys\\LaravelPasskeysServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\LaravelPasskeys\\": "src/", + "Spatie\\LaravelPasskeys\\Database\\Factories\\": "database/factories/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "role": "Developer" + } + ], + "description": "Use passkeys in your Laravel app", + "homepage": "https://github.com/spatie/laravel-passkeys", + "keywords": [ + "laravel", + "laravel-passkeys", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-passkeys/issues", + "source": "https://github.com/spatie/laravel-passkeys/tree/1.5.3" + }, + "funding": [ + { + "url": "https://github.com/Spatie", + "type": "github" + } + ], + "time": "2026-01-12T08:33:46+00:00" + }, { "name": "spatie/laravel-permission", "version": "6.24.0", @@ -8236,6 +8314,186 @@ ], "time": "2026-01-12T07:42:22+00:00" }, + { + "name": "spomky-labs/cbor-php", + "version": "3.2.2", + "source": { + "type": "git", + "url": "https://github.com/Spomky-Labs/cbor-php.git", + "reference": "2a5fb86aacfe1004611370ead6caa2bfc88435d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/2a5fb86aacfe1004611370ead6caa2bfc88435d0", + "reference": "2a5fb86aacfe1004611370ead6caa2bfc88435d0", + "shasum": "" + }, + "require": { + "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14", + "ext-mbstring": "*", + "php": ">=8.0" + }, + "require-dev": { + "ext-json": "*", + "roave/security-advisories": "dev-latest", + "symfony/error-handler": "^6.4|^7.1|^8.0", + "symfony/var-dumper": "^6.4|^7.1|^8.0" + }, + "suggest": { + "ext-bcmath": "GMP or BCMath extensions will drastically improve the library performance. BCMath extension needed to handle the Big Float and Decimal Fraction Tags", + "ext-gmp": "GMP or BCMath extensions will drastically improve the library performance" + }, + "type": "library", + "autoload": { + "psr-4": { + "CBOR\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/Spomky-Labs/cbor-php/contributors" + } + ], + "description": "CBOR Encoder/Decoder for PHP", + "keywords": [ + "Concise Binary Object Representation", + "RFC7049", + "cbor" + ], + "support": { + "issues": "https://github.com/Spomky-Labs/cbor-php/issues", + "source": "https://github.com/Spomky-Labs/cbor-php/tree/3.2.2" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2025-11-13T13:00:34+00:00" + }, + { + "name": "spomky-labs/pki-framework", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/Spomky-Labs/pki-framework.git", + "reference": "f0e9a548df4e3942886adc9b7830581a46334631" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/f0e9a548df4e3942886adc9b7830581a46334631", + "reference": "f0e9a548df4e3942886adc9b7830581a46334631", + "shasum": "" + }, + "require": { + "brick/math": "^0.10|^0.11|^0.12|^0.13|^0.14", + "ext-mbstring": "*", + "php": ">=8.1" + }, + "require-dev": { + "ekino/phpstan-banned-code": "^1.0|^2.0|^3.0", + "ext-gmp": "*", + "ext-openssl": "*", + "infection/infection": "^0.28|^0.29|^0.31", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpstan/extension-installer": "^1.3|^2.0", + "phpstan/phpstan": "^1.8|^2.0", + "phpstan/phpstan-deprecation-rules": "^1.0|^2.0", + "phpstan/phpstan-phpunit": "^1.1|^2.0", + "phpstan/phpstan-strict-rules": "^1.3|^2.0", + "phpunit/phpunit": "^10.1|^11.0|^12.0", + "rector/rector": "^1.0|^2.0", + "roave/security-advisories": "dev-latest", + "symfony/string": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0", + "symplify/easy-coding-standard": "^12.0" + }, + "suggest": { + "ext-bcmath": "For better performance (or GMP)", + "ext-gmp": "For better performance (or BCMath)", + "ext-openssl": "For OpenSSL based cyphering" + }, + "type": "library", + "autoload": { + "psr-4": { + "SpomkyLabs\\Pki\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Joni Eskelinen", + "email": "jonieske@gmail.com", + "role": "Original developer" + }, + { + "name": "Florent Morselli", + "email": "florent.morselli@spomky-labs.com", + "role": "Spomky-Labs PKI Framework developer" + } + ], + "description": "A PHP framework for managing Public Key Infrastructures. It comprises X.509 public key certificates, attribute certificates, certification requests and certification path validation.", + "homepage": "https://github.com/spomky-labs/pki-framework", + "keywords": [ + "DER", + "Private Key", + "ac", + "algorithm identifier", + "asn.1", + "asn1", + "attribute certificate", + "certificate", + "certification request", + "cryptography", + "csr", + "decrypt", + "ec", + "encrypt", + "pem", + "pkcs", + "public key", + "rsa", + "sign", + "signature", + "verify", + "x.509", + "x.690", + "x509", + "x690" + ], + "support": { + "issues": "https://github.com/Spomky-Labs/pki-framework/issues", + "source": "https://github.com/Spomky-Labs/pki-framework/tree/1.4.1" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2025-12-20T12:57:40+00:00" + }, { "name": "symfony/clock", "version": "v7.4.0", @@ -10598,40 +10856,31 @@ "time": "2026-01-26T15:07:59+00:00" }, { - "name": "symfony/routing", + "name": "symfony/property-access", "version": "v7.4.4", "source": { "type": "git", - "url": "https://github.com/symfony/routing.git", - "reference": "0798827fe2c79caeed41d70b680c2c3507d10147" + "url": "https://github.com/symfony/property-access.git", + "reference": "fa49bf1ca8fce1ba0e2dba4e4658554cfb9364b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/0798827fe2c79caeed41d70b680c2c3507d10147", - "reference": "0798827fe2c79caeed41d70b680c2c3507d10147", + "url": "https://api.github.com/repos/symfony/property-access/zipball/fa49bf1ca8fce1ba0e2dba4e4658554cfb9364b1", + "reference": "fa49bf1ca8fce1ba0e2dba4e4658554cfb9364b1", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/config": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/yaml": "<6.4" + "symfony/property-info": "^6.4.32|~7.3.10|^7.4.4|^8.0.4" }, "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/http-foundation": "^6.4|^7.0|^8.0", - "symfony/yaml": "^6.4|^7.0|^8.0" + "symfony/cache": "^6.4|^7.0|^8.0", + "symfony/var-exporter": "^6.4.1|^7.0.1|^8.0" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Routing\\": "" + "Symfony\\Component\\PropertyAccess\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -10651,16 +10900,21 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Maps an HTTP request to a set of configuration variables", + "description": "Provides functions to read and write from/to an object or array using a simple string notation", "homepage": "https://symfony.com", "keywords": [ - "router", - "routing", - "uri", - "url" + "access", + "array", + "extraction", + "index", + "injection", + "object", + "property", + "property-path", + "reflection" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.4.4" + "source": "https://github.com/symfony/property-access/tree/v7.4.4" }, "funding": [ { @@ -10680,46 +10934,49 @@ "type": "tidelift" } ], - "time": "2026-01-12T12:19:02+00:00" + "time": "2026-01-05T08:47:25+00:00" }, { - "name": "symfony/service-contracts", - "version": "v3.6.1", + "name": "symfony/property-info", + "version": "v7.4.5", "source": { "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" + "url": "https://github.com/symfony/property-info.git", + "reference": "1c9d326bd69602561e2ea467a16c09b5972eee21" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", + "url": "https://api.github.com/repos/symfony/property-info/zipball/1c9d326bd69602561e2ea467a16c09b5972eee21", + "reference": "1c9d326bd69602561e2ea467a16c09b5972eee21", "shasum": "" }, "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/string": "^6.4|^7.0|^8.0", + "symfony/type-info": "~7.3.10|^7.4.4|^8.0.4" }, "conflict": { - "ext-psr": "<1.1|>=2" + "phpdocumentor/reflection-docblock": "<5.2|>=6", + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/cache": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/serializer": "<6.4" }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.6-dev" - } + "require-dev": { + "phpdocumentor/reflection-docblock": "^5.2", + "phpstan/phpdoc-parser": "^1.0|^2.0", + "symfony/cache": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4|^7.0|^8.0" }, + "type": "library", "autoload": { "psr-4": { - "Symfony\\Contracts\\Service\\": "" + "Symfony\\Component\\PropertyInfo\\": "" }, "exclude-from-classmap": [ - "/Test/" + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -10728,26 +10985,26 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Generic abstractions related to writing services", + "description": "Extracts information about PHP class' properties using metadata of popular sources", "homepage": "https://symfony.com", "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" + "doctrine", + "phpdoc", + "property", + "symfony", + "type", + "validator" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" + "source": "https://github.com/symfony/property-info/tree/v7.4.5" }, "funding": [ { @@ -10767,41 +11024,316 @@ "type": "tidelift" } ], - "time": "2025-07-15T11:30:57+00:00" + "time": "2026-01-27T16:16:02+00:00" }, { - "name": "symfony/string", + "name": "symfony/routing", "version": "v7.4.4", "source": { "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "1c4b10461bf2ec27537b5f36105337262f5f5d6f" + "url": "https://github.com/symfony/routing.git", + "reference": "0798827fe2c79caeed41d70b680c2c3507d10147" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/1c4b10461bf2ec27537b5f36105337262f5f5d6f", - "reference": "1c4b10461bf2ec27537b5f36105337262f5f5d6f", + "url": "https://api.github.com/repos/symfony/routing/zipball/0798827fe2c79caeed41d70b680c2c3507d10147", + "reference": "0798827fe2c79caeed41d70b680c2c3507d10147", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3.0", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.33", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { - "symfony/translation-contracts": "<2.5" + "symfony/config": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/yaml": "<6.4" }, "require-dev": { - "symfony/emoji": "^7.1|^8.0", - "symfony/http-client": "^6.4|^7.0|^8.0", - "symfony/intl": "^6.4|^7.0|^8.0", - "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.4|^7.0|^8.0" - }, - "type": "library", + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Maps an HTTP request to a set of configuration variables", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "support": { + "source": "https://github.com/symfony/routing/tree/v7.4.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-01-12T12:19:02+00:00" + }, + { + "name": "symfony/serializer", + "version": "v7.4.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/serializer.git", + "reference": "480cd1237c98ab1219c20945b92c9d4480a44f47" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/serializer/zipball/480cd1237c98ab1219c20945b92c9d4480a44f47", + "reference": "480cd1237c98ab1219c20945b92c9d4480a44f47", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php84": "^1.30" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "<5.2|>=6", + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/dependency-injection": "<6.4", + "symfony/property-access": "<6.4", + "symfony/property-info": "<6.4", + "symfony/uid": "<6.4", + "symfony/validator": "<6.4", + "symfony/yaml": "<6.4" + }, + "require-dev": { + "phpdocumentor/reflection-docblock": "^5.2", + "phpstan/phpdoc-parser": "^1.0|^2.0", + "seld/jsonlint": "^1.10", + "symfony/cache": "^6.4|^7.0|^8.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^7.2|^8.0", + "symfony/error-handler": "^6.4|^7.0|^8.0", + "symfony/filesystem": "^6.4|^7.0|^8.0", + "symfony/form": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/mime": "^6.4|^7.0|^8.0", + "symfony/property-access": "^6.4|^7.0|^8.0", + "symfony/property-info": "^6.4|^7.0|^8.0", + "symfony/translation-contracts": "^2.5|^3", + "symfony/type-info": "^7.1.8|^8.0", + "symfony/uid": "^6.4|^7.0|^8.0", + "symfony/validator": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0", + "symfony/var-exporter": "^6.4|^7.0|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Serializer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/serializer/tree/v7.4.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-01-27T08:59:58+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.6.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-15T11:30:57+00:00" + }, + { + "name": "symfony/string", + "version": "v7.4.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "1c4b10461bf2ec27537b5f36105337262f5f5d6f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/1c4b10461bf2ec27537b5f36105337262f5f5d6f", + "reference": "1c4b10461bf2ec27537b5f36105337262f5f5d6f", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.33", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/emoji": "^7.1|^8.0", + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/intl": "^6.4|^7.0|^8.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0|^8.0" + }, + "type": "library", "autoload": { "files": [ "Resources/functions.php" @@ -11042,6 +11574,89 @@ ], "time": "2025-07-15T13:41:35+00:00" }, + { + "name": "symfony/type-info", + "version": "v7.4.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/type-info.git", + "reference": "f83c725e72b39b2704b9d6fc85070ad6ac7a5889" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/type-info/zipball/f83c725e72b39b2704b9d6fc85070ad6ac7a5889", + "reference": "f83c725e72b39b2704b9d6fc85070ad6ac7a5889", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "phpstan/phpdoc-parser": "<1.30" + }, + "require-dev": { + "phpstan/phpdoc-parser": "^1.30|^2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\TypeInfo\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mathias Arlaud", + "email": "mathias.arlaud@gmail.com" + }, + { + "name": "Baptiste LEDUC", + "email": "baptiste.leduc@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Extracts PHP types information.", + "homepage": "https://symfony.com", + "keywords": [ + "PHPStan", + "phpdoc", + "symfony", + "type" + ], + "support": { + "source": "https://github.com/symfony/type-info/tree/v7.4.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-01-09T12:14:21+00:00" + }, { "name": "symfony/uid", "version": "v7.4.4", @@ -11565,6 +12180,163 @@ ], "time": "2024-11-21T01:49:47+00:00" }, + { + "name": "web-auth/cose-lib", + "version": "4.5.0", + "source": { + "type": "git", + "url": "https://github.com/web-auth/cose-lib.git", + "reference": "5adac6fe126994a3ee17ed9950efb4947ab132a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/5adac6fe126994a3ee17ed9950efb4947ab132a9", + "reference": "5adac6fe126994a3ee17ed9950efb4947ab132a9", + "shasum": "" + }, + "require": { + "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14", + "ext-json": "*", + "ext-openssl": "*", + "php": ">=8.1", + "spomky-labs/pki-framework": "^1.0" + }, + "require-dev": { + "spomky-labs/cbor-php": "^3.2.2" + }, + "suggest": { + "ext-bcmath": "For better performance, please install either GMP (recommended) or BCMath extension", + "ext-gmp": "For better performance, please install either GMP (recommended) or BCMath extension", + "spomky-labs/cbor-php": "For COSE Signature support" + }, + "type": "library", + "autoload": { + "psr-4": { + "Cose\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-auth/cose/contributors" + } + ], + "description": "CBOR Object Signing and Encryption (COSE) For PHP", + "homepage": "https://github.com/web-auth", + "keywords": [ + "COSE", + "RFC8152" + ], + "support": { + "issues": "https://github.com/web-auth/cose-lib/issues", + "source": "https://github.com/web-auth/cose-lib/tree/4.5.0" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2026-01-03T14:43:18+00:00" + }, + { + "name": "web-auth/webauthn-lib", + "version": "5.2.3", + "source": { + "type": "git", + "url": "https://github.com/web-auth/webauthn-lib.git", + "reference": "8782f575032fedc36e2eb27c39c736054e2b6867" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/web-auth/webauthn-lib/zipball/8782f575032fedc36e2eb27c39c736054e2b6867", + "reference": "8782f575032fedc36e2eb27c39c736054e2b6867", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-openssl": "*", + "paragonie/constant_time_encoding": "^2.6|^3.0", + "php": ">=8.2", + "phpdocumentor/reflection-docblock": "^5.3", + "psr/clock": "^1.0", + "psr/event-dispatcher": "^1.0", + "psr/log": "^1.0|^2.0|^3.0", + "spomky-labs/cbor-php": "^3.0", + "spomky-labs/pki-framework": "^1.0", + "symfony/clock": "^6.4|^7.0", + "symfony/deprecation-contracts": "^3.2", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", + "web-auth/cose-lib": "^4.2.3" + }, + "suggest": { + "psr/log-implementation": "Recommended to receive logs from the library", + "symfony/event-dispatcher": "Recommended to use dispatched events", + "web-token/jwt-library": "Mandatory for fetching Metadata Statement from distant sources" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/web-auth/webauthn-framework", + "name": "web-auth/webauthn-framework" + } + }, + "autoload": { + "psr-4": { + "Webauthn\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-auth/webauthn-library/contributors" + } + ], + "description": "FIDO2/Webauthn Support For PHP", + "homepage": "https://github.com/web-auth", + "keywords": [ + "FIDO2", + "fido", + "webauthn" + ], + "support": { + "source": "https://github.com/web-auth/webauthn-lib/tree/5.2.3" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2025-12-20T10:54:02+00:00" + }, { "name": "webmozart/assert", "version": "1.11.0", From 33792a1b2643a0b630f2080877a7f4f3d0525f2d Mon Sep 17 00:00:00 2001 From: JoanFo1456 <161775222+JoanFo1456@users.noreply.github.com> Date: Sat, 7 Feb 2026 21:41:22 +0000 Subject: [PATCH 13/18] This should shut phpstan... --- app/Services/Activity/ActivityLogService.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/Services/Activity/ActivityLogService.php b/app/Services/Activity/ActivityLogService.php index 9cf8e2d1ef..2a06427fc4 100644 --- a/app/Services/Activity/ActivityLogService.php +++ b/app/Services/Activity/ActivityLogService.php @@ -10,7 +10,6 @@ use Illuminate\Contracts\Auth\Factory as AuthFactory; use Illuminate\Database\ConnectionInterface; use Illuminate\Database\Eloquent\Model; -use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Request; use Throwable; @@ -71,7 +70,7 @@ public function description(?string $description): self */ public function subject(...$subjects): self { - foreach (Arr::wrap($subjects) as $subject) { + foreach ($subjects as $subject) { if (is_null($subject)) { continue; } From a2704f78b8be9c14d7709f7be0a798b2dfd810d1 Mon Sep 17 00:00:00 2001 From: JoanFo1456 <161775222+JoanFo1456@users.noreply.github.com> Date: Sat, 7 Feb 2026 23:51:58 +0000 Subject: [PATCH 14/18] Rabbit suggestions ig. --- app/Filament/Pages/Auth/EditProfile.php | 2 +- app/Filament/PasskeysPlugin.php | 1 - app/Livewire/Passkeys.php | 4 +++- lang/en/passkeys.php | 24 +++++++++---------- lang/en/profile.php | 1 - .../livewire/partials/createScript.blade.php | 11 +++++++++ .../passkeys/livewire/passkeys.blade.php | 2 +- 7 files changed, 28 insertions(+), 17 deletions(-) create mode 100644 resources/views/passkeys/livewire/partials/createScript.blade.php diff --git a/app/Filament/Pages/Auth/EditProfile.php b/app/Filament/Pages/Auth/EditProfile.php index 5b81692510..16923c7d6a 100644 --- a/app/Filament/Pages/Auth/EditProfile.php +++ b/app/Filament/Pages/Auth/EditProfile.php @@ -239,7 +239,7 @@ protected function getDefaultTabs(): array ->icon(TablerIcon::Fingerprint) ->schema([ Section::make(trans('profile.tabs.passkeys')) - ->description(trans('profile.passkeys_description')) + ->description(trans('passkeys.description')) ->schema([ Group::make([ view('passkeys.livewire.passkeys-tab'), diff --git a/app/Filament/PasskeysPlugin.php b/app/Filament/PasskeysPlugin.php index 7f4f4bcb1f..e96817fcc4 100644 --- a/app/Filament/PasskeysPlugin.php +++ b/app/Filament/PasskeysPlugin.php @@ -46,6 +46,5 @@ public function boot(Panel $panel): void fn (): View => view('passkeys.login'), ); - Livewire::component('filament-passkeys', Passkeys::class); } } diff --git a/app/Livewire/Passkeys.php b/app/Livewire/Passkeys.php index f24cf5450a..b2693737d4 100644 --- a/app/Livewire/Passkeys.php +++ b/app/Livewire/Passkeys.php @@ -29,11 +29,13 @@ public function deleteAction(): Action ->label(__('passkeys.delete')) ->color('danger') ->requiresConfirmation() - ->action(fn (array $arguments) => $this->deletePasskey($arguments['passkey'])); + ->action(fn (array $arguments) => $this->deletePasskey((int) $arguments['passkey'])); } public function deletePasskey(int $passkeyId): void { + $this->currentUser()->passkeys()->findOrFail($passkeyId); + parent::deletePasskey($passkeyId); Notification::make() diff --git a/lang/en/passkeys.php b/lang/en/passkeys.php index 975421434c..73bd6373c9 100644 --- a/lang/en/passkeys.php +++ b/lang/en/passkeys.php @@ -3,18 +3,18 @@ declare(strict_types=1); return [ - 'authenticate_using_passkey' => __('passkeys::passkeys.authenticate_using_passkey'), - 'create' => __('passkeys::passkeys.create'), - 'delete' => __('passkeys::passkeys.delete'), - 'error_something_went_wrong_generating_the_passkey' => __('passkeys::passkeys.error_something_went_wrong_generating_the_passkey'), - 'invalid' => __('passkeys::passkeys.invalid'), - 'last_used' => __('passkeys::passkeys.last_used'), - 'name' => __('passkeys::passkeys.name'), - 'name_placeholder' => __('passkeys::passkeys.name_placeholder'), - 'no_passkeys_registered' => __('passkeys::passkeys.no_passkeys_registered'), - 'not_used_yet' => __('passkeys::passkeys.not_used_yet'), - 'passkeys' => __('passkeys::passkeys.passkeys'), - 'description' => 'Passkeys let you log in without needing a password. Instead of a password, you can generate a passkey which will be stored in 1Pass, MacOS\' password app, or alternative app on your favourite OS.', + 'authenticate_using_passkey' => 'Authenticate using a passkey', + 'create' => 'Create', + 'delete' => 'Delete', + 'error_something_went_wrong_generating_the_passkey' => 'Something went wrong generating the passkey', + 'invalid' => 'Invalid passkey', + 'last_used' => 'Last used', + 'name' => 'Name', + 'name_placeholder' => 'My passkey', + 'no_passkeys_registered' => 'No passkeys registered', + 'not_used_yet' => 'Not used yet', + 'passkeys' => 'Passkeys', + 'description' => 'Passkeys let you log in without needing a password. Instead of a password, you can generate a passkey which will be stored in 1Password, macOS password app, or alternative app on your favourite OS.', 'created_notification_title' => 'Your passkey has been created', 'deleted_notification_title' => 'Your passkey has been deleted', ]; diff --git a/lang/en/profile.php b/lang/en/profile.php index 5d8b57fa0c..f23b199896 100644 --- a/lang/en/profile.php +++ b/lang/en/profile.php @@ -70,5 +70,4 @@ 'no_oauth' => 'No Accounts Linked', 'no_api_keys' => 'No API Keys', 'no_ssh_keys' => 'No SSH Keys', - 'passkeys_description' => 'Passkeys let you log in without needing a password. Instead of a password, you can generate a passkey which will be stored in 1Pass, MacOS password app, or alternative app on your favourite OS.', ]; diff --git a/resources/views/passkeys/livewire/partials/createScript.blade.php b/resources/views/passkeys/livewire/partials/createScript.blade.php new file mode 100644 index 0000000000..4d5a17bb9e --- /dev/null +++ b/resources/views/passkeys/livewire/partials/createScript.blade.php @@ -0,0 +1,11 @@ +@script + +@endscript diff --git a/resources/views/passkeys/livewire/passkeys.blade.php b/resources/views/passkeys/livewire/passkeys.blade.php index bf1e7cad8c..e3a12b7ace 100644 --- a/resources/views/passkeys/livewire/passkeys.blade.php +++ b/resources/views/passkeys/livewire/passkeys.blade.php @@ -48,4 +48,4 @@ -@include('passkeys::livewire.partials.createScript') +@include('passkeys.livewire.partials.createScript') From e16a3d89ebd1e9eae1ee1ceff95fe58a6782f377 Mon Sep 17 00:00:00 2001 From: JoanFo1456 <161775222+JoanFo1456@users.noreply.github.com> Date: Sat, 7 Feb 2026 23:55:11 +0000 Subject: [PATCH 15/18] Pint... --- app/Filament/PasskeysPlugin.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/Filament/PasskeysPlugin.php b/app/Filament/PasskeysPlugin.php index e96817fcc4..4c4ec3b6c6 100644 --- a/app/Filament/PasskeysPlugin.php +++ b/app/Filament/PasskeysPlugin.php @@ -4,13 +4,11 @@ namespace App\Filament; -use App\Livewire\Passkeys; use Filament\Contracts\Plugin; use Filament\Panel; use Filament\Support\Facades\FilamentView; use Filament\View\PanelsRenderHook; use Illuminate\View\View; -use Livewire\Livewire; final class PasskeysPlugin implements Plugin { From 0c47ec2e2e0dcc82dc897fc553f64a1a51de3440 Mon Sep 17 00:00:00 2001 From: JoanFo1456 <161775222+JoanFo1456@users.noreply.github.com> Date: Sun, 8 Feb 2026 16:28:19 +0000 Subject: [PATCH 16/18] Use trans() --- app/Livewire/Passkeys.php | 6 +++--- resources/views/passkeys/livewire/passkeys.blade.php | 12 ++++++------ resources/views/passkeys/login.blade.php | 2 +- resources/views/passkeys/profile.blade.php | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/Livewire/Passkeys.php b/app/Livewire/Passkeys.php index b2693737d4..1b1479cc61 100644 --- a/app/Livewire/Passkeys.php +++ b/app/Livewire/Passkeys.php @@ -26,7 +26,7 @@ public function confirmDelete(int $passkeyId): void public function deleteAction(): Action { return Action::make('deleteAction') - ->label(__('passkeys.delete')) + ->label(trans('passkeys.delete')) ->color('danger') ->requiresConfirmation() ->action(fn (array $arguments) => $this->deletePasskey((int) $arguments['passkey'])); @@ -39,7 +39,7 @@ public function deletePasskey(int $passkeyId): void parent::deletePasskey($passkeyId); Notification::make() - ->title(__('passkeys.deleted_notification_title')) + ->title(trans('passkeys.deleted_notification_title')) ->success() ->send(); } @@ -49,7 +49,7 @@ public function storePasskey(string $passkey): void parent::storePasskey($passkey); Notification::make() - ->title(__('passkeys.created_notification_title')) + ->title(trans('passkeys.created_notification_title')) ->success() ->send(); } diff --git a/resources/views/passkeys/livewire/passkeys.blade.php b/resources/views/passkeys/livewire/passkeys.blade.php index e3a12b7ace..d7a0a12862 100644 --- a/resources/views/passkeys/livewire/passkeys.blade.php +++ b/resources/views/passkeys/livewire/passkeys.blade.php @@ -1,11 +1,11 @@
- + @@ -15,20 +15,20 @@
- {{ __('passkeys.create') }} + {{ trans('passkeys.create') }}
@if($passkeys->isNotEmpty())
- {{ __('passkeys.passkeys') }} + {{ trans('passkeys.passkeys') }}
    @foreach($passkeys as $passkey)
    {{ $passkey->name }} - {{ __('passkeys.last_used') }}: {{ $passkey->last_used_at?->diffForHumans() ?? __('passkeys.not_used_yet') }} + {{ trans('passkeys.last_used') }}: {{ $passkey->last_used_at?->diffForHumans() ?? trans('passkeys.not_used_yet') }}
    - {{ __('passkeys.delete') }} + {{ trans('passkeys.delete') }}
    diff --git a/resources/views/passkeys/login.blade.php b/resources/views/passkeys/login.blade.php index df13aa8c3c..5716f7094d 100644 --- a/resources/views/passkeys/login.blade.php +++ b/resources/views/passkeys/login.blade.php @@ -1,5 +1,5 @@ @include('passkeys.components.authenticate') - {{ __('passkeys.authenticate_using_passkey') }} + {{ trans('passkeys.authenticate_using_passkey') }} diff --git a/resources/views/passkeys/profile.blade.php b/resources/views/passkeys/profile.blade.php index 2a7cd479df..7ea7decf0f 100644 --- a/resources/views/passkeys/profile.blade.php +++ b/resources/views/passkeys/profile.blade.php @@ -1,10 +1,10 @@ - {{ __('passkeys.passkeys') }} + {{ trans('passkeys.passkeys') }} - {{ __('passkeys.description') }} + {{ trans('passkeys.description') }} From 5029e5767cf7a9036a524287208507cd222d56dc Mon Sep 17 00:00:00 2001 From: JoanFo1456 <161775222+JoanFo1456@users.noreply.github.com> Date: Sun, 8 Feb 2026 17:00:13 +0000 Subject: [PATCH 17/18] Goodbye plugin --- app/Filament/PasskeysPlugin.php | 48 ------------------- .../Filament/FilamentServiceProvider.php | 5 ++ app/Providers/Filament/PanelProvider.php | 4 -- 3 files changed, 5 insertions(+), 52 deletions(-) delete mode 100644 app/Filament/PasskeysPlugin.php diff --git a/app/Filament/PasskeysPlugin.php b/app/Filament/PasskeysPlugin.php deleted file mode 100644 index 4c4ec3b6c6..0000000000 --- a/app/Filament/PasskeysPlugin.php +++ /dev/null @@ -1,48 +0,0 @@ -getId()); - - return $plugin; - } - - public function getId(): string - { - return 'filament-passkeys'; - } - - public function register(Panel $panel): void - { - // - } - - public function boot(Panel $panel): void - { - FilamentView::registerRenderHook( - PanelsRenderHook::AUTH_LOGIN_FORM_AFTER, - fn (): View => view('passkeys.login'), - ); - - } -} diff --git a/app/Providers/Filament/FilamentServiceProvider.php b/app/Providers/Filament/FilamentServiceProvider.php index a3934d4133..d3377865d9 100644 --- a/app/Providers/Filament/FilamentServiceProvider.php +++ b/app/Providers/Filament/FilamentServiceProvider.php @@ -65,6 +65,11 @@ public function boot(): void fn () => Blade::render('filament.layouts.footer'), ); + FilamentView::registerRenderHook( + PanelsRenderHook::AUTH_LOGIN_FORM_AFTER, + fn () => view('passkeys.login'), + ); + FilamentView::registerRenderHook( PanelsRenderHook::STYLES_BEFORE, fn () => Blade::render("@vite(['resources/css/app.css'])") diff --git a/app/Providers/Filament/PanelProvider.php b/app/Providers/Filament/PanelProvider.php index 02441601d6..09339d81f3 100644 --- a/app/Providers/Filament/PanelProvider.php +++ b/app/Providers/Filament/PanelProvider.php @@ -5,7 +5,6 @@ use App\Enums\CustomizationKey; use App\Filament\Pages\Auth\EditProfile; use App\Filament\Pages\Auth\Login; -use App\Filament\PasskeysPlugin; use App\Http\Middleware\LanguageMiddleware; use App\Http\Middleware\RequireTwoFactorAuthentication; use Filament\Actions\Action; @@ -57,9 +56,6 @@ public function panel(Panel $panel): Panel AppAuthentication::make()->recoverable(), EmailAuthentication::make(), ]) - ->plugins([ - PasskeysPlugin::make(), - ]) ->middleware([ EncryptCookies::class, AddQueuedCookiesToResponse::class, From 80dbcfc2fb5278d81c07ac2de1061c3cbad17311 Mon Sep 17 00:00:00 2001 From: JoanFo1456 <161775222+JoanFo1456@users.noreply.github.com> Date: Sun, 8 Feb 2026 20:05:07 +0000 Subject: [PATCH 18/18] Suggested changes --- app/Filament/Pages/Auth/EditProfile.php | 5 ++--- app/Filament/Pages/Auth/Login.php | 11 +++++++++++ app/Livewire/Passkeys.php | 2 -- app/Providers/Filament/FilamentServiceProvider.php | 5 ----- app/Services/Activity/ActivityLogService.php | 3 ++- composer.json | 2 +- composer.lock | 12 ++++++------ lang/en/passkeys.php | 2 -- 8 files changed, 22 insertions(+), 20 deletions(-) diff --git a/app/Filament/Pages/Auth/EditProfile.php b/app/Filament/Pages/Auth/EditProfile.php index 16923c7d6a..f79f5b5c9d 100644 --- a/app/Filament/Pages/Auth/EditProfile.php +++ b/app/Filament/Pages/Auth/EditProfile.php @@ -39,6 +39,7 @@ use Filament\Schemas\Components\Tabs; use Filament\Schemas\Components\Tabs\Tab; use Filament\Schemas\Components\Utilities\Get; +use Filament\Schemas\Components\View; use Filament\Schemas\Schema; use Filament\Support\Colors\Color; use Filament\Support\Enums\Width; @@ -241,9 +242,7 @@ protected function getDefaultTabs(): array Section::make(trans('profile.tabs.passkeys')) ->description(trans('passkeys.description')) ->schema([ - Group::make([ - view('passkeys.livewire.passkeys-tab'), - ]), + View::make('passkeys.livewire.passkeys-tab'), ]), ]), Tab::make('api_keys') diff --git a/app/Filament/Pages/Auth/Login.php b/app/Filament/Pages/Auth/Login.php index 58dbb1bbeb..43b20579ae 100644 --- a/app/Filament/Pages/Auth/Login.php +++ b/app/Filament/Pages/Auth/Login.php @@ -9,6 +9,7 @@ use Filament\Forms\Components\TextInput; use Filament\Schemas\Components\Actions; use Filament\Schemas\Components\Component; +use Filament\Schemas\Components\View; use Filament\Schemas\Schema; use Filament\Support\Colors\Color; use Illuminate\Validation\ValidationException; @@ -25,6 +26,16 @@ public function boot(OAuthService $oauthService, CaptchaService $captchaService) $this->captchaService = $captchaService; } + public function content(Schema $schema): Schema + { + return $schema + ->components([ + $this->getFormContentComponent(), + $this->getMultiFactorChallengeFormContentComponent(), + View::make('passkeys.login'), + ]); + } + public function form(Schema $schema): Schema { $components = [ diff --git a/app/Livewire/Passkeys.php b/app/Livewire/Passkeys.php index 1b1479cc61..58674f77ce 100644 --- a/app/Livewire/Passkeys.php +++ b/app/Livewire/Passkeys.php @@ -1,7 +1,5 @@ Blade::render('filament.layouts.footer'), ); - FilamentView::registerRenderHook( - PanelsRenderHook::AUTH_LOGIN_FORM_AFTER, - fn () => view('passkeys.login'), - ); - FilamentView::registerRenderHook( PanelsRenderHook::STYLES_BEFORE, fn () => Blade::render("@vite(['resources/css/app.css'])") diff --git a/app/Services/Activity/ActivityLogService.php b/app/Services/Activity/ActivityLogService.php index 2a06427fc4..9cf8e2d1ef 100644 --- a/app/Services/Activity/ActivityLogService.php +++ b/app/Services/Activity/ActivityLogService.php @@ -10,6 +10,7 @@ use Illuminate\Contracts\Auth\Factory as AuthFactory; use Illuminate\Database\ConnectionInterface; use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Request; use Throwable; @@ -70,7 +71,7 @@ public function description(?string $description): self */ public function subject(...$subjects): self { - foreach ($subjects as $subject) { + foreach (Arr::wrap($subjects) as $subject) { if (is_null($subject)) { continue; } diff --git a/composer.json b/composer.json index c2bccf5cf8..9bf6c42eba 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "filament/filament": "^4.5", "gboquizosanchez/filament-log-viewer": "^2.1", "guzzlehttp/guzzle": "^7.10", - "laravel/framework": "^12.49", + "laravel/framework": "~12.49.0", "laravel/helpers": "^1.8", "laravel/sanctum": "^4.2", "laravel/socialite": "^5.24", diff --git a/composer.lock b/composer.lock index 5d44908d77..940abdc933 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "fe7b314eca9ee093ebf78c54c7c91942", + "content-hash": "dc1eedb66ac1930be9401bf0b299c2e5", "packages": [ { "name": "anourvalar/eloquent-serialize", @@ -2544,16 +2544,16 @@ }, { "name": "laravel/framework", - "version": "v12.50.0", + "version": "v12.49.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "174ffed91d794a35a541a5eb7c3785a02a34aaba" + "reference": "4bde4530545111d8bdd1de6f545fa8824039fcb5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/174ffed91d794a35a541a5eb7c3785a02a34aaba", - "reference": "174ffed91d794a35a541a5eb7c3785a02a34aaba", + "url": "https://api.github.com/repos/laravel/framework/zipball/4bde4530545111d8bdd1de6f545fa8824039fcb5", + "reference": "4bde4530545111d8bdd1de6f545fa8824039fcb5", "shasum": "" }, "require": { @@ -2762,7 +2762,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2026-02-04T18:34:13+00:00" + "time": "2026-01-28T03:40:49+00:00" }, { "name": "laravel/helpers", diff --git a/lang/en/passkeys.php b/lang/en/passkeys.php index 73bd6373c9..0f125d5231 100644 --- a/lang/en/passkeys.php +++ b/lang/en/passkeys.php @@ -1,7 +1,5 @@ 'Authenticate using a passkey', 'create' => 'Create',