Move the 'authenticate' hook deeper into the authentication flow so that password authentication addons are consulted whenever a user's password needs confirming.
This commit is contained in:
		
					parent
					
						
							
								6434d018c8
							
						
					
				
			
			
				commit
				
					
						9ddaabc22d
					
				
			
		
					 3 changed files with 51 additions and 34 deletions
				
			
		|  | @ -666,8 +666,13 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep- | |||
|     Hook::callAll('event_updated', $event['id']); | ||||
|     Hook::callAll("event_created", $event['id']); | ||||
| 
 | ||||
| ### src/Model/Register.php | ||||
| 
 | ||||
|     Hook::callAll('authenticate', $addon_auth); | ||||
| 
 | ||||
| ### src/Model/User.php | ||||
| 
 | ||||
|     Hook::callAll('authenticate', $addon_auth); | ||||
|     Hook::callAll('register_account', $uid); | ||||
|     Hook::callAll('remove_user', $user); | ||||
| 
 | ||||
|  | @ -675,6 +680,22 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep- | |||
| 
 | ||||
|     Hook::callAll('lockview_content', $item); | ||||
| 
 | ||||
| ### src/Module/Settings/Delegation.php | ||||
| 
 | ||||
|     Hook::callAll('authenticate', $addon_auth); | ||||
| 
 | ||||
| ### src/Module/Settings/TwoFactor/Index.php | ||||
| 
 | ||||
|     Hook::callAll('authenticate', $addon_auth); | ||||
| 
 | ||||
| ### src/Security/Authenticate.php | ||||
| 
 | ||||
|     Hook::callAll('authenticate', $addon_auth); | ||||
| 
 | ||||
| ### src/Security/ExAuth.php | ||||
| 
 | ||||
|     Hook::callAll('authenticate', $addon_auth); | ||||
| 
 | ||||
| ### src/Content/ContactBlock.php | ||||
| 
 | ||||
|     Hook::callAll('contact_block_end', $arr); | ||||
|  |  | |||
|  | @ -544,6 +544,24 @@ class User | |||
| 			} | ||||
| 
 | ||||
| 			return $user['uid']; | ||||
| 		} else { | ||||
| 			$addon_auth = [ | ||||
| 				'username'      => $user['nickname'], | ||||
| 				'password'      => $password, | ||||
| 				'authenticated' => 0, | ||||
| 				'user_record'   => null | ||||
| 			]; | ||||
| 
 | ||||
| 			/* | ||||
| 			 * An addon indicates successful login by setting 'authenticated' to non-zero value and returning a user record | ||||
| 			 * Addons should never set 'authenticated' except to indicate success - as hooks may be chained | ||||
| 			 * and later addons should not interfere with an earlier one that succeeded. | ||||
| 			 */ | ||||
| 			Hook::callAll('authenticate', $addon_auth); | ||||
| 
 | ||||
| 			if ($addon_auth['authenticated'] && $addon_auth['user_record']) { | ||||
| 				return $user['uid']; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		throw new HTTPException\ForbiddenException(DI::l10n()->t('Login failed')); | ||||
|  | @ -584,7 +602,7 @@ class User | |||
| 			if (is_int($user_info)) { | ||||
| 				$user = DBA::selectFirst( | ||||
| 					'user', | ||||
| 					['uid', 'password', 'legacy_password'], | ||||
| 					['uid', 'nickname', 'password', 'legacy_password'], | ||||
| 					[ | ||||
| 						'uid' => $user_info, | ||||
| 						'blocked' => 0, | ||||
|  | @ -594,7 +612,7 @@ class User | |||
| 					] | ||||
| 				); | ||||
| 			} else { | ||||
| 				$fields = ['uid', 'password', 'legacy_password']; | ||||
| 				$fields = ['uid', 'nickname', 'password', 'legacy_password']; | ||||
| 				$condition = [ | ||||
| 					"(`email` = ? OR `username` = ? OR `nickname` = ?)
 | ||||
| 					AND NOT `blocked` AND NOT `account_expired` AND NOT `account_removed` AND `verified`",
 | ||||
|  |  | |||
|  | @ -239,34 +239,12 @@ class Authentication | |||
| 	{ | ||||
| 		$record = null; | ||||
| 
 | ||||
| 		$addon_auth = [ | ||||
| 			'username'      => $username, | ||||
| 			'password'      => $password, | ||||
| 			'authenticated' => 0, | ||||
| 			'user_record'   => null | ||||
| 		]; | ||||
| 
 | ||||
| 		/* | ||||
| 		 * An addon indicates successful login by setting 'authenticated' to non-zero value and returning a user record | ||||
| 		 * Addons should never set 'authenticated' except to indicate success - as hooks may be chained | ||||
| 		 * and later addons should not interfere with an earlier one that succeeded. | ||||
| 		 */ | ||||
| 		Hook::callAll('authenticate', $addon_auth); | ||||
| 
 | ||||
| 		try { | ||||
| 			if ($addon_auth['authenticated']) { | ||||
| 				$record = $addon_auth['user_record']; | ||||
| 
 | ||||
| 				if (empty($record)) { | ||||
| 					throw new Exception($this->l10n->t('Login failed.')); | ||||
| 				} | ||||
| 			} else { | ||||
| 			$record = $this->dba->selectFirst( | ||||
| 				'user', | ||||
| 				[], | ||||
| 				['uid' => User::getIdFromPasswordAuthentication($username, $password)] | ||||
| 			); | ||||
| 			} | ||||
| 		} catch (Exception $e) { | ||||
| 			$this->logger->warning('authenticate: failed login attempt', ['action' => 'login', 'username' => Strings::escapeTags($username), 'ip' => $_SERVER['REMOTE_ADDR']]); | ||||
| 			notice($this->l10n->t('Login failed. Please check your credentials.')); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue