-
Notifications
You must be signed in to change notification settings - Fork 133
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #601 from sammyskills/force-password-reset
Feat: Force password reset
- Loading branch information
Showing
12 changed files
with
401 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# Forcing Password Reset | ||
|
||
Depending on the scope of your application, there may be times when you'll decide that it is absolutely necessary to force user(s) to reset their password. This practice is common when you find out that users of your application do not use strong passwords OR there is a reasonable suspicion that their passwords have been compromised. This guide provides you with ways to achieve this. | ||
|
||
- [Forcing Password Reset](#forcing-password-reset) | ||
- [Available Methods](#available-methods) | ||
- [Check if a User Requires Password Reset](#check-if-a-user-requires-password-reset) | ||
- [Force Password Reset On a User](#force-password-reset-on-a-user) | ||
- [Removing Password Reset Flag On a User](#removing-password-reset-flag-on-a-user) | ||
- [Force Password Reset On Multiple Users](#force-password-reset-on-multiple-users) | ||
- [Force Password Reset On All Users](#force-password-reset-on-all-users) | ||
|
||
## Available Methods | ||
|
||
Shield provides a way to enforce password resets throughout your application. The `Resettable` trait on the `User` entity and the `UserIdentityModel` provides the following methods to do so. | ||
|
||
### Check if a User Requires Password Reset | ||
|
||
When you need to check if a user requires password reset, you can do so using the `requiresPasswordReset()` method on the `User` entity. Returns boolean `true`/`false`. | ||
|
||
```php | ||
if ($user->requiresPasswordReset()) { | ||
//... | ||
} | ||
``` | ||
|
||
### Force Password Reset On a User | ||
|
||
To force password reset on a user, you can do so using the `forcePasswordReset()` method on the `User` entity. | ||
|
||
```php | ||
$user->forcePasswordReset(); | ||
``` | ||
|
||
### Remove Force Password Reset Flag On a User | ||
|
||
Undoing or removing the force password reset flag on a user can be done using the `undoForcePasswordReset()` method on the `User` entity. | ||
|
||
```php | ||
$user->undoForcePasswordReset(); | ||
``` | ||
|
||
### Force Password Reset On Multiple Users | ||
|
||
If you see the need to force password reset for more than one user, the `forceMultiplePasswordReset()` method of the `UserIdentityModel` allows you to do this easily. It accepts an `Array` of user IDs. | ||
|
||
```php | ||
use CodeIgniter\Shield\Models\UserIdentityModel; | ||
... | ||
... | ||
... | ||
$identities = new UserIdentityModel(); | ||
$identities->forceMultiplePasswordReset([1,2,3,4]); | ||
``` | ||
|
||
### Force Password Reset On All Users | ||
|
||
If you suspect a security breach or compromise in the passwords of your users, you can easily force password reset on all the users of your application using the `forceGlobalPasswordReset()` method of the `UserIdentityModel`. | ||
|
||
```php | ||
use CodeIgniter\Shield\Models\UserIdentityModel; | ||
... | ||
... | ||
... | ||
$identities = new UserIdentityModel(); | ||
$identities->forceGlobalPasswordReset(); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace CodeIgniter\Shield\Filters; | ||
|
||
use CodeIgniter\Filters\FilterInterface; | ||
use CodeIgniter\HTTP\IncomingRequest; | ||
use CodeIgniter\HTTP\RedirectResponse; | ||
use CodeIgniter\HTTP\RequestInterface; | ||
use CodeIgniter\HTTP\Response; | ||
use CodeIgniter\HTTP\ResponseInterface; | ||
use CodeIgniter\Shield\Authentication\Authenticators\Session; | ||
|
||
/** | ||
* Force Password Reset Filter. | ||
*/ | ||
class ForcePasswordResetFilter implements FilterInterface | ||
{ | ||
/** | ||
* Checks if a logged in user should reset their | ||
* password, and then redirect to the appropriate | ||
* page. | ||
* | ||
* @param array|null $arguments | ||
* | ||
* @return RedirectResponse|void | ||
*/ | ||
public function before(RequestInterface $request, $arguments = null) | ||
{ | ||
if (! $request instanceof IncomingRequest) { | ||
return; | ||
} | ||
|
||
helper('setting'); | ||
|
||
/** @var Session $authenticator */ | ||
$authenticator = auth('session')->getAuthenticator(); | ||
|
||
if ($authenticator->loggedIn() && $authenticator->getUser()->requiresPasswordReset()) { | ||
return redirect()->to(config('Auth')->forcePasswordResetRedirect()); | ||
} | ||
} | ||
|
||
/** | ||
* We don't have anything to do here. | ||
* | ||
* @param Response|ResponseInterface $response | ||
* @param array|null $arguments | ||
*/ | ||
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null): void | ||
{ | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace CodeIgniter\Shield\Traits; | ||
|
||
use CodeIgniter\Shield\Authentication\Authenticators\Session; | ||
use CodeIgniter\Shield\Models\UserIdentityModel; | ||
|
||
/** | ||
* Reusable methods to help the | ||
* enforcing of password resets | ||
*/ | ||
trait Resettable | ||
{ | ||
/** | ||
* Returns true|false based on the value of the | ||
* force reset column of the user's identity. | ||
*/ | ||
public function requiresPasswordReset(): bool | ||
{ | ||
$identity_model = model(UserIdentityModel::class); | ||
$identity = $identity_model->getIdentityByType($this, Session::ID_TYPE_EMAIL_PASSWORD); | ||
|
||
return $identity->force_reset; | ||
} | ||
|
||
/** | ||
* Force password reset | ||
*/ | ||
public function forcePasswordReset(): void | ||
{ | ||
// Do nothing if user already requires reset | ||
if ($this->requiresPasswordReset()) { | ||
return; | ||
} | ||
|
||
// Set force_reset to true | ||
$identity_model = model(UserIdentityModel::class); | ||
$identity_model->set('force_reset', 1); | ||
$identity_model->where(['user_id' => $this->id, 'type' => Session::ID_TYPE_EMAIL_PASSWORD]); | ||
$identity_model->update(); | ||
} | ||
|
||
/** | ||
* Undo Force password reset | ||
*/ | ||
public function undoForcePasswordReset(): void | ||
{ | ||
// If user doesn't require password reset, do nothing | ||
if ($this->requiresPasswordReset() === false) { | ||
return; | ||
} | ||
|
||
// Set force_reset to false | ||
$identity_model = model(UserIdentityModel::class); | ||
$identity_model->set('force_reset', 0); | ||
$identity_model->where(['user_id' => $this->id, 'type' => Session::ID_TYPE_EMAIL_PASSWORD]); | ||
$identity_model->update(); | ||
} | ||
} |
Oops, something went wrong.