Improve Security (2) - reCAPTCHA V2 for AppGini

Got something cool to share with AppGini users? Feel free to post it here!
Post Reply
sathukorala
AppGini Super Hero
AppGini Super Hero
Posts: 121
Joined: 2020-02-16 16:29

Improve Security (2) - reCAPTCHA V2 for AppGini

Post by sathukorala » 2020-05-10 08:36

In this, I will show you how to implement reCAPTCHA V2 for AppGini which will give you a following like login form
14.png
14.png (28.56 KiB) Viewed 30557 times


The steps to do so are the following:

1. Get the reCAPTCHA keys from the Google reCAPTCHA from https://www.google.com/recaptcha
Do not forget to get V2 keys by selecting options like below. Do not forget to add Domains to it (E.g. If you are testing on localhost add localhost to it)

12.png
12.png (15.67 KiB) Viewed 30557 times
13.png
13.png (25.16 KiB) Viewed 30557 times

2. Add below script in header.php file just below <head> tag

Code: Select all

<script src="https://www.google.com/recaptcha/api.js" async defer></script>
3. Replace function logInMember() in incCommon.php and add the following code. Add YOUR-SECRET-KEY to it

Code: Select all

function logInMember(){
		$redir = 'index.php';
		if($_POST['signIn'] != ''){
			if(isset($_POST['signIn']) && !empty($_POST['signIn'])){
				if(isset($_POST['g-recaptcha-response']) && !empty($_POST['g-recaptcha-response'])){
				//your site secret key
				$secret = 'YOUR-SECRET-KEY';
				//get verify response data
				$verifyResponse = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret='.$secret.'&response='.$_POST['g-recaptcha-response']);
				$responseData = json_decode($verifyResponse);
					if($responseData->success == true){

						if($_POST['username'] != '' && $_POST['password'] != '') {
							$username = makeSafe(strtolower($_POST['username']));
							$hash = sqlValue("select passMD5 from membership_users where lcase(memberID)='{$username}' and isApproved=1 and isBanned=0");
							$password = $_POST['password'];

							if(password_match($password, $hash)) {
								$_SESSION['memberID'] = $username;
								$_SESSION['memberGroupID'] = sqlValue("SELECT `groupID` FROM `membership_users` WHERE LCASE(`memberID`)='{$username}'");

									if($_POST['rememberMe'] == 1) {
										RememberMe::login($username);
									}else{
										RememberMe::delete();
										}
										
									// harden user's password hash
									password_harden($username, $password, $hash);

									// hook: login_ok
									if(function_exists('login_ok')) {
										$args=array();
											if(!$redir=login_ok(getMemberInfo(), $args)) {
												$redir='index.php';
											}
									}	
								redirect($redir);
								exit;
							}
						}
						
						// hook: login_failed
						if(function_exists('login_failed')) {
						$args=array();
						login_failed(array(
						'username' => $_POST['username'],
						'password' => $_POST['password'],
						'IP' => $_SERVER['REMOTE_ADDR']
						), $args);
						}

						if(!headers_sent()) header('HTTP/1.0 403 Forbidden');
						redirect("index.php?loginFailed=1");
						exit;
						
					}
					
				} else {
					$_SESSION['custom_err_msg']= "Please click on reCAPTCHA to login";
					if(!headers_sent()) header('HTTP/1.0 403 Forbidden');
					redirect("index.php?loginFailed=1");
					exit;
					}
			}		
		}		
		// do we have a JWT auth header? 
			jwt_check_login();

			if(!empty($_SESSION['memberID']) && !empty($_SESSION['memberGroupID'])) return;

			// check if a rememberMe cookie exists and sign in user if so 
			if(RememberMe::check()) {
			$username = makeSafe(strtolower(RememberMe::user()));
			$_SESSION['memberID'] = $username;
			$_SESSION['memberGroupID'] = sqlValue("SELECT `groupID` FROM `membership_users` WHERE LCASE(`memberID`)='{$username}'");
			}
	}
	
4. Add the following division just above signIn button <div class="row"> in login.php file. Add YOUR-SITE-KEY to it

Code: Select all

<div class="row" align="center">					
	<div class="g-recaptcha" data-sitekey="YOUR-SITE-KEY"></div>
	<br/>						
</div>
5. Add the following code to hooks > header-extras.php file if not already added for another purpose

Code: Select all

<?php	
if (isset($_SESSION['custom_err_msg'])) {
	$customError ='<div id="customErrorMessage" class="custmErrMsg alert alert-dismissable alert-danger">'.$_SESSION['custom_err_msg'].'</div>';
	echo $customError;			
	if ($_SESSION['custom_err_shown'] == 1){
		unset($_SESSION['custom_err_msg']);
		$_SESSION['custom_err_shown'] = 0;
	} 
	else {
		$_SESSION['custom_err_shown'] = 1;
	}				
}
?>
That's all. Now you can get extra security through google reCAPTCHA V2.

****If you want the reCAPTCHA v3 then please visit the following thread (published by: mghielmi)
viewtopic.php?f=8&t=3284

****Improve Security (1) - Session Control for AppGini can be done as given in the following thread
viewtopic.php?f=4&t=3632

User avatar
D Oliveira
AppGini Super Hero
AppGini Super Hero
Posts: 347
Joined: 2018-03-04 09:30
Location: David

Re: Improve Security (2) - reCAPTCHA V2 for AppGini

Post by D Oliveira » 2020-05-10 23:55

Simply amazing mate, very useful, implemented here ;)

Keep up the great work, cheers!

sathukorala
AppGini Super Hero
AppGini Super Hero
Posts: 121
Joined: 2020-02-16 16:29

Re: Improve Security (2) - reCAPTCHA V2 for AppGini

Post by sathukorala » 2020-05-11 05:46

D Oliveira wrote:
2020-05-10 23:55
Simply amazing mate, very useful, implemented here ;)

Keep up the great work, cheers!
Thank you so much for the appreciation :D :D :D
Glad to hear more and more implementations to improve security

jmacdougall
Posts: 26
Joined: 2015-11-02 01:22

Re: Improve Security (2) - reCAPTCHA V2 for AppGini

Post by jmacdougall » 2021-08-15 16:40

Thank you so much for this! It works perfectly. I am curious and please forgive me for such a dumb question as I am a novice, how do I prevent my uploaded updates from overwriting these files?

Thank you!
Jeff :D
Jeff MacDougall

User avatar
onoehring
AppGini Super Hero
AppGini Super Hero
Posts: 1156
Joined: 2019-05-21 22:42
Location: Germany
Contact:

Re: Improve Security (2) - reCAPTCHA V2 for AppGini

Post by onoehring » 2021-08-22 09:55

Hi Jeff,

as most files when regenerated do not actually change, I created a subdirectory "from_root" where I place files (and folders if needed) that need to be replaced after regeneration. Once the app has been regenerated I simply copy the whole contents from "from_root" to the root of the app - done.

Maybe this helps
Olaf

Post Reply