mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-12-03 14:23:42 +08:00
9b271e559f
- Restructured some of the route naming to be a little more consistent. - Moved the routes about to be more logically in one place. - Created a new middleware to handle the auth of people that should be allowed access to mfa setup routes, since these could be used by existing logged in users or by people needing to setup MFA on access. - Added testing to cover MFA setup required flow. - Added TTL and method tracking to session last-login tracking system.
90 lines
2.7 KiB
PHP
90 lines
2.7 KiB
PHP
<?php
|
|
|
|
namespace BookStack\Http\Controllers\Auth;
|
|
|
|
use BookStack\Actions\ActivityType;
|
|
use BookStack\Auth\Access\LoginService;
|
|
use BookStack\Auth\Access\Mfa\MfaSession;
|
|
use BookStack\Auth\Access\Mfa\MfaValue;
|
|
use BookStack\Auth\Access\Mfa\TotpService;
|
|
use BookStack\Auth\Access\Mfa\TotpValidationRule;
|
|
use BookStack\Exceptions\NotFoundException;
|
|
use BookStack\Http\Controllers\Controller;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
class MfaTotpController extends Controller
|
|
{
|
|
use HandlesPartialLogins;
|
|
|
|
protected const SETUP_SECRET_SESSION_KEY = 'mfa-setup-totp-secret';
|
|
|
|
/**
|
|
* Show a view that generates and displays a TOTP QR code.
|
|
*/
|
|
public function generate(TotpService $totp)
|
|
{
|
|
if (session()->has(static::SETUP_SECRET_SESSION_KEY)) {
|
|
$totpSecret = decrypt(session()->get(static::SETUP_SECRET_SESSION_KEY));
|
|
} else {
|
|
$totpSecret = $totp->generateSecret();
|
|
session()->put(static::SETUP_SECRET_SESSION_KEY, encrypt($totpSecret));
|
|
}
|
|
|
|
$qrCodeUrl = $totp->generateUrl($totpSecret);
|
|
$svg = $totp->generateQrCodeSvg($qrCodeUrl);
|
|
|
|
return view('mfa.totp-generate', [
|
|
'secret' => $totpSecret,
|
|
'svg' => $svg,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Confirm the setup of TOTP and save the auth method secret
|
|
* against the current user.
|
|
* @throws ValidationException
|
|
* @throws NotFoundException
|
|
*/
|
|
public function confirm(Request $request)
|
|
{
|
|
$totpSecret = decrypt(session()->get(static::SETUP_SECRET_SESSION_KEY));
|
|
$this->validate($request, [
|
|
'code' => [
|
|
'required',
|
|
'max:12', 'min:4',
|
|
new TotpValidationRule($totpSecret),
|
|
]
|
|
]);
|
|
|
|
MfaValue::upsertWithValue($this->currentOrLastAttemptedUser(), MfaValue::METHOD_TOTP, $totpSecret);
|
|
session()->remove(static::SETUP_SECRET_SESSION_KEY);
|
|
$this->logActivity(ActivityType::MFA_SETUP_METHOD, 'totp');
|
|
|
|
return redirect('/mfa/setup');
|
|
}
|
|
|
|
/**
|
|
* Verify the MFA method submission on check.
|
|
* @throws NotFoundException
|
|
*/
|
|
public function verify(Request $request, LoginService $loginService, MfaSession $mfaSession)
|
|
{
|
|
$user = $this->currentOrLastAttemptedUser();
|
|
$totpSecret = MfaValue::getValueForUser($user, MfaValue::METHOD_TOTP);
|
|
|
|
$this->validate($request, [
|
|
'code' => [
|
|
'required',
|
|
'max:12', 'min:4',
|
|
new TotpValidationRule($totpSecret),
|
|
]
|
|
]);
|
|
|
|
$mfaSession->markVerifiedForUser($user);
|
|
$loginService->reattemptLoginFor($user);
|
|
|
|
return redirect()->intended();
|
|
}
|
|
}
|