mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-11-22 06:21:27 +00:00
Prepare 2FA
This commit is contained in:
parent
63ca2a209d
commit
6d890aaf7f
11 changed files with 135 additions and 10 deletions
|
@ -17,6 +17,7 @@ use Carbon\Carbon;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Mail;
|
use Mail;
|
||||||
use Redis;
|
use Redis;
|
||||||
|
use PragmaRX\Google2FA\Google2FA;
|
||||||
|
|
||||||
class AccountController extends Controller
|
class AccountController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -301,4 +302,28 @@ class AccountController extends Controller
|
||||||
->withErrors(['password' => __('auth.failed')]);
|
->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'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,8 @@ class AdminController extends Controller
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
return $this->middleware('admin');
|
$this->middleware('admin');
|
||||||
|
$this->middleware('twofactor');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function home()
|
public function home()
|
||||||
|
|
|
@ -14,6 +14,7 @@ class TimelineController extends Controller
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->middleware('auth');
|
$this->middleware('auth');
|
||||||
|
$this->middleware('twofactor');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function personal()
|
public function personal()
|
||||||
|
|
|
@ -61,6 +61,7 @@ class Kernel extends HttpKernel
|
||||||
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
||||||
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
|
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
|
||||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||||
|
'twofactor' => \App\Http\Middleware\TwoFactorAuth::class,
|
||||||
'validemail' => \App\Http\Middleware\EmailVerificationCheck::class,
|
'validemail' => \App\Http\Middleware\EmailVerificationCheck::class,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
32
app/Http/Middleware/TwoFactorAuth.php
Normal file
32
app/Http/Middleware/TwoFactorAuth.php
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Auth;
|
||||||
|
use Closure;
|
||||||
|
|
||||||
|
class TwoFactorAuth
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle an incoming request.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param \Closure $next
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function handle($request, Closure $next)
|
||||||
|
{
|
||||||
|
if($request->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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ class User extends Authenticatable
|
||||||
*
|
*
|
||||||
* @var array
|
* @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.
|
* The attributes that are mass assignable.
|
||||||
|
|
|
@ -113,6 +113,7 @@ class RestrictedNames
|
||||||
public static $reserved = [
|
public static $reserved = [
|
||||||
// Reserved for instance admin
|
// Reserved for instance admin
|
||||||
'admin',
|
'admin',
|
||||||
|
'administrator',
|
||||||
|
|
||||||
// Static Assets
|
// Static Assets
|
||||||
'assets',
|
'assets',
|
||||||
|
@ -126,6 +127,7 @@ class RestrictedNames
|
||||||
'api',
|
'api',
|
||||||
'auth',
|
'auth',
|
||||||
'css',
|
'css',
|
||||||
|
'checkpoint',
|
||||||
'c',
|
'c',
|
||||||
'i',
|
'i',
|
||||||
'dashboard',
|
'dashboard',
|
||||||
|
|
49
resources/views/auth/checkpoint.blade.php
Normal file
49
resources/views/auth/checkpoint.blade.php
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
@extends('layouts.blank')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container mt-5">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-lg-5">
|
||||||
|
<div class="text-center">
|
||||||
|
<img src="/img/pixelfed-icon-color.svg" height="60px">
|
||||||
|
<p class="font-weight-light h3 py-4">Verify 2FA Code to continue</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<form method="POST">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div class="form-group row">
|
||||||
|
|
||||||
|
<div class="col-md-12">
|
||||||
|
<input id="code" type="code" class="form-control{{ $errors->has('code') ? ' is-invalid' : '' }}" name="code" placeholder="{{__('Two-Factor Authentication Code')}}" required autocomplete="off">
|
||||||
|
|
||||||
|
@if ($errors->has('code'))
|
||||||
|
<span class="invalid-feedback">
|
||||||
|
<strong>{{ $errors->first('code') }}</strong>
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if(config('pixelfed.recaptcha'))
|
||||||
|
<div class="row my-3">
|
||||||
|
{!! Recaptcha::render() !!}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="form-group row mb-0">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<button type="submit" class="btn btn-success btn-block font-weight-bold">
|
||||||
|
{{ __('Verify') }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
|
@ -0,0 +1,22 @@
|
||||||
|
@extends('settings.template')
|
||||||
|
|
||||||
|
@section('section')
|
||||||
|
|
||||||
|
<div class="title">
|
||||||
|
<h3 class="font-weight-bold">Two-Factor Authentication Recovery Codes</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<p class="lead pb-3">
|
||||||
|
Each code can only be used once.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="lead"></p>
|
||||||
|
<ul class="list-group">
|
||||||
|
@foreach($codes as $code)
|
||||||
|
<li class="list-group-item"><code>{{$code}}</code></li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
@endsection
|
|
@ -12,7 +12,3 @@ use Illuminate\Http\Request;
|
||||||
| is assigned the "api" middleware group. Enjoy building your API!
|
| is assigned the "api" middleware group. Enjoy building your API!
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Route::middleware('auth:api')->get('/user', function (Request $request) {
|
|
||||||
return $request->user();
|
|
||||||
});
|
|
||||||
|
|
|
@ -12,7 +12,3 @@ use Illuminate\Foundation\Inspiring;
|
||||||
| simple approach to interacting with each command's IO methods.
|
| simple approach to interacting with each command's IO methods.
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Artisan::command('inspire', function () {
|
|
||||||
$this->comment(Inspiring::quote());
|
|
||||||
})->describe('Display an inspiring quote');
|
|
||||||
|
|
Loading…
Reference in a new issue