Skip to content

Commit

Permalink
Release 3.6.0
Browse files Browse the repository at this point in the history
  • Loading branch information
glewe committed Nov 4, 2024
1 parent 6387b26 commit 0cb9f83
Show file tree
Hide file tree
Showing 41 changed files with 1,435 additions and 733 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ quite large. I decided to build CI4-Auth based on Myth-Auth, changing and adding
## Requirements

- PHP 8.1+
- CodeIgniter 4.4+
- CodeIgniter 4.5+
- [RobThree TwoFactorAuth](http://github.com/RobThree/TwoFactorAuth)

## Features
Expand Down
2 changes: 1 addition & 1 deletion src/Authentication/Activators/BaseActivator.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public function setConfig(AuthConfig $config) {
* @return object
*/
public function getActivatorSettings() {
return (object)$this->config->userActivators[ static::class ];
return (object)$this->config->userActivators[static::class];
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Authentication/Activators/EmailActivator.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public function send(User $user = null): bool {
$sent = $email->setFrom($settings->fromEmail ?? $config->fromEmail, $settings->fromName ?? $config->fromName)
->setTo($user->email)
->setSubject(lang('Auth.activation.subject'))
->setMessage(view($this->config->views[ 'emailActivation' ], [ 'hash' => $user->activate_hash ]))
->setMessage(view($this->config->views['emailActivation'], [ 'hash' => $user->activate_hash ]))
->setMailType('html')
->send();

Expand Down
149 changes: 89 additions & 60 deletions src/Authentication/AuthenticationBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,39 +37,46 @@ class AuthenticationBase {
*/
protected $config;

//-------------------------------------------------------------------------

/**
* --------------------------------------------------------------------------
* Constructor.
* --------------------------------------------------------------------------
*/
public function __construct($config) {
$this->config = $config;
}

//-------------------------------------------------------------------------

/**
* --------------------------------------------------------------------------
* Error.
* --------------------------------------------------------------------------
*
* Returns the current error, if any.
*
* @return string
*/
public function error() {
public function error(): string {
return $this->error;
}

//-------------------------------------------------------------------------

/**
* --------------------------------------------------------------------------
* Silent.
* --------------------------------------------------------------------------
*
* Whether to continue instead of throwing exceptions, as defined in config.
*
* @return bool
*/
public function silent() {
public function silent(): bool {
return (bool)$this->config->silent;
}

//-------------------------------------------------------------------------

/**
* --------------------------------------------------------------------------
* Login.
* --------------------------------------------------------------------------
*
* Logs a user into the system.
* NOTE: does not perform validation. All validation should be done prior to
* using the login method, incl. 2FA.
Expand Down Expand Up @@ -132,9 +139,11 @@ public function login(User $user = null, bool $remember = false): bool {
return true;
}

//-------------------------------------------------------------------------

/**
* --------------------------------------------------------------------------
* Is Logged In.
* --------------------------------------------------------------------------
*
* Checks to see if the user is logged in.
*
* @return bool
Expand All @@ -146,43 +155,46 @@ public function isLoggedIn(): bool {
if ($this->user instanceof User) {
return true;
}

if ($userID = session('logged_in')) {
//
// Store our current user object
//
$this->user = $this->userModel->find($userID);
return $this->user instanceof User;
}

return false;
}


//-------------------------------------------------------------------------

/**
* --------------------------------------------------------------------------
* Login By ID.
* --------------------------------------------------------------------------
*
* Logs a user into the system by their ID.
*
* @param int $id
* @param int $id
* @param bool $remember
*
* @return bool
*/
public function loginByID(int $id, bool $remember = false) {
public function loginByID(int $id, bool $remember = false): bool {
$user = $this->retrieveUser([ 'id' => $id ]);

if (empty($user)) {
throw UserNotFoundException::forUserID($id);
}

return $this->login($user, $remember);
}

//-------------------------------------------------------------------------

/**
* --------------------------------------------------------------------------
* Logout.
* --------------------------------------------------------------------------
*
* Logs a user out of the system.
*
* @return void
*/
public function logout() {
public function logout(): void {
helper('cookie');

//
Expand All @@ -191,8 +203,8 @@ public function logout() {
//
if (isset($_SESSION)) {
foreach ($_SESSION as $key => $value) {
$_SESSION[ $key ] = NULL;
unset($_SESSION[ $key ]);
$_SESSION[$key] = NULL;
unset($_SESSION[$key]);
}
}

Expand Down Expand Up @@ -224,20 +236,22 @@ public function logout() {
}
}

//-------------------------------------------------------------------------

/**
* --------------------------------------------------------------------------
* Record Login Attempt.
* --------------------------------------------------------------------------
*
* Record a login attempt
*
* @param string $email
* @param string $email
* @param string|null $ipAddress
* @param int|null $userID
* @param bool $success
* @param string $info
* @param int|null $userID
* @param bool $success
* @param string $info
*
* @return bool|int|string
*/
public function recordLoginAttempt(string $email, string $ipAddress = null, int $userID = null, bool $success, string $info) {
public function recordLoginAttempt(string $email, string $ipAddress = null, int $userID = null, bool $success, string $info): bool|int|string {
return $this->loginModel->insert([
'ip_address' => $ipAddress,
'email' => $email,
Expand All @@ -248,19 +262,23 @@ public function recordLoginAttempt(string $email, string $ipAddress = null, int
]);
}

//-------------------------------------------------------------------------

/**
* --------------------------------------------------------------------------
* Remember User.
* --------------------------------------------------------------------------
*
* Generates a timing-attack safe remember me token and stores the necessary
* info in the db and a cookie.
*
* @see https://paragonie.com/blog/2015/04/secure-authentication-php-with-long-term-persistence
*
* @param int $userID
*
* @return void
*
* @throws \Exception
*/
public function rememberUser(int $userID) {
public function rememberUser(int $userID): void {
$selector = bin2hex(random_bytes(12));
$validator = bin2hex(random_bytes(20));
$expires = date('Y-m-d H:i:s', time() + $this->config->rememberLength);
Expand Down Expand Up @@ -293,24 +311,28 @@ public function rememberUser(int $userID) {
);
}

//-------------------------------------------------------------------------

/**
* --------------------------------------------------------------------------
* Refresh Remember.
* --------------------------------------------------------------------------
*
* Sets a new validator for this user/selector. This allows a one-time use
* of remember-me tokens, but still allows a user to be remembered on
* multiple browsers/devices.
*
* @param int $userID
* @param int $userID
* @param string $selector
*
* @return void
*/
public function refreshRemember(int $userID, string $selector) {
public function refreshRemember(int $userID, string $selector): void {
$existing = $this->loginModel->getRememberToken($selector);

//
// No matching record? Shouldn't happen, but remember the user now.
//
if (empty($existing)) {
return $this->rememberUser($userID);
$this->rememberUser($userID);
}

//
Expand Down Expand Up @@ -342,77 +364,84 @@ public function refreshRemember(int $userID, string $selector) {
);
}

//------------------------------------------------------------------------

/**
* --------------------------------------------------------------------------
* Id.
* --------------------------------------------------------------------------
*
* Returns the User ID for the current logged in user.
*
* @return int|null
*/
public function id() {
public function id(): ?int {
return $this->user->id ?? null;
}

//-------------------------------------------------------------------------

/**
* --------------------------------------------------------------------------
* User.
* --------------------------------------------------------------------------
*
* Returns the User instance for the current logged in user.
*
* @return User|null
*/
public function user() {
public function user(): ?User {
return $this->user;
}

//-------------------------------------------------------------------------

/**
* --------------------------------------------------------------------------
* Retrieve User.
* --------------------------------------------------------------------------
*
* Grabs the current user from the database.
*
* @param array $wheres
*
* @return array|null|object
*/
public function retrieveUser(array $wheres) {
public function retrieveUser(array $wheres): array|null|object {
if (!$this->userModel instanceof Model) {
throw AuthException::forInvalidModel('User');
}

$user = $this->userModel
->where($wheres)
->first();

$user = $this->userModel->where($wheres)->first();
return $user;
}

//=========================================================================
// Model Setters
//=========================================================================

//-------------------------------------------------------------------------
/**
* --------------------------------------------------------------------------
* Set User Model.
* --------------------------------------------------------------------------
*
* Sets the model that should be used to work with user accounts.
*
* @param Model $model
*
* @return $this
*/
public function setUserModel(Model $model) {
public function setUserModel(Model $model): AuthenticationBase {
$this->userModel = $model;
return $this;
}

//-------------------------------------------------------------------------

/**
* --------------------------------------------------------------------------
* Check.
* --------------------------------------------------------------------------
*
* Sets the model that should be used to record login attempts (but failed
* and successful).
*
* @param LoginModel $model
*
* @return $this
*/
public function setLoginModel(Model $model) {
public function setLoginModel(Model $model): AuthenticationBase {
$this->loginModel = $model;
return $this;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Authentication/AuthenticatorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ interface AuthenticatorInterface {
* Attempts to validate the credentials and log a user in.
*
* @param array $credentials
* @param bool $remember Should we remember the user (if enabled)
* @param bool $remember Should we remember the user (if enabled)
*
* @return bool
*/
Expand All @@ -27,7 +27,7 @@ public function check(): bool;
* Unlike `attempt()`, will not log the user into the system.
*
* @param array $credentials
* @param bool $returnUser
* @param bool $returnUser
*
* @return bool|User
*/
Expand Down
Loading

0 comments on commit 0cb9f83

Please sign in to comment.