https://github.com/andrej-griniuk/cakephp-two-factor-auth
Two-factor authentication plugin
https://github.com/andrej-griniuk/cakephp-two-factor-auth
Last synced: 7 days ago
JSON representation
Two-factor authentication plugin
- Host: GitHub
- URL: https://github.com/andrej-griniuk/cakephp-two-factor-auth
- Owner: andrej-griniuk
- License: mit
- Created: 2016-02-12T06:42:02.000Z (about 9 years ago)
- Default Branch: master
- Last Pushed: 2024-06-19T14:57:58.000Z (11 months ago)
- Last Synced: 2024-11-12T05:37:07.259Z (6 months ago)
- Language: PHP
- Size: 101 KB
- Stars: 37
- Watchers: 7
- Forks: 11
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-cakephp - TwoFactorAuth plugin - Allows two factor authentication using Google Authenticator or similar app to generate one-time codes. Based on [RobThree/TwoFactorAuth](https://github.com/RobThree/TwoFactorAuth) library. (Authentication and Authorization)
README
[](https://travis-ci.org/andrej-griniuk/cakephp-two-factor-auth)
[](https://codecov.io/gh/andrej-griniuk/cakephp-two-factor-auth)
[](LICENSE)# TwoFactorAuth plugin for CakePHP
This plugin provides two factor authentication functionality using [RobThree/TwoFactorAuth](https://github.com/RobThree/TwoFactorAuth) library.
Basically, it works similar way CakePHP `FormAuthenticate` does. After submitting correct username/password, if the user has `secret` field set, he will be asked to enter a one-time code.
**Attention:** it only provides authenticate provider and component and does not take care of users signup, management etc.## Requirements
- CakePHP 5.0+ (use ***^1.3*** version for CakePHP <3.7, ***^2.0*** version for CakePHP 3.x, ***^3.0*** version for CakePHP 4.x)
## Installation
You can install this plugin into your CakePHP application using [Composer][composer].
```bash
composer require andrej-griniuk/cakephp-two-factor-auth
```## Usage
First of all you need to add `secret` field to your users table (field name can be changed to `TwoFactorAuth.Form` authenticator configuration).
```sql
ALTER TABLE `users` ADD `secret` VARCHAR(255) NULL;
```Second, you need to load the plugin in your Application.php
```php
$this->addPlugin('TwoFactorAuth');
```Alternatively, execute the following line:
```bash
bin/cake plugin load TwoFactorAuth
```You can see the default config values [here](https://github.com/andrej-griniuk/cakephp-two-factor-auth/blob/master/src/Authenticator/TwoFactorFormAuthenticator.php) and find out what do they mean [here](https://github.com/RobThree/TwoFactorAuth#usage). To overwrite them, pass them as `TwoFactorForm` authenticator values.
Then you need to set up authentication in your Application.php as you would [normally do it](https://book.cakephp.org/authentication/2/en/index.html#getting-started), but using `TwoFactorForm` authenticator instead of `Form`, e.g.:
```php
class Application extends BaseApplication implements AuthenticationServiceProviderInterface
{
public function bootstrap(): void
{
// Call parent to load bootstrap from files.
parent::bootstrap();$this->addPlugin('TwoFactorAuth');
$this->addPlugin('Authentication');
}public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
{
// Various other middlewares for error handling, routing etc. added here.// Create an authentication middleware object
$authentication = new AuthenticationMiddleware($this);// Add the middleware to the middleware queue.
// Authentication should be added *after* RoutingMiddleware.
// So that subdirectory information and routes are loaded.
$middlewareQueue->add($authentication);return $middlewareQueue;
}public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
{
$service = new AuthenticationService();
$service->setConfig([
'unauthenticatedRedirect' => '/users/login',
'queryParam' => 'redirect',
]);$fields = [
'username' => 'username',
'password' => 'password'
];// Load the authenticators, you want session first
$service->loadAuthenticator('Authentication.Session');
$service->loadAuthenticator('TwoFactorAuth.TwoFactorForm', [
'fields' => $fields,
'loginUrl' => '/users/login'
]);// Load identifiers
$service->loadIdentifier('Authentication.Password', compact('fields'));return $service;
}
}
```Next, in your AppController load the `Authentication` and `TwoFactorAuth` components:
```php
// in src/Controller/AppController.php
public function initialize()
{
parent::initialize();$this->loadComponent('Authentication.Authentication');
$this->loadComponent('TwoFactorAuth.TwoFactorAuth');
}
```Once you have the middleware applied to your application you’ll need a way for users to login. A simplistic `UsersController` would look like:
```php
class UsersController extends AppController
{
public function beforeFilter(\Cake\Event\EventInterface $event)
{
parent::beforeFilter($event);$this->Authentication->allowUnauthenticated(['login', 'verify']);
}public function login()
{
$result = $this->Authentication->getResult();
if ($result->isValid()) {
// If the user is logged in send them away.
$target = $this->Authentication->getLoginRedirect() ?? '/home';return $this->redirect($target);
}if ($this->request->is('post') && !$result->isValid()) {
if ($result->getStatus() == \TwoFactorAuth\Authenticator\Result::TWO_FACTOR_AUTH_FAILED) {
// One time code was entered and it's invalid
$this->Flash->error('Invalid 2FA code');return $this->redirect(['action' => 'verify']);
} elseif ($result->getStatus() == \TwoFactorAuth\Authenticator\Result::TWO_FACTOR_AUTH_REQUIRED) {
// One time code is required and wasn't yet entered - redirect to the verify action
return $this->redirect(['action' => 'verify']);
} else {
$this->Flash->error('Invalid username or password');
}
}
}public function logout()
{
$this->Authentication->logout();return $this->redirect(['action' => 'login']);
}public function verify()
{
// This action is only needed to render a vew with one time code form
}
}
```And `verify.php` would look like:
```html
= $this->Form->create(null, ['url' => ['action' => 'login']]) ?>
= __('Please enter your 2FA code') ?>
= $this->Form->control('code') ?>
= $this->Form->button(__('Continue')); ?>
= $this->Form->end() ?>
```Basically, it works same way CakePHP `Authentication.Form` authenticator does.
After entering correct username/password combination, if the user has `secret` field (can be overwritten via `TwoFactorAuth.TwoFactorForm` configuration) set he will be redirected to the `verify` action where he is asked to enter a one-time code.
There is no logic behind this action, it only renders the form that has to be submitted to the `loginAction` again with `code` field set.You can access the [RobThree\Auth\TwoFactorAuth](https://github.com/RobThree/TwoFactorAuth) instance from your controller via `$this->TwoFactorAuth->getTfa()` or call some of the methods directly on `TwoFactorAuth` component. For example, you can generate user's secret and get QR code data URI for it this way:
```php
$secret = $this->TwoFactorAuth->createSecret();
$secretDataUri = $this->TwoFactorAuth->getQRCodeImageAsDataUri('CakePHP:[email protected]', $secret);
```
Then display it in your view:
```php![]()
```
See the library page for full documentation: https://github.com/RobThree/TwoFactorAuth## Bugs & Feedback
https://github.com/andrej-griniuk/cakephp-two-factor-auth/issues
## Credits
https://github.com/RobThree/TwoFactorAuth
## License
Copyright (c) 2020, [Andrej Griniuk][andrej-griniuk] and licensed under [The MIT License][mit].
[cakephp]:http://cakephp.org
[composer]:http://getcomposer.org
[mit]:http://www.opensource.org/licenses/mit-license.php
[andrej-griniuk]:https://github.com/andrej-griniuk