Extracted text to translation files
Also aligned mfa method delete route to align with others.
This commit is contained in:
parent
773be963ba
commit
f1f59cf086
14 changed files with 104 additions and 128 deletions
|
@ -81,7 +81,7 @@ class MfaBackupCodesController extends Controller
|
|||
$loginService->reattemptLoginFor($user);
|
||||
|
||||
if ($codeService->countCodesInSet($updatedCodes) < 5) {
|
||||
$this->showWarningNotification('You have less than 5 backup codes remaining, Please generate and store a new set before you run out of codes to prevent being locked out of your account.');
|
||||
$this->showWarningNotification(trans('auth.mfa_backup_codes_usage_limit_warning'));
|
||||
}
|
||||
|
||||
return redirect()->intended();
|
||||
|
|
|
@ -76,6 +76,36 @@ return [
|
|||
'user_invite_success' => 'Password set, you now have access to :appName!',
|
||||
|
||||
// Multi-factor Authentication
|
||||
'mfa_use_totp' => 'Verify using a mobile app',
|
||||
'mfa_use_backup_codes' => 'Verify using a backup code',
|
||||
'mfa_setup' => 'Setup Multi-Factor Authentication',
|
||||
'mfa_setup_desc' => 'Setup multi-factor authentication as an extra layer of security for your user account.',
|
||||
'mfa_setup_configured' => 'Already Configured',
|
||||
'mfa_setup_reconfigure' => 'Reconfigure',
|
||||
'mfa_setup_remove_confirmation' => 'Are you sure you want to remove this multi-factor authentication method?',
|
||||
'mfa_setup_action' => 'Setup',
|
||||
'mfa_backup_codes_usage_limit_warning' => 'You have less than 5 backup codes remaining, Please generate and store a new set before you run out of codes to prevent being locked out of your account.',
|
||||
'mfa_option_totp_title' => 'Mobile App',
|
||||
'mfa_option_totp_desc' => 'To use multi-factor authentication you\'ll need a mobile application that supports TOTP such as Google Authenticator, Authy or Microsoft Authenticator.',
|
||||
'mfa_option_backup_codes_title' => 'Backup Codes',
|
||||
'mfa_option_backup_codes_desc' => 'Securely store a set of one-time-use backup codes which you can enter to verify your identity.',
|
||||
'mfa_gen_confirm_and_enable' => 'Confirm and Enable',
|
||||
'mfa_gen_backup_codes_title' => 'Backup Codes Setup',
|
||||
'mfa_gen_backup_codes_desc' => 'Store the below list of codes in a safe place. When accessing the system you\'ll be able to use one of the codes as a second authentication mechanism.',
|
||||
'mfa_gen_backup_codes_download' => 'Download Codes',
|
||||
'mfa_gen_backup_codes_usage_warning' => 'Each code can only be used once',
|
||||
'mfa_gen_totp_title' => 'Mobile App Setup',
|
||||
'mfa_gen_totp_desc' => 'To use multi-factor authentication you\'ll need a mobile application that supports TOTP such as Google Authenticator, Authy or Microsoft Authenticator.',
|
||||
'mfa_gen_totp_scan' => 'Scan the QR code below using your preferred authentication app to get started.',
|
||||
'mfa_gen_totp_verify_setup' => 'Verify Setup',
|
||||
'mfa_gen_totp_verify_setup_desc' => 'Verify that all is working by entering a code, generated within your authentication app, in the input box below:',
|
||||
'mfa_gen_totp_provide_code_here' => 'Provide your app generated code here',
|
||||
'mfa_verify_access' => 'Verify Access',
|
||||
'mfa_verify_access_desc' => 'Your user account requires you to confirm your identity via an additional level of verification before you\'re granted access. Verify using one of your configured methods to continue.',
|
||||
'mfa_verify_no_methods' => 'No Methods Configured',
|
||||
'mfa_verify_no_methods_desc' => 'No multi-factor authentication methods could be found for your account. You\'ll need to set up at least one method before you gain access.',
|
||||
'mfa_verify_use_totp' => 'Verify using a mobile app',
|
||||
'mfa_verify_use_backup_codes' => 'Verify using a backup code',
|
||||
'mfa_verify_backup_code' => 'Backup Code',
|
||||
'mfa_verify_backup_code_desc' => 'Enter one of your remaining backup codes below:',
|
||||
'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
|
||||
'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
|
||||
];
|
|
@ -39,6 +39,7 @@ return [
|
|||
'reset' => 'Reset',
|
||||
'remove' => 'Remove',
|
||||
'add' => 'Add',
|
||||
'configure' => 'Configure',
|
||||
'fullscreen' => 'Fullscreen',
|
||||
'favourite' => 'Favourite',
|
||||
'unfavourite' => 'Unfavourite',
|
||||
|
|
|
@ -205,6 +205,10 @@ return [
|
|||
'users_api_tokens_create' => 'Create Token',
|
||||
'users_api_tokens_expires' => 'Expires',
|
||||
'users_api_tokens_docs' => 'API Documentation',
|
||||
'users_mfa' => 'Multi-Factor Authentication',
|
||||
'users_mfa_desc' => 'Setup multi-factor authentication as an extra layer of security for your user account.',
|
||||
'users_mfa_x_methods' => ':count method configured|:count methods configured',
|
||||
'users_mfa_configure' => 'Configure Methods',
|
||||
|
||||
// API Tokens
|
||||
'user_api_token_create' => 'Create API Token',
|
||||
|
|
|
@ -4,12 +4,8 @@
|
|||
|
||||
<div class="container very-small py-xl">
|
||||
<div class="card content-wrap auto-height">
|
||||
<h1 class="list-heading">Backup Codes</h1>
|
||||
<p>
|
||||
Store the below list of codes in a safe place.
|
||||
When accessing the system you'll be able to use one of the codes
|
||||
as a second authentication mechanism.
|
||||
</p>
|
||||
<h1 class="list-heading">{{ trans('auth.mfa_gen_backup_codes_title') }}</h1>
|
||||
<p>{{ trans('auth.mfa_gen_backup_codes_desc') }}</p>
|
||||
|
||||
<div class="text-center mb-xs">
|
||||
<div class="text-bigger code-base p-m" style="column-count: 2">
|
||||
|
@ -20,18 +16,18 @@
|
|||
</div>
|
||||
|
||||
<p class="text-right">
|
||||
<a href="{{ $downloadUrl }}" download="backup-codes.txt" class="button outline small">Download Codes</a>
|
||||
<a href="{{ $downloadUrl }}" download="backup-codes.txt" class="button outline small">{{ trans('auth.mfa_gen_backup_codes_download') }}</a>
|
||||
</p>
|
||||
|
||||
<p class="callout warning">
|
||||
Each code can only be used once
|
||||
{{ trans('auth.mfa_gen_backup_codes_usage_warning') }}
|
||||
</p>
|
||||
|
||||
<form action="{{ url('/mfa/backup_codes/confirm') }}" method="POST">
|
||||
{{ csrf_field() }}
|
||||
<div class="mt-s text-right">
|
||||
<a href="{{ url('/mfa/setup') }}" class="button outline">{{ trans('common.cancel') }}</a>
|
||||
<button class="button">Confirm and Enable</button>
|
||||
<button class="button">{{ trans('auth.mfa_gen_confirm_and_enable') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
30
resources/views/mfa/setup-method-row.blade.php
Normal file
30
resources/views/mfa/setup-method-row.blade.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<div class="grid half gap-xl">
|
||||
<div>
|
||||
<div class="setting-list-label">{{ trans('auth.mfa_option_' . $method . '_title') }}</div>
|
||||
<p class="small">
|
||||
{{ trans('auth.mfa_option_' . $method . '_desc') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="pt-m">
|
||||
@if($userMethods->has($method))
|
||||
<div class="text-pos">
|
||||
@icon('check-circle')
|
||||
{{ trans('auth.mfa_setup_configured') }}
|
||||
</div>
|
||||
<a href="{{ url('/mfa/' . $method . '/generate') }}" class="button outline small">{{ trans('auth.mfa_setup_reconfigure') }}</a>
|
||||
<div component="dropdown" class="inline relative">
|
||||
<button type="button" refs="dropdown@toggle" class="button outline small">{{ trans('common.remove') }}</button>
|
||||
<div refs="dropdown@menu" class="dropdown-menu">
|
||||
<p class="text-neg small px-m mb-xs">{{ trans('auth.mfa_setup_remove_confirmation') }}</p>
|
||||
<form action="{{ url('/mfa/' . $method . '/remove') }}" method="post">
|
||||
{{ csrf_field() }}
|
||||
{{ method_field('delete') }}
|
||||
<button class="text-primary small delete">{{ trans('common.confirm') }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<a href="{{ url('/mfa/' . $method . '/generate') }}" class="button outline">{{ trans('auth.mfa_setup_action') }}</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
|
@ -4,76 +4,13 @@
|
|||
<div class="container small py-xl">
|
||||
|
||||
<div class="card content-wrap auto-height">
|
||||
<h1 class="list-heading">Setup Multi-Factor Authentication</h1>
|
||||
<p class="mb-none">
|
||||
Setup multi-factor authentication as an extra layer of security
|
||||
for your user account.
|
||||
</p>
|
||||
<h1 class="list-heading">{{ trans('auth.mfa_setup') }}</h1>
|
||||
<p class="mb-none"> {{ trans('auth.mfa_setup_desc') }}</p>
|
||||
|
||||
<div class="setting-list">
|
||||
<div class="grid half gap-xl">
|
||||
<div>
|
||||
<div class="setting-list-label">Mobile App</div>
|
||||
<p class="small">
|
||||
To use multi-factor authentication you'll need a mobile application
|
||||
that supports TOTP such as Google Authenticator, Authy or Microsoft Authenticator.
|
||||
</p>
|
||||
</div>
|
||||
<div class="pt-m">
|
||||
@if($userMethods->has('totp'))
|
||||
<div class="text-pos">
|
||||
@icon('check-circle')
|
||||
Already configured
|
||||
</div>
|
||||
<a href="{{ url('/mfa/totp/generate') }}" class="button outline small">Reconfigure</a>
|
||||
<div component="dropdown" class="inline relative">
|
||||
<button type="button" refs="dropdown@toggle" class="button outline small">Remove</button>
|
||||
<div refs="dropdown@menu" class="dropdown-menu">
|
||||
<p class="text-neg small px-m mb-xs">Are you sure you want to remove this multi-factor authentication method?</p>
|
||||
<form action="{{ url('/mfa/remove/totp') }}" method="post">
|
||||
{{ csrf_field() }}
|
||||
{{ method_field('delete') }}
|
||||
<button class="text-primary small delete">{{ trans('common.confirm') }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<a href="{{ url('/mfa/totp/generate') }}" class="button outline">Setup</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid half gap-xl">
|
||||
<div>
|
||||
<div class="setting-list-label">Backup Codes</div>
|
||||
<p class="small">
|
||||
Securely store a set of one-time-use backup codes
|
||||
which you can enter to verify your identity.
|
||||
</p>
|
||||
</div>
|
||||
<div class="pt-m">
|
||||
@if($userMethods->has('backup_codes'))
|
||||
<div class="text-pos">
|
||||
@icon('check-circle')
|
||||
Already configured
|
||||
</div>
|
||||
<a href="{{ url('/mfa/backup_codes/generate') }}" class="button outline small">Reconfigure</a>
|
||||
<div component="dropdown" class="inline relative">
|
||||
<button type="button" refs="dropdown@toggle" class="button outline small">Remove</button>
|
||||
<div refs="dropdown@menu" class="dropdown-menu">
|
||||
<p class="text-neg small px-m mb-xs">Are you sure you want to remove this multi-factor authentication method?</p>
|
||||
<form action="{{ url('/mfa/remove/backup_codes') }}" method="post">
|
||||
{{ csrf_field() }}
|
||||
{{ method_field('delete') }}
|
||||
<button class="text-primary small delete">{{ trans('common.confirm') }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<a href="{{ url('/mfa/backup_codes/generate') }}" class="button outline">Setup</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@foreach(['totp', 'backup_codes'] as $method)
|
||||
@include('mfa.setup-method-row', ['method' => $method])
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -4,14 +4,9 @@
|
|||
|
||||
<div class="container very-small py-xl">
|
||||
<div class="card content-wrap auto-height">
|
||||
<h1 class="list-heading">Mobile App Setup</h1>
|
||||
<p>
|
||||
To use multi-factor authentication you'll need a mobile application
|
||||
that supports TOTP such as Google Authenticator, Authy or Microsoft Authenticator.
|
||||
</p>
|
||||
<p>
|
||||
Scan the QR code below using your preferred authentication app to get started.
|
||||
</p>
|
||||
<h1 class="list-heading">{{ trans('auth.mfa_gen_totp_title') }}</h1>
|
||||
<p>{{ trans('auth.mfa_gen_totp_desc') }}</p>
|
||||
<p>{{ trans('auth.mfa_gen_totp_scan') }}</p>
|
||||
|
||||
<div class="text-center">
|
||||
<div class="block inline">
|
||||
|
@ -19,24 +14,21 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="list-heading">Verify Setup</h2>
|
||||
<p id="totp-verify-input-details" class="mb-s">
|
||||
Verify that all is working by entering a code, generated within your
|
||||
authentication app, in the input box below:
|
||||
</p>
|
||||
<h2 class="list-heading">{{ trans('auth.mfa_gen_totp_verify_setup') }}</h2>
|
||||
<p id="totp-verify-input-details" class="mb-s">{{ trans('auth.mfa_gen_totp_verify_setup_desc') }}</p>
|
||||
<form action="{{ url('/mfa/totp/confirm') }}" method="POST">
|
||||
{{ csrf_field() }}
|
||||
<input type="text"
|
||||
name="code"
|
||||
aria-labelledby="totp-verify-input-details"
|
||||
placeholder="Provide your app generated code here"
|
||||
placeholder="{{ trans('auth.mfa_gen_totp_provide_code_here') }}"
|
||||
class="input-fill-width {{ $errors->has('code') ? 'neg' : '' }}">
|
||||
@if($errors->has('code'))
|
||||
<div class="text-neg text-small px-xs">{{ $errors->first('code') }}</div>
|
||||
@endif
|
||||
<div class="mt-s text-right">
|
||||
<a href="{{ url('/mfa/setup') }}" class="button outline">{{ trans('common.cancel') }}</a>
|
||||
<button class="button">Confirm and Enable</button>
|
||||
<button class="button">{{ trans('auth.mfa_gen_confirm_and_enable') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -4,26 +4,18 @@
|
|||
<div class="container very-small py-xl">
|
||||
|
||||
<div class="card content-wrap auto-height">
|
||||
<h1 class="list-heading">Verify Access</h1>
|
||||
<p class="mb-none">
|
||||
Your user account requires you to confirm your identity via an additional level
|
||||
of verification before you're granted access.
|
||||
Verify using one of your configured methods to continue.
|
||||
</p>
|
||||
<h1 class="list-heading">{{ trans('auth.mfa_verify_access') }}</h1>
|
||||
<p class="mb-none">{{ trans('auth.mfa_verify_access_desc') }}</p>
|
||||
|
||||
@if(!$method)
|
||||
<hr class="my-l">
|
||||
<h5>No Methods Configured</h5>
|
||||
<p class="small">
|
||||
No multi-factor authentication methods could be found for your account.
|
||||
You'll need to set up at least one method before you gain access.
|
||||
</p>
|
||||
<h5>{{ trans('auth.mfa_verify_no_methods') }}</h5>
|
||||
<p class="small">{{ trans('auth.mfa_verify_no_methods_desc') }}</p>
|
||||
<div>
|
||||
<a href="{{ url('/mfa/setup') }}" class="button outline">Configure</a>
|
||||
<a href="{{ url('/mfa/setup') }}" class="button outline">{{ trans('common.configure') }}</a>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
@if($method)
|
||||
<hr class="my-l">
|
||||
@include('mfa.verify.' . $method)
|
||||
|
@ -33,7 +25,7 @@
|
|||
<hr class="my-l">
|
||||
@foreach($otherMethods as $otherMethod)
|
||||
<div class="text-center">
|
||||
<a href="{{ url("/mfa/verify?method={$otherMethod}") }}">{{ trans('auth.mfa_use_' . $otherMethod) }}</a>
|
||||
<a href="{{ url("/mfa/verify?method={$otherMethod}") }}">{{ trans('auth.mfa_verify_use_' . $otherMethod) }}</a>
|
||||
</div>
|
||||
@endforeach
|
||||
@endif
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
<div class="setting-list-label">Backup Code</div>
|
||||
<div class="setting-list-label">{{ trans('auth.mfa_verify_backup_code') }}</div>
|
||||
|
||||
<p class="small mb-m">
|
||||
Enter one of your remaining backup codes below:
|
||||
</p>
|
||||
<p class="small mb-m">{{ trans('auth.mfa_verify_backup_code_desc') }}</p>
|
||||
|
||||
<form action="{{ url('/mfa/backup_codes/verify') }}" method="post">
|
||||
{{ csrf_field() }}
|
||||
<input type="text"
|
||||
name="code"
|
||||
placeholder="Enter backup code here"
|
||||
placeholder="{{ trans('auth.mfa_verify_backup_code_enter_here') }}"
|
||||
class="input-fill-width {{ $errors->has('code') ? 'neg' : '' }}">
|
||||
@if($errors->has('code'))
|
||||
<div class="text-neg text-small px-xs">{{ $errors->first('code') }}</div>
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
<div class="setting-list-label">Mobile App</div>
|
||||
<div class="setting-list-label">{{ trans('auth.mfa_option_totp_title') }}</div>
|
||||
|
||||
<p class="small mb-m">
|
||||
Enter the code, generated using your mobile app, below:
|
||||
</p>
|
||||
<p class="small mb-m">{{ trans('auth.mfa_verify_totp_desc') }}</p>
|
||||
|
||||
<form action="{{ url('/mfa/totp/verify') }}" method="post">
|
||||
{{ csrf_field() }}
|
||||
<input type="text"
|
||||
name="code"
|
||||
placeholder="Provide your app generated code here"
|
||||
placeholder="{{ trans('auth.mfa_gen_totp_provide_code_here') }}"
|
||||
class="input-fill-width {{ $errors->has('code') ? 'neg' : '' }}">
|
||||
@if($errors->has('code'))
|
||||
<div class="text-neg text-small px-xs">{{ $errors->first('code') }}</div>
|
||||
|
|
|
@ -64,11 +64,8 @@
|
|||
</section>
|
||||
|
||||
<section class="card content-wrap auto-height">
|
||||
<h2 class="list-heading">Multi-Factor Authentication</h2>
|
||||
<p>
|
||||
Setup multi-factor authentication as an extra layer of security
|
||||
for your user account.
|
||||
</p>
|
||||
<h2 class="list-heading">{{ trans('settings.users_mfa') }}</h2>
|
||||
<p>{{ trans('settings.users_mfa_desc') }}</p>
|
||||
<div class="grid half gap-xl v-center pb-s">
|
||||
<div>
|
||||
@if ($mfaMethods->count() > 0)
|
||||
|
@ -76,11 +73,12 @@
|
|||
@else
|
||||
<span class="text-neg">@icon('cancel')</span>
|
||||
@endif
|
||||
{{ trans_choice('settings.users_mfa_x_methods', $mfaMethods->count()) }}
|
||||
{{ $mfaMethods->count() }} {{ $mfaMethods->count() === 1 ? 'method' : 'methods' }} configured
|
||||
</div>
|
||||
<div class="text-m-right">
|
||||
@if($user->id === user()->id)
|
||||
<a href="{{ url('/mfa/setup') }}" class="button outline">Configure Methods</a>
|
||||
<a href="{{ url('/mfa/setup') }}" class="button outline">{{ trans('settings.users_mfa_configure') }}</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -239,7 +239,7 @@ Route::group(['middleware' => 'guest'], function() {
|
|||
Route::post('/mfa/totp/verify', 'Auth\MfaTotpController@verify');
|
||||
Route::post('/mfa/backup_codes/verify', 'Auth\MfaBackupCodesController@verify');
|
||||
});
|
||||
Route::delete('/mfa/remove/{method}', 'Auth\MfaController@remove')->middleware('auth');
|
||||
Route::delete('/mfa/{method}/remove', 'Auth\MfaController@remove')->middleware('auth');
|
||||
|
||||
// Social auth routes
|
||||
Route::get('/login/service/{socialDriver}', 'Auth\SocialController@login');
|
||||
|
|
|
@ -153,9 +153,9 @@ class MfaConfigurationTest extends TestCase
|
|||
MfaValue::upsertWithValue($admin, MfaValue::METHOD_TOTP, 'test');
|
||||
$this->assertEquals(1, $admin->mfaValues()->count());
|
||||
$resp = $this->actingAs($admin)->get('/mfa/setup');
|
||||
$resp->assertElementExists('form[action$="/mfa/remove/totp"]');
|
||||
$resp->assertElementExists('form[action$="/mfa/totp/remove"]');
|
||||
|
||||
$resp = $this->delete("/mfa/remove/totp");
|
||||
$resp = $this->delete("/mfa/totp/remove");
|
||||
$resp->assertRedirect("/mfa/setup");
|
||||
$resp = $this->followRedirects($resp);
|
||||
$resp->assertSee('Multi-factor method successfully removed');
|
||||
|
|
Loading…
Reference in a new issue