mein-sterntours/app/Services/AuthGoogle2FA.php
2021-11-09 18:38:44 +01:00

235 lines
6.3 KiB
PHP

<?php
namespace App\Services;
use Illuminate\Http\Request as IlluminateRequest;
use Illuminate\Http\Response as IlluminateHtmlResponse;
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
use Illuminate\Support\MessageBag;
use Google2FA;
use Request;
class AuthGoogle2FA
{
const CONFIG_PACKAGE_NAME = 'google2fa';
const SESSION_AUTH_PASSED = 'auth_passed';
const OTP_EMPTY = 'empty';
const OTP_VALID = 'valid';
const OTP_INVALID = 'invalid';
protected $password;
protected $request;
protected $auth;
public function __construct(IlluminateRequest $request)
{
$this->request = $request;
return $this;
}
public function init(IlluminateRequest $request)
{
$this->request = $request;
return $this;
}
public function isAuthenticated()
{
if(!$this->hasSecretKey() || !$this->isEnabled() || $this->noUserIsAuthenticated()){
return false;
}
if($this->twoFactorAuthStillValid()){
return true;
}
return ($this->checkOTP() === $this::OTP_VALID);
}
public function logout()
{
$this->sessionForget();
}
public function makeActiveOneTimePasswordResponse()
{
if($this->request->isMethod('post') && Request::get('action') === 'activate_user_one_time_password'){
$user = $this->getUser();
$user->google2fa = true;
$user->save();
return back();
}
$MyGoogle2FA = new MyGoogle2FA();
$MyGoogle2FA->init($this->getUser())->generate();
$fill = [
'MyGoogle2FA' => $MyGoogle2FA,
];
$view = view("auth.google2fa_activate", $fill);
return new IlluminateHtmlResponse($view);
}
public function makeRequestOneTimePasswordResponse()
{
$view = view($this->config('view'));
$statusCode = $this->makeStatusCode();
if ($statusCode !== SymfonyResponse::HTTP_OK) {
$view->withErrors($this->getErrorBagForStatusCode($statusCode));
}
return new IlluminateHtmlResponse($view, $statusCode);
}
protected function checkOTP()
{
if (!$this->request->has($this->config('otp_input') )|| empty($this->request->input($this->config('otp_input')))) {
return $this::OTP_EMPTY;
}
$isValid = $this->verifyOneTimePassword();
if ($isValid) {
$this->login();
return $this::OTP_VALID;
}
return $this::OTP_INVALID;
}
protected function login()
{
$this->sessionPut($this::SESSION_AUTH_PASSED, true);
}
protected function verifyOneTimePassword()
{
return Google2FA::verifyKey($this->getGoogle2FASecretKey(), $this->getOneTimePassword());
}
private function getOneTimePassword()
{
$password =$this->request->input($this->config('otp_input'));
if (is_null($password) || empty($password)) {
if ($this->config('throw_exceptions', true)) {
throw new \Exception($this->config('error_messages.cannot_be_empty')); }
}
return $password;
}
private function getGoogle2FASecretKey()
{
return $this->getUser()->{$this->config('otp_secret_column')};
}
private function hasSecretKey()
{
$secret = $this->getGoogle2FASecretKey();
return !is_null($secret) && !empty($secret);
}
private function twoFactorAuthStillValid()
{
return (bool) $this->sessionGet($this::SESSION_AUTH_PASSED, false);
}
private function isEnabled()
{
return $this->config('enabled');
}
private function noUserIsAuthenticated()
{
return is_null($this->getUser());
}
private function config($string, $default = null)
{
if (is_null(config($config = $this::CONFIG_PACKAGE_NAME))) {
throw new \Exception("Config ({$config}.php) not found. Have you published it?");
}
return config(
implode('.', [$this::CONFIG_PACKAGE_NAME, $string]),
$default
);
}
private function getAuth()
{
if (is_null($this->auth)) {
$this->auth = app($this->config('auth'));
if (!empty($this->config('guard'))) {
$this->auth = app($this->config('auth'))->guard($this->config('guard'));
}
}
return $this->auth;
}
private function getUser()
{
return $this->getAuth()->user();
}
private function makeSessionVarName($name = null)
{
return $this->config('session_var') . (is_null($name) || empty($name) ? '' : '.' . $name);
}
private function sessionGet($var = null, $default = null)
{
return $this->request->session()->get(
$this->makeSessionVarName($var),
$default
);
}
private function sessionPut($var, $value)
{
$this->request->session()->put(
$this->makeSessionVarName($var),
$value
);
return $value;
}
private function sessionForget($var = null)
{
$this->request->session()->forget(
$this->makeSessionVarName($var)
);
}
private function makeStatusCode()
{
if ($this->request->isMethod('get') || ($this->checkOTP() === $this::OTP_VALID)) {
return SymfonyResponse::HTTP_OK;
}
if ($this->checkOTP() === $this::OTP_EMPTY) {
return SymfonyResponse::HTTP_BAD_REQUEST;
}
return SymfonyResponse::HTTP_UNPROCESSABLE_ENTITY;
}
private function getErrorBagForStatusCode($statusCode)
{
$errorMap = [
SymfonyResponse::HTTP_UNPROCESSABLE_ENTITY => 'google2fa.error_messages.wrong_otp',
SymfonyResponse::HTTP_BAD_REQUEST => 'google2fa.error_messages.cannot_be_empty',
];
return $this->createErrorBagForMessage(
trans(
config(
array_key_exists($statusCode, $errorMap) ? $errorMap[$statusCode] : 'google2fa.error_messages.unknown'
)
)
);
}
private function createErrorBagForMessage($message)
{
return new MessageBag([
'message' => $message,
]);
}
}