Skip to content
This repository has been archived by the owner on Feb 17, 2022. It is now read-only.

Commit

Permalink
Merge pull request #28 from DarkGhostHunter/master
Browse files Browse the repository at this point in the history
Fixes and features.
  • Loading branch information
DarkGhostHunter authored May 27, 2020
2 parents 5110363 + 8f42a48 commit d611d93
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 13 deletions.
34 changes: 26 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ This package _silently_ enables authentication using 6 digits codes, without Int
+ [Safe devices](#safe-devices)
+ [Secret length](#secret-length)
+ [TOTP configuration](#totp-configuration)
+ [QR Code Configuration](#qr-code-configuration)
+ [Custom view](#custom-view)
* [Security](#security)
* [License](#license)
Expand Down Expand Up @@ -270,13 +271,17 @@ return [
'expiration_days' => 14,
],
'secret_length' => 20,
'issuer' => env('APP_NAME', 'Laravel'),
'issuer' => env('OTP_TOTP_ISSUER'),
'totp' => [
'digits' => 6,
'seconds' => 30,
'window' => 1,
'algorithm' => 'sha1',
],
'qr_code' => [
'size' => 400,
'margin' => 4
],
];
```

Expand All @@ -302,7 +307,7 @@ return [
];
```

This is the model where the the Two Factor Authentication data, like the shared secret and recovery codes, are saved and associated to the User model.
This is the model where the data for Two Factor Authentication is saved, like the shared secret and recovery codes, and associated to the User model.

You can change this model for your own if you wish.

Expand Down Expand Up @@ -331,7 +336,7 @@ return [
];
```

[RFC 6238](https://tools.ietf.org/html/rfc6238#section-5) states that one-time passwords shouldn't be able to be usable again, even if inside the time window. For this, we need to use the Cache to save the code for a given period of time.
[RFC 6238](https://tools.ietf.org/html/rfc6238#section-5) states that one-time passwords shouldn't be able to be usable again, even if inside the time window. For this, we need to use the Cache to save the code for a given period.

You can change the store to use, which it's the default used by your application, and the prefix to use as cache keys, in case of collisions.

Expand Down Expand Up @@ -363,7 +368,7 @@ return [
];
```

Enabling this option will allow the application to "remember" a device using a cookie, allowing it to bypass Two Factor Authentication once a code is verified in that device. When the User logs in again in that device, it won't be prompted for a Code.
Enabling this option will allow the application to "remember" a device using a cookie, allowing it to bypass Two Factor Authentication once a code is verified in that device. When the User logs in again in that device, it won't be prompted for a 2FA Code again.

There is a limit of devices that can be saved. New devices will displace the oldest devices registered. Devices are considered no longer "safe" until a set amount of days.

Expand All @@ -387,7 +392,7 @@ It's recommended to use 128-bit or 160-bit because some Authenticator apps may h

```php
return [
'issuer' => env('APP_NAME', 'Laravel'),
'issuer' => env('OTP_TOTP_ISSUER'),
'totp' => [
'digits' => 6,
'seconds' => 30,
Expand All @@ -409,25 +414,38 @@ This configuration values are always passed down to the authentication app as UR

otpauth://totp/Laravel:[email protected]?secret=THISISMYSECRETPLEASEDONOTSHAREIT&issuer=Laravel&label=taylor%40laravel.com&algorithm=SHA1&digits=6&period=30

These values are printed to each 2FA data inside the application. Changes will only take effect for new activations.
These values are printed to each 2FA data record inside the application. Changes will only take effect for new activations.

> It's not recommended to edit these parameters if you plan to use publicly available Authenticator apps, since some of them **may not support non-standard configuration**, like more digits, different period of seconds or other algorithms.
### QR Code Configuration

```php
return [
'qr_code' => [
'size' => 400,
'margin' => 4
],
];
```

This controls the size and margin used to create the QR Code, which are created as SVG.

### Custom view

resources/views/vendor/laraguard/auth.blade.php

You can override the view, which handles the Two Factor Code verification for the User. It receives this data:

* `$action`: The full URL where the form should send the login credentials.
* `$credentials`: An array containing the User credentials used for the login.
* `$credentials`: An `array|null` containing the User credentials used for the login.
* `$user`: The User instance trying to authenticate.
* `$error`: If the Two Factor Code is invalid.
* `$remember`: If the "remember" checkbox has been filled.

The way it works is very simple: it will hold the User credentials in a hidden input while it asks for the Two Factor Code. The User will send everything again along with the Code, the application will ensure its correct, and complete the log in.

This view and its form is bypassed if the User doesn't uses Two Factor Authentication, making the log in transparent and non-invasive.
This view and its form is bypassed if the User doesn't uses Two Factor Authentication, making the login transparent and non-invasive.

## Security

Expand Down
18 changes: 17 additions & 1 deletion config/laraguard.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,28 @@
|
*/

'issuer' => env('APP_NAME', 'Laravel'),
'issuer' => env('OTP_TOTP_ISSUER'),

'totp' => [
'digits' => 6,
'seconds' => 30,
'window' => 1,
'algorithm' => 'sha1',
],

/*
|--------------------------------------------------------------------------
| QR Code Config
|--------------------------------------------------------------------------
|
| This package uses the BaconQrCode generator package to generate QR codes
| as SVG. These size and image margin values are used to create them. You
| can always your own code to create personalized QR Codes from the URI.
|
*/

'qr_code' => [
'size' => 400,
'margin' => 4
],
];
2 changes: 1 addition & 1 deletion resources/views/auth.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
@section('card-body')
<form action="{{ $action }}" method="post">
@csrf
@foreach($credentials as $name => $value)
@foreach((array)$credentials as $name => $value)
<input type="hidden" name="{{ $name }}" value="{{ $value }}">
@endforeach
@if($remember)
Expand Down
4 changes: 3 additions & 1 deletion src/Eloquent/SerializesSharedSecret.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ public function toUri() : string
*/
public function toQr() : string
{
[$size, $margin] = array_values(config('laraguard.qr_code'));

return (
new Writer((new ImageRenderer(new RendererStyle(400), new SvgImageBackEnd())))
new Writer((new ImageRenderer(new RendererStyle($size, $margin), new SvgImageBackEnd())))
)->writeString($this->toUri());
}

Expand Down
19 changes: 19 additions & 0 deletions tests/Eloquent/TwoFactorAuthenticationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,25 @@ public function test_serializes_to_qr_and_renders_to_qr()
$this->assertStringEqualsFile(__DIR__ . '/../Stubs/QrStub.svg', $tfa->render());
}

public function test_serializes_to_qr_and_renders_to_qr_with_custom_values()
{
config(['laraguard.issuer' => 'quz']);
config(['laraguard.qr_code' => [
'size' => 600,
'margin' => 10
]]);

$tfa = factory(TwoFactorAuthentication::class)->states('with recovery', 'with safe devices')->make([
'label' => '[email protected]',
'shared_secret' => 'KS72XBTN5PEBGX2IWBMVW44LXHPAQ7L3',
'algorithm' => 'sHa256',
'digits' => 14,
]);

$this->assertStringEqualsFile(__DIR__ . '/../Stubs/CustomQrStub.svg', $tfa->toQr());
$this->assertStringEqualsFile(__DIR__ . '/../Stubs/CustomQrStub.svg', $tfa->render());
}

public function test_serializes_uri_to_json()
{
config(['laraguard.issuer' => 'quz']);
Expand Down
16 changes: 16 additions & 0 deletions tests/Listeners/ForcesTwoFactorAuthTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,22 @@ public function test_form_contains_action_credentials_remember_and_user()
$this->assertStringContainsString(__('The Code is invalid or has expired.'), $view);
}

public function test_form_doesnt_contains_credentials()
{
$view = view('laraguard::auth')->with([
'action' => 'qux',
'user' => $this->user,
'credentials' => null,
'remember' => 'on',
'error' => true,
])->render();

$this->assertStringContainsString('action="qux"', $view);
$this->assertStringNotContainsString('<input type="hidden" name="foo" value="bar">', $view);
$this->assertStringContainsString('<input type="hidden" name="remember" value="on">', $view);
$this->assertStringContainsString(__('The Code is invalid or has expired.'), $view);
}

public function test_login_with_no_valid_credentials_no_2fa_fails()
{
$this->app['config']->set('auth.providers.users.model', UserStub::class);
Expand Down
2 changes: 2 additions & 0 deletions tests/Stubs/CustomQrStub.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 0 additions & 2 deletions tests/Stubs/UserStub.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use DarkGhostHunter\Laraguard\TwoFactorAuthentication;
use DarkGhostHunter\Laraguard\Contracts\TwoFactorAuthenticatable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;

class UserStub extends Model implements AuthenticatableContract
Expand Down

0 comments on commit d611d93

Please sign in to comment.