8 Commits

Author SHA1 Message Date
Italo
bb3b21e325 Fixes database migration morph index being too large. 2022-06-17 17:33:46 -04:00
Italo
6fe7ff58f5 Changes to easier route registration. 2022-06-15 16:16:56 -04:00
Italo
43a192d007 Minor clarifications. 2022-06-15 16:15:08 -04:00
Italo
ac85b22030 Better WebAuthn explanation [skip-ci] 2022-06-15 11:33:48 -04:00
Italo
8c51785abc Merge pull request #2 from szepeviktor/patch-1
Make Markdown of images readable in README
2022-06-15 00:39:34 -04:00
Italo
47e0e95c09 Removed support image separation. 2022-06-15 00:38:40 -04:00
Viktor Szépe
4dcad713e5 Make Markdown of images readable in README 2022-06-15 02:41:39 +00:00
Italo
4469ac967a Adds TwoFactor mention [skip-ci] 2022-06-14 15:46:51 -04:00
5 changed files with 75 additions and 26 deletions

View File

@@ -1,5 +1,11 @@
# WebAuthn # WebAuthn
[![Latest Version on Packagist](https://img.shields.io/packagist/v/laragear/webauthn.svg)](https://packagist.org/packages/laragear/webauthn) [![Latest stable test run](https://github.com/Laragear/WebAuthn/workflows/Tests/badge.svg)](https://github.com/Laragear/WebAuthn/actions) [![Codecov coverage](https://codecov.io/gh/Laragear/WebAuthn/branch/1.x/graph/badge.svg?token=HIngrvQeOj)](https://codecov.io/gh/Laragear/WebAuthn) [![Maintainability](https://api.codeclimate.com/v1/badges/39841b40ab4b05b8f9d3/maintainability)](https://codeclimate.com/github/Laragear/WebAuthn/maintainability) [![Sonarcloud Status](https://sonarcloud.io/api/project_badges/measure?project=Laragear_WebAuthn&metric=alert_status)](https://sonarcloud.io/dashboard?id=Laragear_WebAuthn) [![Laravel Octane Compatibility](https://img.shields.io/badge/Laravel%20Octane-Compatible-success?style=flat&logo=laravel)](https://laravel.com/docs/9.x/octane#introduction)
[![Latest Version on Packagist](https://img.shields.io/packagist/v/laragear/webauthn.svg)](https://packagist.org/packages/laragear/webauthn)
[![Latest stable test run](https://github.com/Laragear/WebAuthn/workflows/Tests/badge.svg)](https://github.com/Laragear/WebAuthn/actions)
[![Codecov coverage](https://codecov.io/gh/Laragear/WebAuthn/branch/1.x/graph/badge.svg?token=HIngrvQeOj)](https://codecov.io/gh/Laragear/WebAuthn)
[![CodeClimate Maintainability](https://api.codeclimate.com/v1/badges/39841b40ab4b05b8f9d3/maintainability)](https://codeclimate.com/github/Laragear/WebAuthn/maintainability)
[![Sonarcloud Status](https://sonarcloud.io/api/project_badges/measure?project=Laragear_WebAuthn&metric=alert_status)](https://sonarcloud.io/dashboard?id=Laragear_WebAuthn)
[![Laravel Octane Compatibility](https://img.shields.io/badge/Laravel%20Octane-Compatible-success?style=flat&logo=laravel)](https://laravel.com/docs/9.x/octane#introduction)
Authenticate users with fingerprints, patterns and biometric data. Authenticate users with fingerprints, patterns and biometric data.
@@ -14,9 +20,11 @@ public function login(AssertedRequest $request)
} }
``` ```
> You want to add two-factor authentication to your app? Check out [Laragear TwoFactor](https://github.com/Laragear/TwoFactor).
## Keep this package free ## Keep this package free
[![](.assets/patreon.png)](https://patreon.com/packagesforlaravel)[![](.assets/ko-fi.png)](https://ko-fi.com/DarkGhostHunter)[![](.assets/buymeacoffee.png)](https://www.buymeacoffee.com/darkghosthunter)[![](.assets/paypal.png)](https://www.paypal.com/paypalme/darkghosthunter) [![Patreon](.assets/patreon.png)](https://patreon.com/packagesforlaravel)[![Ko-fi](.assets/ko-fi.png)](https://ko-fi.com/DarkGhostHunter)[![Buymeacoffee](.assets/buymeacoffee.png)](https://www.buymeacoffee.com/darkghosthunter)[![PayPal](.assets/paypal.png)](https://www.paypal.com/paypalme/darkghosthunter)
Your support allows me to keep this package free, up-to-date and maintainable. Alternatively, you can **[spread the word!](http://twitter.com/share?text=I%20am%20using%20this%20cool%20PHP%20package&url=https://github.com%2FLaragear%2FWebAuthn&hashtags=PHP,Laravel)** Your support allows me to keep this package free, up-to-date and maintainable. Alternatively, you can **[spread the word!](http://twitter.com/share?text=I%20am%20using%20this%20cool%20PHP%20package&url=https://github.com%2FLaragear%2FWebAuthn&hashtags=PHP,Laravel)**
@@ -37,11 +45,11 @@ composer require laragear/webauthn
WebAuthn authentication process consists in two _ceremonies_: attestation, and assertion. WebAuthn authentication process consists in two _ceremonies_: attestation, and assertion.
Attestation is the process of registering in the app a new public key from the authenticated user device. For that to work, the user must exist, and the device or browser must support WebAuthn. Attestation is the process of asking the authenticator (a phone, laptop, USB key...) to create a private-public key pair, and **register** the public key inside the app. For that to work, the user must exist, and the browser must support WebAuthn, which is what intermediates between the authenticator and the app.
Assertion is the process of pushing a cryptographic challenge to the device, and checking the response is valid using the public key already registered inside the application. Assertion is the process of pushing a cryptographic challenge to the device, which will return _signed_ by the private key. Upon arrival, the app checks the signature with the public key, ready to **log in**.
The private key doesn't leave the device, and there are no shared passwords to remember. The private key doesn't leave the authenticator, and there are no shared passwords to save, let alone remember.
## Set up ## Set up
@@ -53,7 +61,7 @@ We need to make sure your users can register their devices and authenticate with
After that, you can quickly start WebAuthn with the included controllers and helpers to make your life easier. After that, you can quickly start WebAuthn with the included controllers and helpers to make your life easier.
4. [Register the controllers](#4-register-the-controllers) 4. [Register the controllers](#4-register-the-routes-and-controllers)
5. [Use the Javascript helper](#5-use-the-javascript-helper) 5. [Use the Javascript helper](#5-use-the-javascript-helper)
### 1. Add the `eloquent-webauthn` driver ### 1. Add the `eloquent-webauthn` driver
@@ -112,26 +120,29 @@ class User extends Authenticatable implements WebAuthnAuthenticatable
From here you're ready to work with WebAuthn Authentication. The following steps will help you close the gap to a full implementation. From here you're ready to work with WebAuthn Authentication. The following steps will help you close the gap to a full implementation.
### 4. Register the controllers ### 4. Register the routes and controllers
WebAuthn uses exclusive controller actions to registering and authenticating users. If you want a quick start, just publish the controllers and routes included in Laragear WebAuthn. WebAuthn uses exclusive routes to register and authenticate users. Creating these routes and controller may be cumbersome, specially if it's your first time in the WebAuthn real.
Instead, go for a quick start and publish the controllers included in Laragear WebAuthn. These controllers will be located at `app\Http\Controllers\WebAuthn`.
```shell ```shell
php artisan vendor:publish --provider="Laragear\WebAuthn\WebAuthnServiceProvider" --tag="routes"
php artisan vendor:publish --provider="Laragear\WebAuthn\WebAuthnServiceProvider" --tag="controllers" php artisan vendor:publish --provider="Laragear\WebAuthn\WebAuthnServiceProvider" --tag="controllers"
``` ```
The `webauthn.php` route file should be added to your `routes` directory. You can pick them up easily in your `RouteServiceProvider`, or go the quick way and require the file from your `web.php` routes file. Next, to pick these controllers easily, go into your `web.php` routes file and register a default set of routes with the `WebAuthn::routes()` method.
```php ```php
// web.php
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use Laragear\WebAuthn\WebAuthn;
Route::view('welcome');
// WebAuthn Routes // WebAuthn Routes
Route::group([], base_path('routes/webauthn.php')); WebAuthn::routes();
``` ```
Along with the routes, the authentication controllers will be located at `App\Http\Controllers\WebAuthn`, which these routes point them toward automatically.
### 5. Use the Javascript helper ### 5. Use the Javascript helper
This package includes a simple but convenient script to handle WebAuthn Attestation and Assertion. To use it, just publish the `webauthn.js` asset into your application public resources. This package includes a simple but convenient script to handle WebAuthn Attestation and Assertion. To use it, just publish the `webauthn.js` asset into your application public resources.
@@ -191,7 +202,7 @@ new WebAuthn().login({
### Custom routes ### Custom routes
By default, the helper assumes you're using the [default WebAuthn routes](#4-register-the-controllers). If you're using different routes for WebAuthn, you can set them at runtime. Here is good place to use [ziggy](https://github.com/tighten/ziggy) if it's in your project. By default, the helper assumes you're using the [default WebAuthn routes](#4-register-the-routes-and-controllers). If you're using different routes for WebAuthn, you can set them at runtime.
```javascript ```javascript
const webAuthn = new WebAuthn({ const webAuthn = new WebAuthn({
@@ -203,6 +214,8 @@ const webAuthn = new WebAuthn({
}); });
``` ```
> Here is good place to use [ziggy](https://github.com/tighten/ziggy) if it's in your project.
### Headers ### Headers
You may add headers to all WebAuthn authentication requests using the second parameter of the `WebAuthn` constructor. These headers will be present on all requests made by the instance. You may add headers to all WebAuthn authentication requests using the second parameter of the `WebAuthn` constructor. These headers will be present on all requests made by the instance.
@@ -381,9 +394,9 @@ You may disable the fallback to only allow WebAuthn authentication by [setting `
### Detecting Cloned Credentials ### Detecting Cloned Credentials
During assertion, the package will automatically detect if a Credential as been cloned by comparing how many times the user has logged in with it. During assertion, the package will automatically detect if a Credential has been cloned by comparing how many times the user has logged in with it.
If it's detected as cloned, the Credential gets blacklisted, a [`CredentialCloned`](#events) event is fired, and the Assertion gets denied. If it's detected as cloned, the Credential is disabled, a [`CredentialCloned`](#events) event is fired, and the Assertion gets denied.
You can use the event to warn the user: You can use the event to warn the user:

View File

@@ -45,7 +45,7 @@ return new class extends Migration {
{ {
$table->string('id')->primary(); $table->string('id')->primary();
$table->morphs('authenticatable'); $table->morphs('authenticatable', 'webauthn_user_index');
// This is the user UUID that is generated automatically when a credential for the // This is the user UUID that is generated automatically when a credential for the
// given user is created. If a second credential is created, this UUID is queried // given user is created. If a second credential is created, this UUID is queried

View File

@@ -2,6 +2,8 @@
namespace Laragear\WebAuthn; namespace Laragear\WebAuthn;
use Illuminate\Support\Facades\Route;
/** /**
* @internal * @internal
*/ */
@@ -23,16 +25,26 @@ class WebAuthn
public const RESIDENT_KEY_DISCOURAGED = 'discouraged'; public const RESIDENT_KEY_DISCOURAGED = 'discouraged';
/** /**
* Returns all user verifications flags possible. * Registers a set of default WebAuthn routes.
* *
* @return string[] * @return void
*/ */
public static function userVerifications(): array public static function routes(): void
{ {
return [ Route::middleware('web')->group(static function (): void {
static::USER_VERIFICATION_REQUIRED, Route::post('webauthn/register/options')
static::USER_VERIFICATION_PREFERRED, ->uses([\App\Http\Controllers\WebAuthn\WebAuthnRegisterController::class, 'options'])
static::USER_VERIFICATION_DISCOURAGED, ->name('webauthn.register.options');
]; Route::post('webauthn/register')
->uses([\App\Http\Controllers\WebAuthn\WebAuthnRegisterController::class, 'register'])
->name('webauthn.register');
Route::post('webauthn/login/options')
->uses([\App\Http\Controllers\WebAuthn\WebAuthnLoginController::class, 'options'])
->name('webauthn.login.options');
Route::post('webauthn/login')
->uses([\App\Http\Controllers\WebAuthn\WebAuthnLoginController::class, 'login'])
->name('webauthn.login');
});
} }
} }

View File

@@ -7,6 +7,7 @@ use Laragear\WebAuthn\Http\Requests\AssertionRequest;
use Laragear\WebAuthn\Http\Requests\AttestationRequest; use Laragear\WebAuthn\Http\Requests\AttestationRequest;
use Laragear\WebAuthn\Http\Requests\AttestedRequest; use Laragear\WebAuthn\Http\Requests\AttestedRequest;
use Laragear\WebAuthn\JsonTransport; use Laragear\WebAuthn\JsonTransport;
use Laragear\WebAuthn\WebAuthn;
use Tests\Stubs\WebAuthnAuthenticatableUser; use Tests\Stubs\WebAuthnAuthenticatableUser;
use Tests\TestCase; use Tests\TestCase;
@@ -14,7 +15,7 @@ class StubControllersTest extends TestCase
{ {
protected function defineWebRoutes($router): void protected function defineWebRoutes($router): void
{ {
$router->group([], __DIR__ . '/../../../routes/webauthn.php'); WebAuthn::routes();
} }
public function test_uses_attestation_request(): void public function test_uses_attestation_request(): void

23
tests/WebAuthnTest.php Normal file
View File

@@ -0,0 +1,23 @@
<?php
namespace Tests;
use Illuminate\Support\Facades\Route;
use Laragear\WebAuthn\WebAuthn;
class WebAuthnTest extends TestCase
{
protected function defineWebRoutes($router): void
{
WebAuthn::routes();
}
public function test_registers_webauthn_routes(): void
{
static::assertTrue(Route::has('webauthn.register.options'));
static::assertTrue(Route::has('webauthn.register'));
static::assertTrue(Route::has('webauthn.login.options'));
static::assertTrue(Route::has('webauthn.login'));
}
}