Added Google Two Factor Authentication. Closes #326.

This commit is contained in:
James Brooks
2015-01-09 09:03:07 +00:00
committed by James Brooks
parent 20f744602a
commit de4ecf636f
20 changed files with 320 additions and 75 deletions
+12 -11
View File
@@ -135,6 +135,7 @@ return [
'Thujohn\Rss\RssServiceProvider',
'Jenssegers\Date\DateServiceProvider',
'McCool\LaravelAutoPresenter\LaravelAutoPresenterServiceProvider',
'PragmaRX\Google2FA\Vendor\Laravel\ServiceProvider',
/*
* Application Service Providers...
@@ -172,17 +173,17 @@ return [
'aliases' => [
'App' => 'Illuminate\Support\Facades\App',
'Auth' => 'Illuminate\Support\Facades\Auth',
'Form' => 'Illuminate\Support\Facades\Form',
'Input' => 'Illuminate\Support\Facades\Input',
'Redirect' => 'Illuminate\Support\Facades\Redirect',
'Request' => 'Illuminate\Support\Facades\Request',
'Response' => 'Illuminate\Support\Facades\Response',
'Route' => 'Illuminate\Support\Facades\Route',
'Session' => 'Illuminate\Support\Facades\Session',
'Setting' => 'CachetHQ\Cachet\Models\Setting',
'Str' => 'Illuminate\Support\Str',
'App' => 'Illuminate\Support\Facades\App',
'Auth' => 'Illuminate\Support\Facades\Auth',
'Form' => 'Illuminate\Support\Facades\Form',
'Input' => 'Illuminate\Support\Facades\Input',
'Redirect' => 'Illuminate\Support\Facades\Redirect',
'Request' => 'Illuminate\Support\Facades\Request',
'Response' => 'Illuminate\Support\Facades\Response',
'Route' => 'Illuminate\Support\Facades\Route',
'Session' => 'Illuminate\Support\Facades\Session',
'Setting' => 'CachetHQ\Cachet\Models\Setting',
'Str' => 'Illuminate\Support\Str',
],
@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AlterTableUsersAdd2FA extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('google_2fa_secret')->after('remember_token');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('google_2fa_secret');
});
}
}
+4 -3
View File
@@ -108,9 +108,10 @@ return [
// Login
'login' => [
'login' => 'Login',
'logged_in' => "You're logged in.",
'welcome' => 'Welcome Back!',
'login' => 'Login',
'logged_in' => 'You\'re logged in.',
'welcome' => 'Welcome Back!',
'two-factor' => 'Please enter your token.',
],
// Sidebar footer
+12 -7
View File
@@ -4,19 +4,21 @@ return [
// Setup form fields
'setup' => [
'email' => 'Email',
'username' => 'Username',
'password' => 'Password',
'site_name' => 'Site Name',
'site_domain' => 'Site Domain',
'site_timezone' => 'Select your timezone',
'site_locale' => 'Select your language',
'email' => 'Email',
'username' => 'Username',
'password' => 'Password',
'site_name' => 'Site Name',
'site_domain' => 'Site Domain',
'site_timezone' => 'Select your timezone',
'site_locale' => 'Select your language',
'enable_google2fa' => 'Enable Google Two Factor Authentication',
],
// Login form fields
'login' => [
'email' => 'Email',
'password' => 'Password',
'2fauth' => 'Authentication Code',
],
// Incidents form fields
@@ -79,6 +81,9 @@ return [
'password' => 'Password',
'api-key' => 'API Key',
'api-key-help' => 'Regenerating your API key will revoke all existing applications.',
'2fa' => [
'help' => 'Enabling two factor authentication increases security of your account. You will need to download <a href="https://support.google.com/accounts/answer/1066447?hl=en">Google Authenticator</a> or a similar app on to your mobile device. When you login you will be asked to provide a token generated by the app.',
],
],
// Buttons
+4 -3
View File
@@ -108,9 +108,10 @@ return [
// Login
'login' => [
'login' => 'Connexion',
'logged_in' => "Vous êtes connecté.",
'welcome' => 'Re-bonjour !',
'login' => 'Connexion',
'logged_in' => "Vous êtes connecté.",
'welcome' => 'Re-bonjour !',
'two-factor' => 'Please enter your token.',
],
// Sidebar footer
+12 -7
View File
@@ -4,19 +4,21 @@ return [
// Setup form fields
'setup' => [
'email' => 'Adresse email',
'username' => 'Identifiant',
'password' => 'Mot de passe',
'site_name' => 'Nom du site',
'site_domain' => 'Domaine du site',
'site_timezone' => 'Sélectionnez votre fuseau horaire',
'site_locale' => 'Sélectionnez votre langue',
'email' => 'Adresse email',
'username' => 'Identifiant',
'password' => 'Mot de passe',
'site_name' => 'Nom du site',
'site_domain' => 'Domaine du site',
'site_timezone' => 'Sélectionnez votre fuseau horaire',
'site_locale' => 'Sélectionnez votre langue',
'enable_google2fa' => 'Enable Google Two Factor Authentication',
],
// Login form fields
'login' => [
'email' => 'Adresse email',
'password' => 'Mot de passe',
'2fauth' => 'Authentication Code',
],
// Incidents form fields
@@ -79,6 +81,9 @@ return [
'password' => 'Mot de passe',
'api-key' => 'Clé API',
'api-key-help' => 'Regénérer votre clé API révoquera toutes les applications existantes.',
'2fa' => [
'help' => 'Enabling two factor authentication increases security of your account. You will need to download <a href="https://support.google.com/accounts/answer/1066447?hl=en">Google Authenticator</a> or a similar app on to your mobile device. When you login you will be asked to provide a token generated by the app.',
],
],
// Buttons
+6 -4
View File
@@ -1,6 +1,7 @@
<?php
return [
'dashboard' => 'Dashboard',
// Incidents
@@ -97,7 +98,7 @@ return [
'stylesheet' => 'Folha de estilo',
],
'theme' => [
'theme' => ' Tema',
'theme' => 'Tema',
],
'edit' => [
'success' => 'Configurações salvas.',
@@ -107,9 +108,10 @@ return [
// Login
'login' => [
'login' => 'Login',
'logged_in' => "Você está logado.",
'welcome' => 'Bem-vindo de volta!',
'login' => 'Login',
'logged_in' => "Você está logado.",
'welcome' => 'Bem-vindo de volta!',
'two-factor' => 'Please enter your token.',
],
// Sidebar footer
+12 -7
View File
@@ -3,19 +3,21 @@
return [
// Setup form fields
'setup' => [
'email' => 'Email',
'username' => 'Usuário',
'password' => 'Senha',
'site_name' => 'Nome do site',
'site_domain' => 'Domínio do site',
'site_timezone' => 'Select your timezone',
'site_locale' => 'Select your language',
'email' => 'Email',
'username' => 'Usuário',
'password' => 'Senha',
'site_name' => 'Nome do site',
'site_domain' => 'Domínio do site',
'site_timezone' => 'Select your timezone',
'site_locale' => 'Select your language',
'enable_google2fa' => 'Enable Google Two Factor Authentication',
],
// Login form fields
'login' => [
'email' => 'Email',
'password' => 'Senha',
'2fauth' => 'Authentication Code',
],
// Incidents form fields
@@ -78,6 +80,9 @@ return [
'password' => 'Senha',
'api-key' => 'Chave da API',
'api-key-help' => 'Regenerar sua chave de API irá revogar todos os aplicativos existentes.',
'2fa' => [
'help' => 'Enabling two factor authentication increases security of your account. You will need to download <a href="https://support.google.com/accounts/answer/1066447?hl=en">Google Authenticator</a> or a similar app on to your mobile device. When you login you will be asked to provide a token generated by the app.',
],
],
// Buttons
+29 -18
View File
@@ -1,22 +1,33 @@
<?php
Route::group(['before' => 'has_setting:app_name', 'namespace' => 'CachetHQ\Cachet\Http\Controllers'], function () {
// Login routes
Route::get('/auth/login', [
'before' => 'guest',
'as' => 'login',
'uses' => 'AuthController@showLogin',
]);
Route::post('/auth/login', [
'before' => 'guest|csrf|login_throttling',
'as' => 'logout',
'uses' => 'AuthController@postLogin',
]);
});
Route::group(['prefix' => 'auth', 'namespace' => 'CachetHQ\Cachet\Http\Controllers'], function () {
Route::group(['before' => 'has_setting:app_name'], function () {
// Login routes
Route::get('login', [
'before' => 'guest',
'as' => 'login',
'uses' => 'AuthController@showLogin',
]);
Route::group(['before' => 'auth', 'namespace' => 'CachetHQ\Cachet\Http\Controllers'], function () {
Route::get('/auth/logout', [
'as' => 'logout',
'uses' => 'AuthController@logoutAction',
]);
Route::post('login', [
'before' => 'guest|csrf|login_throttling',
'as' => 'logout',
'uses' => 'AuthController@postLogin',
]);
// Two factor authorization
Route::get('2fa', [
'as' => 'two-factor',
'uses' => 'AuthController@showTwoFactorAuth',
]);
Route::post('2fa', 'AuthController@postTwoFactor');
});
Route::group(['before' => 'auth'], function () {
Route::get('logout', [
'as' => 'logout',
'uses' => 'AuthController@logoutAction',
]);
});
});
+31
View File
@@ -0,0 +1,31 @@
@extends('layout.clean')
@section('content')
<div class="login">
<div class="col-xs-12 col-xs-offset-0 col-sm-6 col-sm-offset-3 col-md-4 col-md-offset-4 text-center">
<div class="welcome-logo">
<img class="logo" height="50" src="{{ url('img/cachet-logo.svg') }}" alt="Cachet"/>
</div>
{{ Form::open() }}
<fieldset>
<legend>{{ trans('dashboard.login.two-factor') }}</legend>
@if(Session::has('error'))
<p class="text-danger">{{ Session::get('error') }}</p>
@endif
<div class="form-group">
<label class="sr-only">{{ trans('forms.login.2fauth') }}</label>
{{ Form::text('code', null, [
'class' => 'form-control', 'placeholder' => trans('forms.login.2fauth'), 'required' => 'required'
]) }}
</div>
<hr />
<div class="form-group">
<button type="submit" class="btn btn-lg btn-block btn-success">{{ trans('dashboard.login.login') }}</button>
</div>
</fieldset>
{{ Form::close() }}
</div>
</div>
@stop
+3 -3
View File
@@ -6,7 +6,7 @@
<i class="icon ion-navicon"></i>
</div>
<span class="uppercase">
<i class="ion ion-person"></i> {{ trans('dashboard.user.user') }}
<i class="ion ion-person"></i> {{ trans('dashboard.team.member') }}
</span>
</div>
<div class="content-wrapper">
@@ -15,9 +15,9 @@
@if($updated = Session::get('updated'))
<div class="alert alert-{{ $updated ? 'success' : 'danger' }}">
@if($updated)
{{ sprintf("<strong>%s</strong> %s", trans('dashboard.notifications.awesome'), trans('dashboard.user.edit.success')) }}
{{ sprintf("<strong>%s</strong> %s", trans('dashboard.notifications.awesome'), trans('dashboard.team.edit.success')) }}
@else
{{ sprintf("<strong>%s</strong> %s", trans('dashboard.notifications.whoops'), trans('dashboard.user.edit.failure')) }}
{{ sprintf("<strong>%s</strong> %s", trans('dashboard.notifications.whoops'), trans('dashboard.team.edit.failure')) }}
@endif
</div>
@endif
+1 -1
View File
@@ -21,7 +21,7 @@
<div class="user-grid">
@foreach($teamMembers as $member)
<div class="user col-sm-3 col-xs-6">
<a href="/dashboard/team/{{ $member->id }}">
<a href="@if(Auth::user()->id == $member->id) {{ url('dashboard/user') }} @else /dashboard/team/{{ $member->id }} @endif">
<img src="{{ $member->gravatar }}" />
</a>
<div class="name">{{ $member->username }}</div>
+23 -2
View File
@@ -15,9 +15,9 @@
@if($updated = Session::get('updated'))
<div class="alert alert-{{ $updated ? 'success' : 'danger' }}">
@if($updated)
{{ sprintf("<strong>%s</strong> %s", trans('dashboard.notifications.awesome'), trans('dashboard.user.edit.success')) }}
{{ sprintf("<strong>%s</strong> %s", trans('dashboard.notifications.awesome'), trans('dashboard.team.edit.success')) }}
@else
{{ sprintf("<strong>%s</strong> %s", trans('dashboard.notifications.whoops'), trans('dashboard.user.edit.failure')) }}
{{ sprintf("<strong>%s</strong> %s", trans('dashboard.notifications.whoops'), trans('dashboard.team.edit.failure')) }}
@endif
</div>
@endif
@@ -42,6 +42,27 @@
<input type="text" class="form-control" name="api_key" disabled value="{{ Auth::user()->api_key }}" />
<span class="help-block">{{ trans('forms.user.api-key-help') }}</span>
</div>
<hr />
<div class="form-group">
<label class="checkbox-inline">
<input type="hidden" name="google2fa" value="0" />
<input type='checkbox' name="google2fa" value="1" {{ !empty(Auth::user()->google_2fa_secret) ? "checked" : "" }} />
{{ trans('forms.setup.enable_google2fa') }}
</label>
</div>
@if(Auth::user()->hasEnabled2FA)
<div class="form-group">
<?php
$google2fa_url = PragmaRX\Google2FA\Vendor\Laravel\Facade::getQRCodeGoogleUrl(
'CachetHQ',
Auth::user()->email,
Auth::user()->google_2fa_secret
);
?>
<img src="{{ $google2fa_url }}" class="img-responsive" />
<span class='help-block'>{{ trans('forms.user.2fa.help') }}</span>
</div>
@endif
</fieldset>
<button type="submit" class="btn btn-success">{{ trans('forms.update') }}</button>
+3
View File
@@ -107,6 +107,9 @@
<span class="text-danger">{{ $errors->first('user.password') }}</span>
@endif
</div>
<div class="form-group">
<i>{{ trans('forms.setup.enable_google2fa') }}</i>
</div>
</fieldset>
<hr />
<div class="form-group">