Skip to content

Commit

Permalink
feat: rewrite for more customizable library (#355)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: This new version is a rewrite with a lot of breaking changes, see details in https://github.com/asbiin/laravel-webauthn/blob/main/docs/migration-v1-to-v2.md
  • Loading branch information
asbiin authored Feb 5, 2022
1 parent 51c23a4 commit 424caae
Show file tree
Hide file tree
Showing 80 changed files with 3,119 additions and 1,635 deletions.
68 changes: 51 additions & 17 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,31 @@ on:
workflow_dispatch:

env:
php-version: '8.1'
laravel-version: '8.*'
node-version: 14
default-php-version: '8.1'
default-laravel-version: '8.*'
semantic-node-version: 16

jobs:
tests:
runs-on: ubuntu-latest
name: PHP ${{ matrix.php-version }} | Laravel ${{ matrix.laravel_version }}
name: PHP ${{ matrix.php-version }} | Laravel ${{ matrix.laravel-version }} (${{ matrix.psr7 }})

strategy:
fail-fast: false
matrix:
php-version: ['7.4', '8.0', '8.1']
laravel_version: [6.*, 7.*, 8.*]
laravel-version: [7.*, 8.*]
psr7: ['guzzle']
exclude:
- php-version: '8.1'
laravel_version: '6.*'
laravel-version: '7.*'
include:
- php-version: '8.1'
laravel_version: '7.*'
laravel-version: '8.*'
psr7: 'nyholm'
- php-version: '8.1'
laravel-version: '8.*'
psr7: 'discovery'

steps:
- name: Checkout sources
Expand Down Expand Up @@ -63,27 +69,45 @@ jobs:
uses: actions/[email protected]
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-v4-${{ hashFiles('**/composer.json') }}-${{ matrix.php-version }}-${{ matrix.laravel_version }}
key: ${{ runner.os }}-composer-v4-${{ hashFiles('**/composer.json') }}-${{ matrix.php-version }}-${{ matrix.laravel-version }}
restore-keys: |
${{ runner.os }}-composer-v4-${{ hashFiles('**/composer.json') }}-${{ matrix.php-version }}-${{ matrix.laravel_version }}
${{ runner.os }}-composer-v4-${{ hashFiles('**/composer.json') }}-${{ matrix.php-version }}-${{ matrix.laravel-version }}
${{ runner.os }}-composer-v4-${{ hashFiles('**/composer.json') }}-${{ matrix.php-version }}
${{ runner.os }}-composer-v4-${{ hashFiles('**/composer.json') }}
${{ runner.os }}-composer-v4-
- name: Install dependencies with Laravel ${{ matrix.laravel_version }}
- name: Update dependencies with Laravel ${{ matrix.laravel-version }}
run: |
export COMPOSER_ROOT_VERSION=dev-main
composer require "illuminate/support:${{ matrix.laravel-version }}" --no-update
- name: Use psr7 variant (nyholm)
if: matrix.psr7 == 'nyholm'
run: |
composer remove psr/http-factory-implementation --no-update
composer remove --dev guzzlehttp/psr7 --no-update
composer require --dev symfony/psr-http-message-bridge nyholm/psr7 --no-update
- name: Use psr7 variant (with php-http/discovery)
if: matrix.psr7 == 'discovery'
run: |
export COMPOSER_ROOT_VERSION=dev-master
composer require "laravel/framework:${{ matrix.laravel_version }}" --no-interaction --no-progress --prefer-stable --prefer-dist
composer remove psr/http-factory-implementation --no-update
composer remove --dev guzzlehttp/psr7 --no-update
composer require --dev symfony/psr-http-message-bridge php-http/discovery laminas/laminas-diactoros php-http/curl-client --no-update
- name: Install dependencies
run: |
composer update --no-interaction --no-progress --prefer-dist
- name: Run test suite
run: phpdbg -dmemory_limit=4G -qrr vendor/bin/phpunit -c phpunit.xml --log-junit ./results/results.xml --coverage-clover ./results/coverage.xml
run: phpdbg -dmemory_limit=4G -qrr vendor/bin/phpunit -c phpunit.xml --log-junit ./results/results_${{ matrix.psr7 }}.xml --coverage-clover ./results/coverage_${{ matrix.psr7 }}.xml

- name: Fix results files
run: sed -i -e "s%$GITHUB_WORKSPACE/%%g" *.xml
working-directory: results

- name: Store results
if: matrix.php-version == '${{ env.php-version }}' && matrix.laravel_version == '${{ env.laravel-version }}'
if: matrix.php-version == env.default-php-version && matrix.laravel-version == env.default-laravel-version
uses: actions/upload-artifact@v2
with:
name: results
Expand Down Expand Up @@ -112,12 +136,22 @@ jobs:
name: results
path: results

- name: Set coverage list
id: coverage
run: |
SONAR_COVERAGE=$(ls -m --format=comma results/coverage*.xml | sed -e ':a;N;$!ba;s/\n//g; s/ //g;')
echo "::set-output name=list::$SONAR_COVERAGE"
- name: SonarCloud Scan
if: env.SONAR_TOKEN != ''
uses: SonarSource/[email protected]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
with:
args: |
-Dsonar.php.tests.reportPath=./results/results_guzzle.xml
-Dsonar.php.coverage.reportPaths=${{ steps.coverage.outputs.list }}
####################
Expand All @@ -135,10 +169,10 @@ jobs:
with:
fetch-depth: 0 # Get all tags

- name: Use Node.js ${{ env.node-version }}
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: ${{ env.node-version }}
node-version: ${{ env.semantic-node-version }}

- name: Semantic Release
uses: cycjimmy/semantic-release-action@v2
Expand All @@ -149,7 +183,7 @@ jobs:
with:
semantic_version: 18
extra_plugins: |
@semantic-release/changelog
@semantic-release/changelog@6
semantic-release-github-pullrequest
- name: New release published
Expand Down
172 changes: 128 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Webauthn adapter for Laravel
Webauthn adapter for Laravel <!-- omit in toc -->
============================

LaravelWebauthn is an adapter to use Webauthn as 2FA (second-factor authentication) on Laravel.
Expand All @@ -10,6 +10,21 @@ LaravelWebauthn is an adapter to use Webauthn as 2FA (second-factor authenticati
[![Coverage Status](https://img.shields.io/sonar/coverage/asbiin_laravel-webauthn?server=https%3A%2F%2Fsonarcloud.io&style=flat-square&label=Coverage%20Status)](https://sonarcloud.io/dashboard?id=asbiin_laravel-webauthn)


- [Installation](#installation)
- [Configuration](#configuration)
- [Add LaravelWebauthn middleware](#add-laravelwebauthn-middleware)
- [Login via remember](#login-via-remember)
- [Usage](#usage)
- [Authenticate](#authenticate)
- [Register a new key](#register-a-new-key)
- [Important](#important)
- [Homestead](#homestead)
- [Routes](#routes)
- [Events](#events)
- [View response](#view-response)
- [Compatibility](#compatibility)
- [License](#license)

# Installation

You may use Composer to install this package into your Laravel project:
Expand All @@ -20,47 +35,14 @@ composer require asbiin/laravel-webauthn

You don't need to add this package to your service providers.

## Support

This package supports Laravel 5.8 and newer, and has been tested with php 7.2 and newer versions.

It's based on [web-auth/webauthn-framework](https://github.com/web-auth/webauthn-framework).


## Important

Your browser will refuse to negotiate a relay to your security device without the following:

- domain (localhost and 127.0.0.1 will be rejected by `webauthn.js`)
- an SSL/TLS certificate trusted by your browser (self-signed is okay)
- connected HTTPS on port 443 (ports other than 443 will be rejected)

### Homestead
If you are a Laravel Homestead user, the default is to forward ports. You can switch from NAT/port forwarding to a private network with similar `Homestead.yaml` options:

```yaml
sites:
- map: homestead.test
networks:
- type: "private_network"
ip: "192.168.254.2"
```
Re-provisioning vagrant will inform your virtual machine of the new network and install self-signed SSL/TLS certificates automatically: `vagrant reload --provision`

If you haven't done so already, describe your site domain and network in your hosts file:
```
192.168.254.2 homestead.test
```


## Configuration

You can publish the LaravelWebauthn configuration in a file named `config/webauthn.php`, and resources.
Just run this artisan command:

```sh
php artisan laravelwebauthn:publish
php artisan vendor:publish --provider="LaravelWebauthn\WebauthnServiceProvider"
```

If desired, you may disable LaravelWebauthn entirely using the `enabled` configuration option:
Expand All @@ -87,6 +69,23 @@ Route::middleware(['auth', 'webauthn'])->group(function () {
This way users would have to validate their key on login.


### Login via remember

When session expires, but the user set the `remember` token, you can revalidate webauthn session by adding this in your `App\Providers\EventServiceProvider` file:

```php
use Illuminate\Auth\Events\Login;
use LaravelWebauthn\Listeners\LoginViaRemember;

class EventServiceProvider extends ServiceProvider
{
protected $listen = [
Login::class => [
LoginViaRemember::class,
],
];
...
```

# Usage

Expand Down Expand Up @@ -184,35 +183,120 @@ If `postSuccessRedirectRoute` is empty, the return will be JSON form:
}
```

## Important

Your browser will refuse to negotiate a relay to your security device without the following:

- domain (localhost and 127.0.0.1 will be rejected by `webauthn.js`)
- an SSL/TLS certificate trusted by your browser (self-signed is okay)
- connected HTTPS on port 443 (ports other than 443 will be rejected)

### Homestead
If you are a Laravel Homestead user, the default is to forward ports. You can switch from NAT/port forwarding to a private network with similar `Homestead.yaml` options:

```yaml
sites:
- map: homestead.test
networks:
- type: "private_network"
ip: "192.168.254.2"
```
Re-provisioning vagrant will inform your virtual machine of the new network and install self-signed SSL/TLS certificates automatically: `vagrant reload --provision`

If you haven't done so already, describe your site domain and network in your hosts file:
```
192.168.254.2 homestead.test
```

## Urls

These url are used
## Routes

These reoutes are defined:

* GET `/webauthn/auth` / `route('webauthn.login')`
The login page.

* POST `/webauthn/auth` / `route('webauthn.auth')`
Post datas after a WebAuthn login validate.

* GET `/webauthn/register` / `route('webauthn.register')`
* GET `/webauthn/keys/create` / `route('webauthn.create')`
Get datas to register a new key

* POST `/webauthn/register` / `route('webauthn.create')`
* POST `/webauthn/keys` / `route('webauthn.store')`
Post datas after a WebAuthn register check

* DELETE `/webauthn/{id}` / `route('webauthn.destroy')`
Get register datas
* DELETE `/webauthn/keys/{id}` / `route('webauthn.destroy')`
Delete an existing key

* UPDATE `/webauthn/keys/{id}` / `route('webauthn.update')`
Update key properties


You can modify the first part of the url by setting `prefix` value in the config file.

## Events

Events are dispatched by LaravelWebauthn:

* `\LaravelWebauthn\Events\WebauthnLoginData` on creating authentication datas
* `\LaravelWebauthn\Events\WebauthnLogin` on login with WebAuthn check
* `\LaravelWebauthn\Events\WebauthnRegisterData` on creating register datas
* `\LaravelWebauthn\Events\WebauthnLoginData` on preparing authentication data
* `\LaravelWebauthn\Events\WebauthnLogin` on login with Webauthn check
* `\LaravelWebauthn\Events\WebauthnLoginFailed` on a failed login check
* `\LaravelWebauthn\Events\WebauthnRegisterData` on preparing register data
* `\LaravelWebauthn\Events\WebauthnRegister` on registering a new key
* `\LaravelWebauthn\Events\WebauthnRegisterFailed` on failing registering a new key


## View response

You can easily change the view responses with the Webauthn service:

```php
use LaravelWebauthn\Services\Webauthn;
class AppServiceProvider extends ServiceProvider
{
public function register()
{
Webauthn::loginViewResponseUsing(LoginViewResponse::class);
}
}
```

```php
use LaravelWebauthn\Http\Responses\LoginViewResponse as LoginViewResponseBase;
class LoginViewResponse extends LoginViewResponseBase
{
public function toResponse($request)
{
$publicKey = $this->publicKeyRequest($request);
return Inertia::render('Webauthn/WebauthnLogin', [
'publicKey' => $publicKey
]);
}
}
```

List of methods and their expected response contracts:

| Webauthn | LaravelWebauthn\Contracts |
|------------------------------|---------------------------------|
| loginViewResponseUsing | LoginViewResponseContract |
| loginSuccessResponseUsing | LoginSuccessResponseContract |
| registerViewResponseUsing | RegisterViewResponseContract |
| registerSuccessResponseUsing | RegisterSuccessResponseContract |
| destroyViewResponseUsing | DestroyResponseContract |
| updateViewResponseUsing | UpdateResponseContract |


# Compatibility

| Laravel | [asbiin/laravel-webauthn](https://github.com/asbiin/laravel-webauthn) |
|----------|----------|
| 5.8-8.x | <= 1.2.0 |
| 7.x-8.x | 2.0.0 |


# License
Expand Down
Loading

0 comments on commit 424caae

Please sign in to comment.