Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: Support Laravel 12 and webauthn-lib 5.0+ #497

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/static.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ jobs:
name: Static analysis
uses: monicahq/workflows/.github/workflows/static.yml@v2
with:
php-version: 8.2
php-version: 8.4
33 changes: 12 additions & 21 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ on:
workflow_dispatch:

env:
default-php-version: '8.3'
default-laravel-version: '11.0'
semantic-node-version: 20
default-php-version: '8.4'
default-laravel-version: '12.0'
semantic-node-version: 22

concurrency:
group: Tests ${{ github.ref }}
Expand All @@ -32,22 +32,10 @@ jobs:
strategy:
fail-fast: false
matrix:
php-version: ['8.1', '8.2', '8.3']
laravel-version: ['9.0', '10.0', '11.0']
php-version: ['8.2', '8.3', '8.4']
laravel-version: ['11.0', '12.0']
psr7: ['guzzle']
include:
- php-version: '8.1'
laravel-version: '9.0'
psr7: 'nyholm'
- php-version: '8.1'
laravel-version: '9.0'
psr7: 'discovery'
- php-version: '8.2'
laravel-version: '10.0'
psr7: 'nyholm'
- php-version: '8.2'
laravel-version: '10.0'
psr7: 'discovery'
- php-version: '8.2'
laravel-version: '11.0'
psr7: 'nyholm'
Expand All @@ -60,9 +48,12 @@ jobs:
- php-version: '8.3'
laravel-version: '11.0'
psr7: 'discovery'
exclude:
- php-version: '8.1'
laravel-version: '11.0'
- php-version: '8.4'
laravel-version: '12.0'
psr7: 'nyholm'
- php-version: '8.4'
laravel-version: '12.0'
psr7: 'discovery'

steps:
- name: Checkout sources
Expand Down Expand Up @@ -183,7 +174,7 @@ jobs:

- name: SonarCloud Scan
if: env.SONAR_TOKEN != ''
uses: SonarSource/sonarqube-scan-action@v4
uses: SonarSource/sonarqube-scan-action@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
Expand Down
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -427,11 +427,12 @@ List of methods and their expected response contracts:

This package has the following Laravel compatibility:

| Laravel | [asbiin/laravel-webauthn](https://github.com/asbiin/laravel-webauthn) |
| [asbiin/laravel-webauthn](https://github.com/asbiin/laravel-webauthn) | Laravel |
|----------|----------|
| 5.8-8.x | <= 1.2.0 |
| 7.x-8.x | 2.0.1 |
| >= 9.x | >= 3.0.0 |
| <= 1.2.0 | 5.8-8.x |
| 2.0.1 | 7.x-8.x |
| >= 3.0.0, <= 4.6.0 | 9.x-11.x |
| >= 5.0.0 | >= 11.x |

## Browser compatibility

Expand Down
24 changes: 12 additions & 12 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,34 +20,34 @@
}
],
"require": {
"php": ">=8.1",
"illuminate/support": "^9.0 || ^10.0 || ^11.0",
"php": ">=8.2",
"illuminate/support": "^11.0 || ^12.0",
"phpdocumentor/reflection-docblock": "^5.3",
"psr/http-factory-implementation": "1.0",
"symfony/property-access": "^6.4 || ^7.0",
"symfony/property-info": "^6.4 || ^7.0",
"symfony/serializer": "^6.4 || ^7.0",
"web-auth/cose-lib": "^4.0",
"web-auth/webauthn-lib": "^4.8",
"web-token/jwt-library": "^3.0"
"web-auth/webauthn-lib": "^4.8 || ^5.0",
"web-token/jwt-library": "^3.0 || ^4.0"
},
"conflict": {
"web-auth/webauthn-lib": "4.7.0"
},
"require-dev": {
"ext-sqlite3": "*",
"brainmaestro/composer-git-hooks": "^3.0",
"guzzlehttp/psr7": "^2.1",
"jschaedl/composer-git-hooks": "^4.0",
"larastan/larastan": "^2.0",
"larastan/larastan": "^2.0 || ^3.0",
"laravel/legacy-factories": "^1.0",
"laravel/pint": "^1.13",
"ocramius/package-versions": "^2.0",
"orchestra/testbench": "^7.0 || ^8.0 || ^9.0",
"phpstan/phpstan-deprecation-rules": "^1.0",
"phpstan/phpstan-phpunit": "^1.0",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^9.5 || ^10.0 || ^11.0",
"psalm/plugin-laravel": "^2.8"
"orchestra/testbench": "^9.0 || ^10.0",
"phpstan/phpstan-deprecation-rules": "^1.0 || ^2.0",
"phpstan/phpstan-phpunit": "^1.0 || ^2.0",
"phpstan/phpstan-strict-rules": "^1.0 || ^2.0",
"phpunit/phpunit": "^10.0 || ^11.0 || ^12.0",
"psalm/plugin-laravel": "^2.8 || ^3.0"
},
"suggest": {
"guzzlehttp/psr7": "To provide a psr/http-factory-implementation implementation",
Expand Down
2 changes: 1 addition & 1 deletion database/migrations/2019_03_29_163611_add_webauthn.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class() extends Migration
return new class extends Migration
{
/**
* Run the migrations.
Expand Down
2 changes: 0 additions & 2 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,3 @@ parameters:
paths:
- */Actions/AttemptToAuthenticate.php
- */Services/Webauthn/CreationOptionsFactory.php

excludes_analyse:
4 changes: 4 additions & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@
<plugins>
<pluginClass class="Psalm\LaravelPlugin\Plugin"/>
</plugins>

<issueHandlers>
<PossiblyUnusedMethod errorLevel="suppress"/>
</issueHandlers>
</psalm>
2 changes: 2 additions & 0 deletions src/Actions/UpdateKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ class UpdateKey
{
/**
* Update a key.
*
* @psalm-suppress PossiblyUnusedReturnValue
*/
public function __invoke(User $user, int $webauthnKeyId, string $keyName): Model
{
Expand Down
12 changes: 4 additions & 8 deletions src/Auth/EloquentWebAuthnProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
use Illuminate\Database\Eloquent\ModelNotFoundException;
use LaravelWebauthn\Events\WebauthnLogin;
use LaravelWebauthn\Facades\Webauthn;
use LaravelWebauthn\Services\Webauthn\CredentialAssertionValidator;
use ParagonIE\ConstantTime\Base64UrlSafe;
use Webauthn\Util\Base64;

Expand All @@ -20,25 +19,20 @@ class EloquentWebAuthnProvider extends EloquentUserProvider
*/
protected bool $fallback;

/**
* WebAuthn assertion validator.
*/
protected CredentialAssertionValidator $validator;

/**
* Create a new database user provider.
*/
public function __construct(Config $config, CredentialAssertionValidator $validator, Hasher $hasher, string $model)
public function __construct(Config $config, Hasher $hasher, string $model)
{
$this->fallback = (bool) $config->get('webauthn.fallback', true);
$this->validator = $validator;

parent::__construct($hasher, $model);
}

/**
* Retrieve a user by the given credentials.
*/
#[\Override]
public function retrieveByCredentials(array $credentials): ?User
{
if ($this->isSignedChallenge($credentials)) {
Expand Down Expand Up @@ -68,6 +62,7 @@ protected function isSignedChallenge(array $credentials): bool
/**
* Validate a user against the given credentials.
*/
#[\Override]
public function validateCredentials(User $user, array $credentials): bool
{
if ($this->isSignedChallenge($credentials)
Expand All @@ -88,6 +83,7 @@ public function validateCredentials(User $user, array $credentials): bool
/**
* Rehash the user's password if required and supported.
*/
#[\Override]
public function rehashPasswordIfRequired(User $user, array $credentials, bool $force = false): void
{
if ($this->isSignedChallenge($credentials)) {
Expand Down
3 changes: 3 additions & 0 deletions src/Events/WebauthnLogin.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

/**
* @psalm-suppress PossiblyUnusedProperty
*/
class WebauthnLogin
{
use Dispatchable, SerializesModels;
Expand Down
3 changes: 3 additions & 0 deletions src/Events/WebauthnLoginData.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
use Illuminate\Queue\SerializesModels;
use Webauthn\PublicKeyCredentialRequestOptions;

/**
* @psalm-suppress PossiblyUnusedProperty
*/
class WebauthnLoginData
{
use Dispatchable, SerializesModels;
Expand Down
5 changes: 5 additions & 0 deletions src/Events/WebauthnRegister.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

/**
* @psalm-suppress PossiblyUnusedProperty
*/
class WebauthnRegister
{
use Dispatchable, SerializesModels;
Expand All @@ -14,6 +17,8 @@ class WebauthnRegister
* Create a new event instance.
*
* @param \Illuminate\Database\Eloquent\Model $webauthnKey The new WebauthnKey.
*
* @psalm-suppress PossiblyUnusedProperty
*/
public function __construct(
public Model $webauthnKey
Expand Down
5 changes: 5 additions & 0 deletions src/Events/WebauthnRegisterData.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
use Illuminate\Queue\SerializesModels;
use Webauthn\PublicKeyCredentialCreationOptions;

/**
* @psalm-suppress PossiblyUnusedProperty
*/
class WebauthnRegisterData
{
use Dispatchable, SerializesModels;
Expand All @@ -16,6 +19,8 @@ class WebauthnRegisterData
*
* @param \Illuminate\Contracts\Auth\Authenticatable $user The authenticated user.
* @param PublicKeyCredentialCreationOptions $publicKey The register data.
*
* @psalm-suppress PossiblyUnusedProperty
*/
public function __construct(
public User $user,
Expand Down
5 changes: 5 additions & 0 deletions src/Events/WebauthnRegisterFailed.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

/**
* @psalm-suppress PossiblyUnusedProperty
*/
class WebauthnRegisterFailed
{
use Dispatchable, SerializesModels;
Expand All @@ -16,6 +19,8 @@ class WebauthnRegisterFailed
*
* @param \Illuminate\Contracts\Auth\Authenticatable $user The authenticated user.
* @param Exception|null $exception Exception throwned.
*
* @psalm-suppress PossiblyUnusedProperty
*/
public function __construct(
public User $user,
Expand Down
1 change: 1 addition & 0 deletions src/Facades/Webauthn.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class Webauthn extends Facade
/**
* Get the registered name of the component.
*/
#[\Override]
protected static function getFacadeAccessor(): string
{
return \LaravelWebauthn\Services\Webauthn::class;
Expand Down
4 changes: 2 additions & 2 deletions src/Http/Controllers/AuthenticateController.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ public function store(WebauthnLoginRequest $request): LoginSuccessResponse
protected function loginPipeline(WebauthnLoginRequest $request): Pipeline
{
if (Webauthn::$authenticateThroughCallback !== null) {
return (new Pipeline(app()))->send($request)->through(array_filter(
return (new Pipeline(app()))->send($request)->through(array_filter( // @phpstan-ignore arrayFilter.strict
call_user_func(Webauthn::$authenticateThroughCallback, $request)
));
}

if (is_array($pipelines = config('webauthn.pipelines.login'))) {
return (new Pipeline(app()))->send($request)->through(array_filter(
return (new Pipeline(app()))->send($request)->through(array_filter( // @phpstan-ignore arrayFilter.strict
$pipelines
));
}
Expand Down
3 changes: 3 additions & 0 deletions src/Http/Middleware/WebauthnMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
use Illuminate\Support\Facades\Redirect;
use LaravelWebauthn\Facades\Webauthn;

/**
* @psalm-suppress UnusedClass
*/
class WebauthnMiddleware
{
/**
Expand Down
1 change: 1 addition & 0 deletions src/Http/Responses/DestroyResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class DestroyResponse implements DestroyResponseContract
* @param \Illuminate\Http\Request $request
* @return \Symfony\Component\HttpFoundation\Response
*/
#[\Override]
public function toResponse($request)
{
return $request->wantsJson()
Expand Down
4 changes: 4 additions & 0 deletions src/Http/Responses/LockoutResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
use LaravelWebauthn\Services\LoginRateLimiter;
use LaravelWebauthn\Services\Webauthn;

/**
* @psalm-suppress UnusedClass
*/
class LockoutResponse implements LockoutResponseContract
{
/**
Expand All @@ -23,6 +26,7 @@ public function __construct(
* @param \Illuminate\Http\Request $request
* @return \Symfony\Component\HttpFoundation\Response
*/
#[\Override]
public function toResponse($request)
{
$seconds = $this->limiter->availableIn($request);
Expand Down
1 change: 1 addition & 0 deletions src/Http/Responses/LoginSuccessResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class LoginSuccessResponse implements LoginSuccessResponseContract
* @param \Illuminate\Http\Request $request
* @return \Symfony\Component\HttpFoundation\Response
*/
#[\Override]
public function toResponse($request)
{
return $request->wantsJson()
Expand Down
2 changes: 2 additions & 0 deletions src/Http/Responses/LoginViewResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class LoginViewResponse implements LoginViewResponseContract
* @param \Illuminate\Http\Request $request
* @return \Symfony\Component\HttpFoundation\Response
*/
#[\Override]
public function toResponse($request)
{
$view = config('webauthn.views.authenticate', '');
Expand All @@ -32,6 +33,7 @@ public function toResponse($request)
/**
* Set public key request data.
*/
#[\Override]
public function setPublicKey(Request $request, PublicKeyCredentialRequestOptions $publicKey): self
{
$this->publicKey = $publicKey;
Expand Down
2 changes: 2 additions & 0 deletions src/Http/Responses/RegisterSuccessResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class RegisterSuccessResponse implements RegisterSuccessResponseContract
* @param \Illuminate\Http\Request $request
* @return \Symfony\Component\HttpFoundation\Response
*/
#[\Override]
public function toResponse($request)
{
return $request->wantsJson()
Expand All @@ -45,6 +46,7 @@ protected function jsonResponse(Request $request): \Symfony\Component\HttpFounda
/**
* Set the new Webauthn key.
*/
#[\Override]
public function setWebauthnKey(Request $request, Model $webauthnKey): self
{
$this->webauthnKey = $webauthnKey;
Expand Down
Loading