{"id":18028282,"url":"https://github.com/alexandregz/twofactor_gauthenticator","last_synced_at":"2025-05-15T04:05:09.720Z","repository":{"id":12527076,"uuid":"15196977","full_name":"alexandregz/twofactor_gauthenticator","owner":"alexandregz","description":"This RoundCube plugin adds the 2-step verification(OTP) to the login proccess","archived":false,"fork":false,"pushed_at":"2025-03-28T20:25:19.000Z","size":1849,"stargazers_count":237,"open_issues_count":48,"forks_count":82,"subscribers_count":30,"default_branch":"master","last_synced_at":"2025-04-14T05:55:16.599Z","etag":null,"topics":["otpauth","php","roundcube"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"DraftDario/PeopleList","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alexandregz.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,"zenodo":null}},"created_at":"2013-12-15T03:10:29.000Z","updated_at":"2025-04-10T13:20:34.000Z","dependencies_parsed_at":"2024-03-31T12:27:09.411Z","dependency_job_id":"1d2523ad-db06-4b7e-bead-dbaca22ec954","html_url":"https://github.com/alexandregz/twofactor_gauthenticator","commit_stats":{"total_commits":173,"total_committers":36,"mean_commits":4.805555555555555,"dds":"0.34104046242774566","last_synced_commit":"38a642d9cade07c407af7c48da36167a18c4a304"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexandregz%2Ftwofactor_gauthenticator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexandregz%2Ftwofactor_gauthenticator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexandregz%2Ftwofactor_gauthenticator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexandregz%2Ftwofactor_gauthenticator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexandregz","download_url":"https://codeload.github.com/alexandregz/twofactor_gauthenticator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254270643,"owners_count":22042859,"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":["otpauth","php","roundcube"],"created_at":"2024-10-30T08:14:40.171Z","updated_at":"2025-05-15T04:05:04.697Z","avatar_url":"https://github.com/alexandregz.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Two-factor verification\n\nThis RoundCube plugin adds the 2-step verification (OTP) to the login process.\n\nIt works with all TOTP applications [RFC 6238](https://www.rfc-editor.org/info/rfc6238).\n\nSome code by:\n\n- [Ricardo Signes](https://github.com/rjbs)\n- [Justin Buchanan](https://github.com/jusbuc2k)\n- [Ricardo Iván Vieitez Parra](https://github.com/corrideat)\n- [GoogleAuthenticator class](https://github.com/PHPGangsta/GoogleAuthenticator/) by Michael Kliewe (to _see_ secrets)\n- [qrcode.js](https://github.com/davidshimjs/qrcodejs) by ShimSangmin\n- Also thanks to [Victor R. Rodriguez Dominguez](https://github.com/vrdominguez) for some ideas and support\n- Stephen K. Gielda\n\n\u003cbr /\u003e\u003cbr /\u003e\n\n## Screenshots\n\n\u003cimg src=\"screenshots/001-login.png\" alt=\"Login\" width=\"400\" /\u003e\n\u003cbr /\u003e\u003cbr /\u003e\n\u003cimg src=\"screenshots/002-2steps.png\" alt=\"Login\" width=\"400\" /\u003e\n\n\u003cbr /\u003e\u003cbr /\u003e\n\n## Table of Contents\n- [Installation](#installation)\n  - [Get the plugin](#get-the-plugin)\n  - [Activate the plugin](#activate-the-plugin)\n  - [Configuration](#configuration)\n    - [Variables](#variables)\n- [Usage](#usage)\n- [Docker Compose](#docker-compose)\n- [Development](#development)\n  - [Code formatting](#code-formatting)\n- [Additional Information](#additional-information)\n  - [Author](#author)\n  - [Issues](#issues)\n  - [TOTP Codes](#totp-codes)\n  - [License](#license)\n  - [Notes](#notes)\n  - [Testing](#testing)\n  - [Using with Kolab](#using-with-kolab)\n  - [Client implementations](#client-implementations)\n- [Uninstall](#uninstall)\n- [For version 1.3.x](#for-version-13x)\n- [Security incidents](#security-incidents)\n  - [2022-04-02](#2022-04-02)\n\n\u003cbr /\u003e\u003cbr /\u003e\n\n## Installation\n\n**If you are using Roundcube 1.3.x, please refer to section [For version 1.3.x](#for-version-13x)**.\n\n### Get the plugin\n\n**Method 1:** Clone from GitHub inside the plugins directory of Roundcube:\n\n    1. `cd plugins`\n    2. `git clone https://github.com/alexandregz/twofactor_gauthenticator.git`\n\n**Method 2:** Use composer from the Roundcube root directory:\n\n```sh\ncomposer require alexandregz/twofactor_gauthenticator:dev-master\n```\n\n_NOTE:_ Answer **N** when the composer ask you about plugin activation.\n\n### Activate the plugin\n\nActivate the plugin by editing the `HOME_RC/config/config.inc.php` file:\n\n```php\n$config['plugins'] = [\n        // Other plugins...\n        'twofactor_gauthenticator',\n];\n```\n\n_NOTE:_ For docker user, add env `ROUNDCUBE_PLUGINS=twofactor_gauthenticator` into docker-compose file. For detailed\ninformation, see [Roundcube Docker Hub](https://hub.docker.com/r/roundcube/roundcubemail/).\n\n### Configuration\n\nCopy `HOME_RC/plugins/twofactor_gauthenticator/config.inc.php.dist` to\n`HOME_RC/plugins/twofactor_gauthenticator/config.inc.php`.\n\n#### Variables\n\nVariables inside `config.inc.php`:\n\n| Variable                          | Variable Type | Default Value | Description                                                                                                                                                                                                                                                                                                                                                                                                      |\n|-----------------------------------|---------------|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `force_enrollment_users`          | boolean       | false         | If true, all users must log in with 2-step verification. They will receive an alert message and cannot skip the configuration.                                                                                                                                                                                                                                                                                   |\n| `whitelist`                       | array         | N/A           | A Whitelist of IPs which are allowed to bypass the 2FA, CIDR format available. \u003cbr /\u003e\u003cbr /\u003e _NOTE:_ We need to use .0 IP to define LAN because the class CIDR have a issue about that (we can't use 129.168.1.2/24, for example). \u003cbr /\u003e\u003cbr /\u003e _NOTE2:_ To create a empty whitelist, make sure it looks like this: \u003cbr /\u003e`$rcmail_config['whitelist'] = array();` \u003c- There are NO QUOTES inside the parentheses. |\n| `allow_save_device_30days`        | boolean       | false         | If true, there will be a checkbox in the the TOTP code prompting page. By ticking it, there will be no 2FA prompt for 30 days.                                                                                                                                                                                                                                                                                   | \n| `twofactor_formfield_as_password` | boolean       | false         | If true, the entered TOTP code will appear as password in the webpage when prompting it. Otherwise, it'll shown as text.                                                                                                                                                                                                                                                                                         |\n| `users_allowed_2FA`               | array         | N/A           | Users allowed to use plugin (IMPORTANT: other users DON'T have plugin activated). Regex is supported. \u003cbr /\u003e\u003cbr /\u003e _NOTE:_ plugin must be base32 valid characters ([A-Z][2-7]), see [PHPGansta Library](https://github.com/alexandregz/twofactor_gauthenticator/blob/master/PHPGangsta/GoogleAuthenticator.php#L18), from [Issues 139](https://github.com/alexandregz/twofactor_gauthenticator/issues/139).      |\n| `enable_fail_logs`                | boolean       | false         | If true, 2FA failure will be logged in file log_errors_2FA.txt under HOME_RC/logs/log_errors_2FA.txt. \u003cbr /\u003e\u003cbr /\u003e Suggested by @pngd [issue 131](https://github.com/alexandregz/twofactor_gauthenticator/issues/131).                                                                                                                                                                                           |                                                                                                                                                                                                                                                                                                                                                                                                      \n\nThe tickbox allows users to skip 2FA for 30 days:\n\n\u003cimg src=\"screenshots/003-skip_30_days.png\" alt=\"Login\" width=\"400\" /\u003e\n\nVariables that only existed in **Samefield branch**:\n\n| Variable                    | Variable Type | Default Value | Description                                                                                                                                                                                                                                                                    |\n|-----------------------------|---------------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `2step_codes_on_login_form` | boolean       | false         | If config value _2step_codes_on_login_form_ is true, 2-step codes (and recovery) must be sended with password value, append to this, from the login screen: \"Normal\" codes just following password (passswordCODE), recovery codes after two pipes (passsword\\|\\|RECOVERYCODE) |\n\n\u003cbr /\u003e\u003cbr /\u003e\n\n## Usage\n\nGo to Roundcube Settings \u003e 2-Factor Authentication:\n\n\u003cimg src=\"screenshots/004-default_settings.png\" alt=\"Login\" width=\"800\" /\u003e\n\nThe most easy way to configure it is by clicking \"Fill all fields\". The plugin automatically creates the secret as\nwell as the recovery codes for you:\n\n\u003cimg src=\"screenshots/005-generated_setting.png\" alt=\"Login\" width=\"800\" /\u003e\n\nYou can store/create TOTP codes with any authenticator app by either scanning the QR code or entering the secret\nmanually.\n\nManually entering the secret as well as recovery codes is also possible.\nNote that the recovery codes are optional, so you can leave them blank.\n\nAfter setting up the authenticator, enter the code and press \"Check code\". If the code is correct, you can press \"Save\"\nto save the configuration and enable 2-step verification.\n\n\u003cimg src=\"screenshots/006-settings_ok.png\" alt=\"Login\" width=\"800\" /\u003e\n\n\u003cbr /\u003e\u003cbr /\u003e\n\n## Docker Compose\n\nYou can use `docker-compose` file to modify and test plugin:\n\n- Replace `mail.EXAMPLE.com` for your IMAP and SMTP server.\n- `docker-compose up`\n- You can use `adminer` to check DB and reset secrets, for example.\n\n\u003cbr /\u003e\u003cbr /\u003e\n\n## Development\n\n### Code formatting\n\nInstall PHP-CS-Fixer (requires `composer` to be installed):\n\n```sh\ncomposer install --working-dir=./tools/php-cs-fixer\n```\n\nRun the coding standards fixer (in current working directory):\n\n```sh\n./tools/php-cs-fixer/vendor/bin/php-cs-fixer fix .\n```\n\n\u003cbr /\u003e\u003cbr /\u003e\n\n## Additional Information\n\n### Author\n\nAlexandre Espinosa Menor \u003caemenor@gmail.com\u003e\n\n### Issues\n\nJust open issues using GitHub issues instead of sending me emails, please.\nGmail usually marks messages like this as SPAMs.\n\n### TOTP Codes\n\nTOTP codes have a 2\\*30 seconds clock tolerance. (May be editable in future versions)\n\n### License\n\nMIT, see License\n\n### Notes\n\nTested with RoundCube 0.9.5 and Google app. Also with Roundcube 1.0.4 and 1.6.9 with OpenAuthenticator.\n\nRemember, time synchronization it's essential to TOTP: \"For this to work, the clocks of the user's device and the server\nneed to\nbe roughly synchronized (the server will typically accept one-time passwords generated from timestamps that differ by ±1\nfrom the client's timestamp)\" (\nfrom [Wikipedia: Time-based one-time password](https://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm)).\n\n### Testing\n\n- Vagrant: https://github.com/alexandregz/vagrant-twofactor_gauthenticator\n- Docker: https://hub.docker.com/r/alexandregz/twofactor_gauthenticator/\n\n### Using with Kolab\n\nAdd a symlink into the public_html/assets directory\n\n[Show explained](https://github.com/alexandregz/twofactor_gauthenticator/issues/29#issuecomment-156838186)\nby [Martin Stone](https://github.com/d7415)\n\n### Client implementations\n\nYou can use various [OTP clients](https://en.wikipedia.org/wiki/HMAC-based_One-time_Password_Algorithm#Applications)\n, by [helmo](https://github.com/helmo).\n\n\u003cbr /\u003e\u003cbr /\u003e\n\n## Uninstall\n\nTo deactivate the plugin, there are two methods:\n\n- For one only: Restore the user prefs from DB to null (rouncubeDB.users.preferences) which the user plugin options\n  stored.\n\n- To all: Remove the plugin from config.inc.php thus remove the plugin itself.\n\n\u003cbr /\u003e\u003cbr /\u003e\n\n## For version 1.3.x\n\nUse _1.3.9-version_ branch\n\n`$ git checkout 1.3.9-version`\n\nIf you are using other versions other than 1.3.9, use _master_ version normally (thanks\nto [tborgans](https://github.com/tborgans))\n\n\u003cimg src=\"/screenshots/007-elastic_skin_start.png\" alt=\"Login\" width=\"400\" /\u003e\n\u003cbr /\u003e\u003cbr /\u003e\n\u003cimg src=\"/screenshots/008-elastic_skin_config.png\" alt=\"Login\" width=\"800\" /\u003e\n\n\u003cbr /\u003e\u003cbr /\u003e\n\n## Security incidents\n\n### 2022-04-02\n\nReported by kototilt@haiiro.dev (thx for the report and the PoC script)\n\nI made a little modification to the script to disallow user to save config without param session generated from a\nrendered page to force user to introduce previously 2FA code and navigate across site.\n\n_NOTE:_ I also checked if the user has 2FA activated because with only first condition -check SESSION- app kick me out\nbefore activating 2FA.\n\n\u003cbr /\u003e\n\n**Function `twofactor_gauthenticator_save()`**\n\nOn function `twofactor_gauthenticator_save()` I added this code:\n\n```php\n// save config\nfunction twofactor_gauthenticator_save()\n{\n    $rcmail = rcmail::get_instance();\n\n    // 2022-04-03: Corrected security incidente reported by kototilt@haiiro.dev\n    //\t\t\t\t\t\"2FA in twofactor_gauthenticator can be bypassed allowing an attacker to disable 2FA or change the TOTP secret.\"\n    //\n    // Solution: if user don't have session created by any rendered page, we kick out\n    $config_2FA = self::__get2FAconfig();\n    if(!$_SESSION['twofactor_gauthenticator_2FA_login'] \u0026\u0026 $config_2FA['activate']) {\n        $this-\u003e__exitSession();\n    }\n```\n\nThe idea is to create a session variable from a rendered page, redirected from `__goingRoundcubeTask` function (\nredirector to `roundcube tasks`)\n\n\u003cbr /\u003e\n\n**Tests with PoC Python Script**\n\nPreviously, with security compromised:\n\n```bash\nalex@vosjod:~/Desktop/report$ ./poc.py\nPassword:xxxxxxxx\n1. Fetching login page (http://localhost:8888/roundcubemail-1.4.8)\n2. Logging in\n  POST http://localhost:8888/roundcubemail-1.4.8/?_task=login\n3. Disabling 2FA\n  POST http://localhost:8888/roundcubemail-1.4.8/?_task=settings\u0026_action=plugin.twofactor_gauthenticator-save\n  POST returned task \"settings\"\n2FA disabled!\n```\n\nModified code and tested again, not allowed to deactivated/modified without going to a RC task (with 2FA\nauthentication):\n\n```bash\nalex@vosjod:~/Desktop/report$ ./poc.py\nPassword:xxxxxxxxx\n1. Fetching login page (http://localhost:8888/roundcubemail-1.4.8)\n2. Logging in\n  POST http://localhost:8888/roundcubemail-1.4.8/?_task=login\n3. Disabling 2FA\n  POST http://localhost:8888/roundcubemail-1.4.8/?_task=settings\u0026_action=plugin.twofactor_gauthenticator-save\n  POST returned task \"login\"\nExpected \"settings\" task, something went wrong\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexandregz%2Ftwofactor_gauthenticator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexandregz%2Ftwofactor_gauthenticator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexandregz%2Ftwofactor_gauthenticator/lists"}