{"id":13684149,"url":"https://github.com/andrej-griniuk/cakephp-two-factor-auth","last_synced_at":"2026-05-07T15:01:55.395Z","repository":{"id":52592540,"uuid":"51571295","full_name":"andrej-griniuk/cakephp-two-factor-auth","owner":"andrej-griniuk","description":"Two-factor authentication plugin","archived":false,"fork":false,"pushed_at":"2024-06-19T14:57:58.000Z","size":103,"stargazers_count":37,"open_issues_count":1,"forks_count":11,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-11-12T05:37:07.259Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andrej-griniuk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-02-12T06:42:02.000Z","updated_at":"2024-10-29T15:21:59.000Z","dependencies_parsed_at":"2024-11-12T05:31:39.535Z","dependency_job_id":"4c080feb-6827-4145-8ff6-5f595433fea0","html_url":"https://github.com/andrej-griniuk/cakephp-two-factor-auth","commit_stats":{"total_commits":73,"total_committers":8,"mean_commits":9.125,"dds":0.3013698630136986,"last_synced_commit":"63d035673971cd91521d946688618a5290f74604"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrej-griniuk%2Fcakephp-two-factor-auth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrej-griniuk%2Fcakephp-two-factor-auth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrej-griniuk%2Fcakephp-two-factor-auth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrej-griniuk%2Fcakephp-two-factor-auth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andrej-griniuk","download_url":"https://codeload.github.com/andrej-griniuk/cakephp-two-factor-auth/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251777715,"owners_count":21642212,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T14:00:27.280Z","updated_at":"2026-05-07T15:01:55.384Z","avatar_url":"https://github.com/andrej-griniuk.png","language":"PHP","funding_links":[],"categories":["Authentication and Authorization","Plugins"],"sub_categories":["Authentication and Authorization"],"readme":"[![Build Status](https://github.com/andrej-griniuk/cakephp-two-factor-auth/actions/workflows/ci.yml/badge.svg)](https://github.com/andrej-griniuk/cakephp-two-factor-auth/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/andrej-griniuk/cakephp-two-factor-auth/branch/master/graph/badge.svg)](https://codecov.io/gh/andrej-griniuk/cakephp-two-factor-auth)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE)\n\n# TwoFactorAuth plugin for CakePHP\n\nThis plugin provides two factor authentication functionality using [RobThree/TwoFactorAuth](https://github.com/RobThree/TwoFactorAuth) library.\nBasically, 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.\n**Attention:** it only provides authenticate provider and component and does not take care of users signup, management etc.\n\n## Requirements\n\n- CakePHP 5.0+ (use ***^1.3*** version for CakePHP \u003c3.7, ***^2.0*** version for CakePHP 3.x, ***^3.0*** version for CakePHP 4.x)\n\n## Installation\n\nYou can install this plugin into your CakePHP application using [Composer][composer].\n\n```bash\ncomposer require andrej-griniuk/cakephp-two-factor-auth\n```\n\n## Usage\n\nFirst of all you need to add `secret` field to your users table (field name can be changed to `TwoFactorAuth.Form` authenticator configuration).\n```sql\nALTER TABLE `users` ADD `secret` VARCHAR(255) NULL;\n```\n\nSecond, you need to load the plugin in your Application.php\n\n```php\n$this-\u003eaddPlugin('TwoFactorAuth');\n```\n\nAlternatively, execute the following line:\n\n```bash\nbin/cake plugin load TwoFactorAuth\n```\n\nYou 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.\n\nThen 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.:\n\n```php\nclass Application extends BaseApplication implements AuthenticationServiceProviderInterface\n{\n    public function bootstrap(): void\n    {\n        // Call parent to load bootstrap from files.\n        parent::bootstrap();\n\n        $this-\u003eaddPlugin('TwoFactorAuth');\n        $this-\u003eaddPlugin('Authentication');\n    }\n\n    public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue\n    {\n        // Various other middlewares for error handling, routing etc. added here.\n\n        // Create an authentication middleware object\n        $authentication = new AuthenticationMiddleware($this);\n\n        // Add the middleware to the middleware queue.\n        // Authentication should be added *after* RoutingMiddleware.\n        // So that subdirectory information and routes are loaded.\n        $middlewareQueue-\u003eadd($authentication);\n\n        return $middlewareQueue;\n    }\n\n    public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface\n    {\n        $service = new AuthenticationService();\n        $service-\u003esetConfig([\n            'unauthenticatedRedirect' =\u003e '/users/login',\n            'queryParam' =\u003e 'redirect',\n        ]);\n\n        // Load the authenticators, you want session first\n        $service-\u003eloadAuthenticator('Authentication.Session');\n        $service-\u003eloadAuthenticator('TwoFactorAuth.TwoFactorForm', [\n           'identifier' =\u003e 'Authentication.Password',\n           'loginUrl' =\u003e '/users/login',\n        ]);\n\n        return $service;\n    }\n}\n```\n\nNext, in your AppController load the `Authentication` and `TwoFactorAuth` components:\n\n```php\n// in src/Controller/AppController.php\npublic function initialize()\n{\n    parent::initialize();\n\n    $this-\u003eloadComponent('Authentication.Authentication');\n    $this-\u003eloadComponent('TwoFactorAuth.TwoFactorAuth');\n}\n```\n\nOnce you have the middleware applied to your application you’ll need a way for users to login. A simplistic `UsersController` would look like:\n\n```php\nclass UsersController extends AppController\n{\n    public function beforeFilter(\\Cake\\Event\\EventInterface $event)\n    {\n        parent::beforeFilter($event);\n\n        $this-\u003eAuthentication-\u003eallowUnauthenticated(['login', 'verify']);\n    }\n\n    public function login()\n    {\n        $result = $this-\u003eAuthentication-\u003egetResult();\n        if ($result-\u003eisValid()) {\n            // If the user is logged in send them away.\n            $target = $this-\u003eAuthentication-\u003egetLoginRedirect() ?? '/home';\n\n            return $this-\u003eredirect($target);\n        }\n\n        if ($this-\u003erequest-\u003eis('post') \u0026\u0026 !$result-\u003eisValid()) {\n            if ($result-\u003egetStatus() == \\TwoFactorAuth\\Authenticator\\Result::TWO_FACTOR_AUTH_FAILED) {\n                // One time code was entered and it's invalid\n                $this-\u003eFlash-\u003eerror('Invalid 2FA code');\n\n                return $this-\u003eredirect(['action' =\u003e 'verify']);\n            } elseif ($result-\u003egetStatus() == \\TwoFactorAuth\\Authenticator\\Result::TWO_FACTOR_AUTH_REQUIRED) {\n                // One time code is required and wasn't yet entered - redirect to the verify action\n                return $this-\u003eredirect(['action' =\u003e 'verify']);\n            } else {\n                $this-\u003eFlash-\u003eerror('Invalid username or password');\n            }\n        }\n    }\n\n    public function logout()\n    {\n        $this-\u003eAuthentication-\u003elogout();\n\n        return $this-\u003eredirect(['action' =\u003e 'login']);\n    }\n\n    public function verify()\n    {\n        // This action is only needed to render a vew with one time code form\n    }\n}\n```\n\nAnd `verify.php` would look like:\n\n```html\n\u003cdiv class=\"users form content\"\u003e\n    \u003c?= $this-\u003eForm-\u003ecreate(null, ['url' =\u003e ['action' =\u003e 'login']]) ?\u003e\n    \u003cfieldset\u003e\n        \u003clegend\u003e\u003c?= __('Please enter your 2FA code') ?\u003e\u003c/legend\u003e\n        \u003c?= $this-\u003eForm-\u003econtrol('code') ?\u003e\n    \u003c/fieldset\u003e\n    \u003c?= $this-\u003eForm-\u003ebutton(__('Continue')); ?\u003e\n    \u003c?= $this-\u003eForm-\u003eend() ?\u003e\n\u003c/div\u003e\n```\n\nBasically, it works same way CakePHP `Authentication.Form` authenticator does.\nAfter 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.\nThere is no logic behind this action, it only renders the form that has to be submitted to the `loginAction` again with `code` field set.\n\nYou can access the [RobThree\\Auth\\TwoFactorAuth](https://github.com/RobThree/TwoFactorAuth) instance from your controller via `$this-\u003eTwoFactorAuth-\u003egetTfa()` 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:\n```php\n$secret = $this-\u003eTwoFactorAuth-\u003ecreateSecret();\n$secretDataUri = $this-\u003eTwoFactorAuth-\u003egetQRCodeImageAsDataUri('CakePHP:user@email.com', $secret);\n```\nThen display it in your view:\n```php\n\u003cimg src=\"\u003c?= $secretDataUri ?\u003e\" /\u003e\n```\nSee the library page for full documentation: https://github.com/RobThree/TwoFactorAuth\n\n## Bugs \u0026 Feedback\n\nhttps://github.com/andrej-griniuk/cakephp-two-factor-auth/issues\n\n## Credits\n\nhttps://github.com/RobThree/TwoFactorAuth\n\n## License\n\nCopyright (c) 2020, [Andrej Griniuk][andrej-griniuk] and licensed under [The MIT License][mit].\n\n[cakephp]:http://cakephp.org\n[composer]:http://getcomposer.org\n[mit]:http://www.opensource.org/licenses/mit-license.php\n[andrej-griniuk]:https://github.com/andrej-griniuk\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandrej-griniuk%2Fcakephp-two-factor-auth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandrej-griniuk%2Fcakephp-two-factor-auth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandrej-griniuk%2Fcakephp-two-factor-auth/lists"}