From 6d890aaf7fbb66fd2b50ecc4adc1715a5fcc23f1 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sat, 15 Sep 2018 23:15:45 -0600 Subject: [PATCH] Prepare 2FA --- app/Http/Controllers/AccountController.php | 25 ++++++++++ app/Http/Controllers/AdminController.php | 3 +- app/Http/Controllers/TimelineController.php | 1 + app/Http/Kernel.php | 1 + app/Http/Middleware/TwoFactorAuth.php | 32 ++++++++++++ app/User.php | 2 +- app/Util/Lexer/RestrictedNames.php | 2 + resources/views/auth/checkpoint.blade.php | 49 +++++++++++++++++++ .../security/2fa/recovery-codes.blade.php | 22 +++++++++ routes/api.php | 4 -- routes/console.php | 4 -- 11 files changed, 135 insertions(+), 10 deletions(-) create mode 100644 app/Http/Middleware/TwoFactorAuth.php create mode 100644 resources/views/auth/checkpoint.blade.php create mode 100644 resources/views/settings/security/2fa/recovery-codes.blade.php diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index b7f567d7e..f7af111cf 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -17,6 +17,7 @@ use Carbon\Carbon; use Illuminate\Http\Request; use Mail; use Redis; +use PragmaRX\Google2FA\Google2FA; class AccountController extends Controller { @@ -301,4 +302,28 @@ class AccountController extends Controller ->withErrors(['password' => __('auth.failed')]); } } + + public function twoFactorCheckpoint(Request $request) + { + return view('auth.checkpoint'); + } + + public function twoFactorVerify(Request $request) + { + $this->validate($request, [ + 'code' => 'required|string|max:32' + ]); + $user = Auth::user(); + $code = $request->input('code'); + $google2fa = new Google2FA(); + $verify = $google2fa->verifyKey($user->{'2fa_secret'}, $code); + if($verify) { + $request->session()->push('2fa.session.active', true); + return redirect('/'); + } else { + return redirect()->back()->withErrors([ + 'code' => 'Invalid code' + ]); + } + } } diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index 97cc1ff5e..8f04879eb 100644 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -19,7 +19,8 @@ class AdminController extends Controller public function __construct() { - return $this->middleware('admin'); + $this->middleware('admin'); + $this->middleware('twofactor'); } public function home() diff --git a/app/Http/Controllers/TimelineController.php b/app/Http/Controllers/TimelineController.php index 1ce714b9f..58665fb0a 100644 --- a/app/Http/Controllers/TimelineController.php +++ b/app/Http/Controllers/TimelineController.php @@ -14,6 +14,7 @@ class TimelineController extends Controller public function __construct() { $this->middleware('auth'); + $this->middleware('twofactor'); } public function personal() diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index b90d197a4..eb8a2a4f7 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -61,6 +61,7 @@ class Kernel extends HttpKernel 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, + 'twofactor' => \App\Http\Middleware\TwoFactorAuth::class, 'validemail' => \App\Http\Middleware\EmailVerificationCheck::class, ]; } diff --git a/app/Http/Middleware/TwoFactorAuth.php b/app/Http/Middleware/TwoFactorAuth.php new file mode 100644 index 000000000..9eb742e61 --- /dev/null +++ b/app/Http/Middleware/TwoFactorAuth.php @@ -0,0 +1,32 @@ +user()) { + $user = $request->user(); + $enabled = (bool) $user->{'2fa_enabled'}; + if($enabled != false) { + $checkpoint = 'i/auth/checkpoint'; + if($request->session()->has('2fa.session.active') !== true && !$request->is($checkpoint)) + { + return redirect('/i/auth/checkpoint'); + } + } + } + return $next($request); + } +} diff --git a/app/User.php b/app/User.php index 4e014f046..7fba2c170 100644 --- a/app/User.php +++ b/app/User.php @@ -16,7 +16,7 @@ class User extends Authenticatable * * @var array */ - protected $dates = ['deleted_at', 'email_verified_at']; + protected $dates = ['deleted_at', 'email_verified_at', '2fa_setup_at']; /** * The attributes that are mass assignable. diff --git a/app/Util/Lexer/RestrictedNames.php b/app/Util/Lexer/RestrictedNames.php index 1bd67e81f..0bd2648b6 100644 --- a/app/Util/Lexer/RestrictedNames.php +++ b/app/Util/Lexer/RestrictedNames.php @@ -113,6 +113,7 @@ class RestrictedNames public static $reserved = [ // Reserved for instance admin 'admin', + 'administrator', // Static Assets 'assets', @@ -126,6 +127,7 @@ class RestrictedNames 'api', 'auth', 'css', + 'checkpoint', 'c', 'i', 'dashboard', diff --git a/resources/views/auth/checkpoint.blade.php b/resources/views/auth/checkpoint.blade.php new file mode 100644 index 000000000..24c4ae775 --- /dev/null +++ b/resources/views/auth/checkpoint.blade.php @@ -0,0 +1,49 @@ +@extends('layouts.blank') + +@section('content') +
+
+
+
+ +

Verify 2FA Code to continue

+
+
+
+
+ @csrf + +
+ +
+ + + @if ($errors->has('code')) + + {{ $errors->first('code') }} + + @endif +
+
+ + @if(config('pixelfed.recaptcha')) +
+ {!! Recaptcha::render() !!} +
+ @endif + +
+
+ + +
+
+
+
+
+
+
+
+@endsection diff --git a/resources/views/settings/security/2fa/recovery-codes.blade.php b/resources/views/settings/security/2fa/recovery-codes.blade.php new file mode 100644 index 000000000..47f37af29 --- /dev/null +++ b/resources/views/settings/security/2fa/recovery-codes.blade.php @@ -0,0 +1,22 @@ +@extends('settings.template') + +@section('section') + +
+

Two-Factor Authentication Recovery Codes

+
+ +
+ +

+ Each code can only be used once. +

+ +

+ + +@endsection \ No newline at end of file diff --git a/routes/api.php b/routes/api.php index c641ca5e5..852967954 100644 --- a/routes/api.php +++ b/routes/api.php @@ -12,7 +12,3 @@ use Illuminate\Http\Request; | is assigned the "api" middleware group. Enjoy building your API! | */ - -Route::middleware('auth:api')->get('/user', function (Request $request) { - return $request->user(); -}); diff --git a/routes/console.php b/routes/console.php index 75dd0cded..42cca27da 100644 --- a/routes/console.php +++ b/routes/console.php @@ -12,7 +12,3 @@ use Illuminate\Foundation\Inspiring; | simple approach to interacting with each command's IO methods. | */ - -Artisan::command('inspire', function () { - $this->comment(Inspiring::quote()); -})->describe('Display an inspiring quote');