3 changed files with 329 additions and 0 deletions
@ -0,0 +1,166 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* CodeIgniter-Aauth |
||||||
|
* |
||||||
|
* Aauth is a User Authorization Library for CodeIgniter 4.x, which aims to make |
||||||
|
* easy some essential jobs such as login, permissions and access operations. |
||||||
|
* Despite ease of use, it has also very advanced features like grouping, |
||||||
|
* access management, public access etc.. |
||||||
|
* |
||||||
|
* @package CodeIgniter-Aauth |
||||||
|
* @author Emre Akay |
||||||
|
* @author Raphael "REJack" Jackstadt |
||||||
|
* @copyright 2014-2019 Emre Akay |
||||||
|
* @license https://opensource.org/licenses/MIT MIT License |
||||||
|
* @link https://github.com/emreakay/CodeIgniter-Aauth |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace App\Libraries\Aauth; |
||||||
|
|
||||||
|
use \App\Models\Aauth\LoginAttemptModel; |
||||||
|
|
||||||
|
/** |
||||||
|
* Aauth CAPTCHA |
||||||
|
* |
||||||
|
* Class for handling CAPTCHA (reCAPTCHA & hCAPTCHA) |
||||||
|
* |
||||||
|
* @package CodeIgniter-Aauth |
||||||
|
*/ |
||||||
|
class CAPTCHA extends \App\Libraries\Aauth |
||||||
|
{ |
||||||
|
|
||||||
|
/** |
||||||
|
* Verify Response |
||||||
|
* |
||||||
|
* Calls the CAPTCHA site verify API to verify whether the user passes |
||||||
|
* CAPTCHA test. |
||||||
|
* |
||||||
|
* @param string $response Response string from CAPTCHA verification. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
*/ |
||||||
|
public function verifyResponse($response) |
||||||
|
{ |
||||||
|
if ($response === null || strlen($response) === 0) |
||||||
|
{ |
||||||
|
return [ |
||||||
|
'success' => false, |
||||||
|
'errorCodes' => 'missing-input', |
||||||
|
]; |
||||||
|
} |
||||||
|
|
||||||
|
$request = \Config\Services::request(); |
||||||
|
$remoteIp = $request->getIPAddress(); |
||||||
|
|
||||||
|
if ($this->config->captchaType === 'recaptcha') |
||||||
|
{ |
||||||
|
$siteUrl = 'https://www.google.com/recaptcha/api/siteverify'; |
||||||
|
$request = $this->_submitGet( |
||||||
|
$siteUrl, |
||||||
|
[ |
||||||
|
'secret' => $this->config->captchaSecret, |
||||||
|
'remoteip' => $remoteIp, |
||||||
|
'response' => $response, |
||||||
|
'version' => 'php_1.0.0', |
||||||
|
]); |
||||||
|
} |
||||||
|
else if ($this->config->captchaType === 'hcaptcha') |
||||||
|
{ |
||||||
|
$siteUrl = 'https://hcaptcha.com/siteverify'; |
||||||
|
$request = $this->_submitPost( |
||||||
|
$siteUrl, |
||||||
|
[ |
||||||
|
'secret' => $this->config->captchaSecret, |
||||||
|
'response' => $response, |
||||||
|
'remoteip' => $remoteIp, |
||||||
|
]); |
||||||
|
} |
||||||
|
|
||||||
|
$answer = json_decode($request, true); |
||||||
|
|
||||||
|
if (trim($answer['success']) === true) |
||||||
|
{ |
||||||
|
return ['success' => true]; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
return [ |
||||||
|
'success' => false, |
||||||
|
'errorCodes' => $answer['error-codes'], |
||||||
|
]; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Generate CAPTCHA HTML |
||||||
|
* |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
public function generateCaptchaHtml() |
||||||
|
{ |
||||||
|
$content = ''; |
||||||
|
|
||||||
|
if ($this->config->loginProtection && $this->config->captchaEnabled) |
||||||
|
{ |
||||||
|
$loginAttemptModel = new LoginAttemptModel(); |
||||||
|
|
||||||
|
if ($loginAttemptModel->find() >= $this->config->captchaLoginAttempts) |
||||||
|
{ |
||||||
|
$siteKey = $this->config->captchaSiteKey; |
||||||
|
|
||||||
|
if ($this->config->captchaType === 'recaptcha') |
||||||
|
{ |
||||||
|
$content .= "<div class='g-recaptcha' data-sitekey='{$siteKey}'></div>"; |
||||||
|
$content = '<script src="https://www.google.com/recaptcha/api.js" async defer></script>'; |
||||||
|
} |
||||||
|
else if ($this->config->captchaType === 'hcaptcha') |
||||||
|
{ |
||||||
|
$content = "<div class='h-captcha' data-sitekey='{$siteKey}'></div>"; |
||||||
|
$content .= '<script src="https://hcaptcha.com/1/api.js" async defer></script>'; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return $content; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Submit GET |
||||||
|
* |
||||||
|
* Submits an HTTP GET to a CAPTCHA server. |
||||||
|
* |
||||||
|
* @param string $url URL path to CAPTCHA server. |
||||||
|
* @param array $data Array of parameters to be sent. |
||||||
|
* |
||||||
|
* @return array response |
||||||
|
*/ |
||||||
|
private function _submitGet($url, $data) |
||||||
|
{ |
||||||
|
$client = \Config\Services::curlrequest(); |
||||||
|
$response = $client->request('GET', $url, [ |
||||||
|
'query' => $data, |
||||||
|
]); |
||||||
|
|
||||||
|
return $response->getBody(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Submit POST |
||||||
|
* |
||||||
|
* Submits an HTTP POST to a CAPTCHA server. |
||||||
|
* |
||||||
|
* @param string $url URL path to CAPTCHA server. |
||||||
|
* @param array $data Array of parameters to be sent. |
||||||
|
* |
||||||
|
* @return array response |
||||||
|
*/ |
||||||
|
private function _submitPost($url, $data) |
||||||
|
{ |
||||||
|
$client = \Config\Services::curlrequest(); |
||||||
|
$response = $client->request('POST', $url, [ |
||||||
|
'query' => $data, |
||||||
|
]); |
||||||
|
|
||||||
|
return $response->getBody(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,153 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* CodeIgniter-Aauth |
||||||
|
* |
||||||
|
* Aauth is a User Authorization Library for CodeIgniter 4.x, which aims to make |
||||||
|
* easy some essential jobs such as login, permissions and access operations. |
||||||
|
* Despite ease of use, it has also very advanced features like grouping, |
||||||
|
* access management, public access etc.. |
||||||
|
* |
||||||
|
* @package CodeIgniter-Aauth |
||||||
|
* @author Emre Akay |
||||||
|
* @author Raphael "REJack" Jackstadt |
||||||
|
* @copyright 2014-2019 Emre Akay |
||||||
|
* @license https://opensource.org/licenses/MIT MIT License |
||||||
|
* @link https://github.com/emreakay/CodeIgniter-Aauth |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace App\Libraries\Aauth; |
||||||
|
|
||||||
|
use \App\Models\Aauth\UserVariableModel; |
||||||
|
|
||||||
|
use OTPHP\TOTP as OTPHP_TOTP; |
||||||
|
|
||||||
|
/** |
||||||
|
* Aauth TOTP |
||||||
|
* |
||||||
|
* Class for handling 2-factor authentication |
||||||
|
* |
||||||
|
* @package CodeIgniter-Aauth |
||||||
|
*/ |
||||||
|
class TOTP extends \App\Libraries\Aauth |
||||||
|
{ |
||||||
|
/** |
||||||
|
* Update User TOTP Secret |
||||||
|
* |
||||||
|
* @param integer $userId User Id |
||||||
|
* @param string $secret Secret Key |
||||||
|
* |
||||||
|
* @return boolean |
||||||
|
*/ |
||||||
|
public function updateUserTotpSecret(int $userId = null, string $secret) |
||||||
|
{ |
||||||
|
if (! $userId) |
||||||
|
{ |
||||||
|
$userId = (int) @$this->session->user['id']; |
||||||
|
} |
||||||
|
|
||||||
|
$userVariableModel = new UserVariableModel(); |
||||||
|
|
||||||
|
return $userVariableModel->save($userId, 'totp_secret', $secret, true); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Generate Unique TOTP Secret |
||||||
|
* |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
public function generateUniqueTotpSecret() |
||||||
|
{ |
||||||
|
$stop = false; |
||||||
|
|
||||||
|
while (! $stop) |
||||||
|
{ |
||||||
|
$secret = OTPHP_TOTP::create(); |
||||||
|
|
||||||
|
if ($userVariable !== $userVariableModel->where(['data_key' => 'totp_secret', 'data_value' => $secret, 'system' => 1])->getFirstRow('array')) |
||||||
|
{ |
||||||
|
$stop = true; |
||||||
|
|
||||||
|
return $secret; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Generate TOTP QR Code |
||||||
|
* |
||||||
|
* Generate TOTP QR Code URI by Secret |
||||||
|
* |
||||||
|
* @param string $secret Secret Key |
||||||
|
* |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
public function generateTotpQrCode(string $secret) |
||||||
|
{ |
||||||
|
$totp = OTPHP_TOTP::create($secret); |
||||||
|
|
||||||
|
return $totp->getQrCodeUri(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Verify user TOTP Code |
||||||
|
* |
||||||
|
* @param integer $totpCode TOTP Code |
||||||
|
* @param string $userId User Id |
||||||
|
* |
||||||
|
* @return boolean |
||||||
|
*/ |
||||||
|
public function verifyUserTotpCode(int $totpCode, string $userId = null) |
||||||
|
{ |
||||||
|
if (! $this->isTotpRequired()) |
||||||
|
{ |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
if (! $userId) |
||||||
|
{ |
||||||
|
$userId = (int) @$this->session->user['id']; |
||||||
|
} |
||||||
|
|
||||||
|
if (empty($totpCode)) |
||||||
|
{ |
||||||
|
$this->error(lang('Aauth.requiredTOTPCode')); |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
$userVariableModel = new UserVariableModel(); |
||||||
|
|
||||||
|
$totpSecret = $userVariableModel->find($userId, 'totp_secret', true); |
||||||
|
$totp = OTPHP_TOTP::create($totpSecret); |
||||||
|
|
||||||
|
if (! $totp->verify($totpCode)) |
||||||
|
{ |
||||||
|
$this->error(lang('Aauth.invalidTOTPCode')); |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
unset($_SESSION['user']['totp_required']); |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* IS TOTP Required |
||||||
|
* |
||||||
|
* Checks if User need TOTP verification. |
||||||
|
* |
||||||
|
* @return boolean |
||||||
|
*/ |
||||||
|
public function isTotpRequired() |
||||||
|
{ |
||||||
|
if (@$this->session->user['totp_required']) |
||||||
|
{ |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue