diff --git a/app/Http/Controllers/Settings/SecuritySettings.php b/app/Http/Controllers/Settings/SecuritySettings.php
new file mode 100644
index 000000000..99547b73b
--- /dev/null
+++ b/app/Http/Controllers/Settings/SecuritySettings.php
@@ -0,0 +1,139 @@
+<?php
+
+namespace App\Http\Controllers\Settings;
+
+use App\AccountLog;
+use App\EmailVerification;
+use App\Media;
+use App\Profile;
+use App\User;
+use App\UserFilter;
+use App\Util\Lexer\PrettyNumber;
+use Auth;
+use DB;
+use Carbon\Carbon;
+use Illuminate\Http\Request;
+use PragmaRX\Google2FA\Google2FA;
+
+trait SecuritySettings
+{
+
+	public function security()
+	{
+		$sessions = DB::table('sessions')
+			->whereUserId(Auth::id())
+			->limit(20)
+			->get();
+
+		$activity = AccountLog::whereUserId(Auth::id())
+			->orderBy('created_at', 'desc')
+			->limit(20)
+			->get();
+
+		$user = Auth::user();
+
+		return view('settings.security', compact('sessions', 'activity', 'user'));
+	}
+
+	public function securityTwoFactorSetup(Request $request)
+	{
+		$user = Auth::user();
+		if($user->{'2fa_enabled'} && $user->{'2fa_secret'}) {
+			return redirect(route('account.security'));
+		}
+		$backups = $this->generateBackupCodes();
+		$google2fa = new Google2FA();
+		$key = $google2fa->generateSecretKey(32);
+		$qrcode = $google2fa->getQRCodeInline(
+		    config('pixelfed.domain.app'),
+		    $user->email,
+		    $key,
+		    500
+		);
+		$user->{'2fa_secret'} = $key;
+		$user->{'2fa_backup_codes'} = json_encode($backups);
+		$user->save();
+		return view('settings.security.2fa.setup', compact('user', 'qrcode', 'backups'));
+	}
+
+	protected function generateBackupCodes()
+	{
+		$keys = [];
+		for ($i=0; $i < 11; $i++) { 
+			$key = str_random(24);
+			$keys[] = $key;
+		}
+		return $keys;
+	}
+
+	public function securityTwoFactorSetupStore(Request $request)
+	{
+		$user = Auth::user();
+		if($user->{'2fa_enabled'} && $user->{'2fa_secret'}) {
+			abort(403, 'Two factor auth is already setup.');
+		}
+		$this->validate($request, [
+			'code' => 'required|integer'
+		]);
+		$code = $request->input('code');
+		$google2fa = new Google2FA();
+		$verify = $google2fa->verifyKey($user->{'2fa_secret'}, $code);
+		if($verify) {
+			$user->{'2fa_enabled'} = true;
+			$user->{'2fa_setup_at'} = Carbon::now();
+			$user->save();
+			return response()->json(['msg'=>'success']);
+		} else {
+			return response()->json(['msg'=>'fail'], 403);
+		}
+	}
+
+	public function securityTwoFactorEdit(Request $request)
+	{
+		$user = Auth::user();
+
+		if(!$user->{'2fa_enabled'} || !$user->{'2fa_secret'}) {
+			abort(403);
+		}
+
+		return view('settings.security.2fa.edit', compact('user'));
+	}
+
+	public function securityTwoFactorRecoveryCodes(Request $request)
+	{
+		$user = Auth::user();
+
+		if(!$user->{'2fa_enabled'} || !$user->{'2fa_secret'} || !$user->{'2fa_backup_codes'}) {
+			abort(403);
+		}
+		$codes = json_decode($user->{'2fa_backup_codes'}, true);
+		return view('settings.security.2fa.recovery-codes', compact('user', 'codes'));
+	}
+
+	public function securityTwoFactorUpdate(Request $request)
+	{
+		$user = Auth::user();
+
+		if(!$user->{'2fa_enabled'} || !$user->{'2fa_secret'} || !$user->{'2fa_backup_codes'}) {
+			abort(403);
+		}
+
+		$this->validate($request, [
+			'action'	=> 'required|string|max:12'
+		]);
+		
+		if($request->action !== 'remove') {
+			abort(403);
+		}
+
+		$user->{'2fa_enabled'} = false;
+		$user->{'2fa_secret'} = null;
+		$user->{'2fa_backup_codes'} = null;
+		$user->{'2fa_setup_at'} = null;
+		$user->save();
+
+		return response()->json([
+			'msg' => 'Successfully removed 2fa device'
+		], 200);
+	}
+}
\ No newline at end of file