PHPackages                             alexandregz/twofactor\_gauthenticator - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. alexandregz/twofactor\_gauthenticator

ActiveRoundcube-plugin[Authentication &amp; Authorization](/categories/authentication)

alexandregz/twofactor\_gauthenticator
=====================================

This RoundCube plugin adds the Google 2-step verification to the login proccess (OTP)

2579.6k↑17.9%96[46 issues](https://github.com/alexandregz/twofactor_gauthenticator/issues)[3 PRs](https://github.com/alexandregz/twofactor_gauthenticator/pulls)PHP

Since Feb 9Pushed 2mo ago30 watchersCompare

[ Source](https://github.com/alexandregz/twofactor_gauthenticator)[ Packagist](https://packagist.org/packages/alexandregz/twofactor_gauthenticator)[ RSS](/packages/alexandregz-twofactor-gauthenticator/feed)WikiDiscussions master Synced 2d ago

READMEChangelogDependenciesVersions (8)Used By (0)

Two-factor verification
=======================

[](#two-factor-verification)

This RoundCube plugin adds the 2-step verification (OTP) to the login process.

It works with all TOTP applications [RFC 6238](https://www.rfc-editor.org/info/rfc6238).

Some code by:

- [Ricardo Signes](https://github.com/rjbs)
- [Justin Buchanan](https://github.com/jusbuc2k)
- [Ricardo Iván Vieitez Parra](https://github.com/corrideat)
- [GoogleAuthenticator class](https://github.com/PHPGangsta/GoogleAuthenticator/) by Michael Kliewe (to *see* secrets)
- [qrcode.js](https://github.com/davidshimjs/qrcodejs) by ShimSangmin
- Also thanks to [Victor R. Rodriguez Dominguez](https://github.com/vrdominguez) for some ideas and support
- Stephen K. Gielda
- [Manuel Delgado](https://github.com/valarauco/)
-

Screenshots
-----------

[](#screenshots)

[![Login](screenshots/001-login.png)](screenshots/001-login.png)

[![Login](screenshots/002-2steps.png)](screenshots/002-2steps.png)

Table of Contents
-----------------

[](#table-of-contents)

- [Installation](#installation)
    - [Get the plugin](#get-the-plugin)
    - [Activate the plugin](#activate-the-plugin)
    - [Configuration](#configuration)
        - [Variables](#variables)
- [Usage](#usage)
- [Docker Compose](#docker-compose)
- [Development](#development)
    - [Code formatting](#code-formatting)
- [Additional Information](#additional-information)
    - [Author](#author)
    - [Issues](#issues)
    - [TOTP Codes](#totp-codes)
    - [License](#license)
    - [Notes](#notes)
    - [Testing](#testing)
    - [Using with Kolab](#using-with-kolab)
    - [Client implementations](#client-implementations)
- [Uninstall](#uninstall)
- [For version 1.3.x](#for-version-13x)
- [Security incidents](#security-incidents)
    - [2022-04-02](#2022-04-02)

Installation
------------

[](#installation)

**If you are using Roundcube 1.3.x, please refer to section [For version 1.3.x](#for-version-13x)**.

### Get the plugin

[](#get-the-plugin)

**Method 1:** Clone from GitHub inside the plugins directory of Roundcube:

```
1. `cd plugins`
2. `git clone https://github.com/alexandregz/twofactor_gauthenticator.git`

```

**Method 2:** Use composer from the Roundcube root directory:

```
composer require alexandregz/twofactor_gauthenticator:dev-master
```

*NOTE:* Answer **N** when the composer ask you about plugin activation.

### Activate the plugin

[](#activate-the-plugin)

Activate the plugin by editing the `HOME_RC/config/config.inc.php` file:

```
$config['plugins'] = [
        // Other plugins...
        'twofactor_gauthenticator',
];
```

*NOTE:* For docker user, add env `ROUNDCUBE_PLUGINS=twofactor_gauthenticator` into docker-compose file. For detailed information, see [Roundcube Docker Hub](https://hub.docker.com/r/roundcube/roundcubemail/).

### Configuration

[](#configuration)

Copy `HOME_RC/plugins/twofactor_gauthenticator/config.inc.php.dist` to `HOME_RC/plugins/twofactor_gauthenticator/config.inc.php`.

#### Variables

[](#variables)

Variables inside `config.inc.php`:

VariableVariable TypeDefault ValueDescription`force_enrollment_users`booleanfalseIf true, all users must log in with 2-step verification. They will receive an alert message and cannot skip the configuration.`whitelist`arrayN/AA Whitelist of IPs which are allowed to bypass the 2FA, CIDR format available.

 *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).

 *NOTE2:* To create a empty whitelist, make sure it looks like this:
`$rcmail_config['whitelist'] = array();` &lt;- There are NO QUOTES inside the parentheses.`allow_save_device_30days`booleanfalseIf 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.`twofactor_formfield_as_password`booleanfalseIf true, the entered TOTP code will appear as password in the webpage when prompting it. Otherwise, it'll shown as text.`users_allowed_2FA`arrayN/AUsers allowed to use plugin (IMPORTANT: other users DON'T have plugin activated). Regex is supported.

 *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).`enable_fail_logs`booleanfalseIf true, 2FA failure will be logged in file twofactor\_gauthenticator.log under HOME\_RC/logs/.

 Suggested by @pngd [issue 131](https://github.com/alexandregz/twofactor_gauthenticator/issues/131).

Code by [@valarauco](https://github.com/valarauco) [\#227](https://github.com/alexandregz/twofactor_gauthenticator/pull/227)`twofactor_pref_encrypt`booleanfalseIf true, twofactor user preferences (secret and codes) will be encrypted with Roundcube's DES key

Code by [@valarauco](https://github.com/valarauco) [\#225](https://github.com/alexandregz/twofactor_gauthenticator/pull/225)

NOTE: when prefs are encrypted and you set this variable to `false`, you enter without twofactor authentication. Encryption it's not reversible.The tickbox allows users to skip 2FA for 30 days:

[![Login](screenshots/003-skip_30_days.png)](screenshots/003-skip_30_days.png)

Variables that only existed in **Samefield branch**:

VariableVariable TypeDefault ValueDescription`2step_codes_on_login_form`booleanfalseIf 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)Usage
-----

[](#usage)

Go to Roundcube Settings &gt; 2-Factor Authentication:

[![Login](screenshots/004-default_settings.png)](screenshots/004-default_settings.png)

The most easy way to configure it is by clicking "Fill all fields". The plugin automatically creates the secret as well as the recovery codes for you:

[![Login](screenshots/005-generated_setting.png)](screenshots/005-generated_setting.png)

You can store/create TOTP codes with any authenticator app by either scanning the QR code or entering the secret manually.

Manually entering the secret as well as recovery codes is also possible. Note that the recovery codes are optional, so you can leave them blank.

After setting up the authenticator, enter the code and press "Check code". If the code is correct, you can press "Save" to save the configuration and enable 2-step verification.

[![Login](screenshots/006-settings_ok.png)](screenshots/006-settings_ok.png)

Docker Compose
--------------

[](#docker-compose)

You can use `docker-compose` file to modify and test plugin:

- Replace `mail.EXAMPLE.com` for your IMAP and SMTP server.
- `docker-compose up`
- You can use `adminer` to check DB and reset secrets, for example.

Development
-----------

[](#development)

### Code formatting

[](#code-formatting)

Install PHP-CS-Fixer (requires `composer` to be installed):

```
composer install --working-dir=./tools/php-cs-fixer
```

Run the coding standards fixer (in current working directory):

```
./tools/php-cs-fixer/vendor/bin/php-cs-fixer fix .
```

Additional Information
----------------------

[](#additional-information)

### Author

[](#author)

Alexandre Espinosa Menor

### Issues

[](#issues)

Just open issues using GitHub issues instead of sending me emails, please. Gmail usually marks messages like this as SPAMs.

### TOTP Codes

[](#totp-codes)

TOTP codes have a 2\*30 seconds clock tolerance. (May be editable in future versions)

### License

[](#license)

MIT, see License

### Notes

[](#notes)

Tested with RoundCube 0.9.5 and Google app. Also with Roundcube 1.0.4 and 1.6.9 with OpenAuthenticator, Authy, etc.

Remember, time synchronization it's essential to TOTP: "For this to work, the clocks of the user's device and the server need to be roughly synchronized (the server will typically accept one-time passwords generated from timestamps that differ by ±1 from the client's timestamp)" ( from [Wikipedia: Time-based one-time password](https://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm)).

### Testing

[](#testing)

- Vagrant: [https://github.com/alexandregz/vagrant-twofactor\_gauthenticator](https://github.com/alexandregz/vagrant-twofactor_gauthenticator)
- Docker: [https://hub.docker.com/r/alexandregz/twofactor\_gauthenticator/](https://hub.docker.com/r/alexandregz/twofactor_gauthenticator/)

### Using with Kolab

[](#using-with-kolab)

Add a symlink into the public\_html/assets directory

[Show explained](https://github.com/alexandregz/twofactor_gauthenticator/issues/29#issuecomment-156838186)by [Martin Stone](https://github.com/d7415)

### Client implementations

[](#client-implementations)

You can use various [OTP clients](https://en.wikipedia.org/wiki/HMAC-based_One-time_Password_Algorithm#Applications), by [helmo](https://github.com/helmo).

Uninstall
---------

[](#uninstall)

To deactivate the plugin, there are two methods:

- For one only: Restore the user prefs from DB to null (rouncubeDB.users.preferences) which the user plugin options stored.
- To all: Remove the plugin from config.inc.php thus remove the plugin itself.

For version 1.3.x
-----------------

[](#for-version-13x)

Use *1.3.9-version* branch

`$ git checkout 1.3.9-version`

If you are using other versions other than 1.3.9, use *master* version normally (thanks to [tborgans](https://github.com/tborgans))

[![Login](/screenshots/007-elastic_skin_start.png)](/screenshots/007-elastic_skin_start.png)

[![Login](/screenshots/008-elastic_skin_config.png)](/screenshots/008-elastic_skin_config.png)

Security incidents
------------------

[](#security-incidents)

### 2022-04-02

[](#2022-04-02)

Reported by  (thx for the report and the PoC script)

I made a little modification to the script to disallow user to save config without param session generated from a rendered page to force user to introduce previously 2FA code and navigate across site.

*NOTE:* I also checked if the user has 2FA activated because with only first condition -check SESSION- app kick me out before activating 2FA.

**Function `twofactor_gauthenticator_save()`**

On function `twofactor_gauthenticator_save()` I added this code:

```
// save config
function twofactor_gauthenticator_save()
{
    $rcmail = rcmail::get_instance();

    // 2022-04-03: Corrected security incidente reported by kototilt@haiiro.dev
    //					"2FA in twofactor_gauthenticator can be bypassed allowing an attacker to disable 2FA or change the TOTP secret."
    //
    // Solution: if user don't have session created by any rendered page, we kick out
    $config_2FA = self::__get2FAconfig();
    if(!$_SESSION['twofactor_gauthenticator_2FA_login'] && $config_2FA['activate']) {
        $this->__exitSession();
    }
```

The idea is to create a session variable from a rendered page, redirected from `__goingRoundcubeTask` function ( redirector to `roundcube tasks`)

**Tests with PoC Python Script**

Previously, with security compromised:

```
alex@vosjod:~/Desktop/report$ ./poc.py
Password:xxxxxxxx
1. Fetching login page (http://localhost:8888/roundcubemail-1.4.8)
2. Logging in
  POST http://localhost:8888/roundcubemail-1.4.8/?_task=login
3. Disabling 2FA
  POST http://localhost:8888/roundcubemail-1.4.8/?_task=settings&_action=plugin.twofactor_gauthenticator-save
  POST returned task "settings"
2FA disabled!
```

Modified code and tested again, not allowed to deactivated/modified without going to a RC task (with 2FA authentication):

```
alex@vosjod:~/Desktop/report$ ./poc.py
Password:xxxxxxxxx
1. Fetching login page (http://localhost:8888/roundcubemail-1.4.8)
2. Logging in
  POST http://localhost:8888/roundcubemail-1.4.8/?_task=login
3. Disabling 2FA
  POST http://localhost:8888/roundcubemail-1.4.8/?_task=settings&_action=plugin.twofactor_gauthenticator-save
  POST returned task "login"
Expected "settings" task, something went wrong
```

###  Health Score

46

—

FairBetter than 92% of packages

Maintenance52

Moderate activity, may be stable

Popularity45

Moderate usage in the ecosystem

Community32

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 71.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/bac185919c9a769922fadc33c6e0517a455d4762f33c854ced30e8778bc45f64?d=identicon)[alexandregz](/maintainers/alexandregz)

---

Top Contributors

[![alexandregz](https://avatars.githubusercontent.com/u/1374718?v=4)](https://github.com/alexandregz "alexandregz (193 commits)")[![corbolais](https://avatars.githubusercontent.com/u/5993400?v=4)](https://github.com/corbolais "corbolais (9 commits)")[![melroy89](https://avatars.githubusercontent.com/u/628926?v=4)](https://github.com/melroy89 "melroy89 (8 commits)")[![cooldark](https://avatars.githubusercontent.com/u/15010571?v=4)](https://github.com/cooldark "cooldark (7 commits)")[![helmo](https://avatars.githubusercontent.com/u/104120?v=4)](https://github.com/helmo "helmo (7 commits)")[![RealSebFox](https://avatars.githubusercontent.com/u/47162552?v=4)](https://github.com/RealSebFox "RealSebFox (5 commits)")[![SamWang8891](https://avatars.githubusercontent.com/u/73735177?v=4)](https://github.com/SamWang8891 "SamWang8891 (4 commits)")[![tborgans](https://avatars.githubusercontent.com/u/1382329?v=4)](https://github.com/tborgans "tborgans (4 commits)")[![valarauco](https://avatars.githubusercontent.com/u/434898?v=4)](https://github.com/valarauco "valarauco (3 commits)")[![numericOverflow](https://avatars.githubusercontent.com/u/3429424?v=4)](https://github.com/numericOverflow "numericOverflow (2 commits)")[![limer-org](https://avatars.githubusercontent.com/u/2848202?v=4)](https://github.com/limer-org "limer-org (2 commits)")[![bilbolodz](https://avatars.githubusercontent.com/u/4696144?v=4)](https://github.com/bilbolodz "bilbolodz (2 commits)")[![SuluCiprian](https://avatars.githubusercontent.com/u/29707282?v=4)](https://github.com/SuluCiprian "SuluCiprian (2 commits)")[![sun0537](https://avatars.githubusercontent.com/u/149989756?v=4)](https://github.com/sun0537 "sun0537 (2 commits)")[![condless](https://avatars.githubusercontent.com/u/55792802?v=4)](https://github.com/condless "condless (2 commits)")[![urbels](https://avatars.githubusercontent.com/u/2535400?v=4)](https://github.com/urbels "urbels (2 commits)")[![PeteLawler](https://avatars.githubusercontent.com/u/168658?v=4)](https://github.com/PeteLawler "PeteLawler (2 commits)")[![vookimedlo](https://avatars.githubusercontent.com/u/2312301?v=4)](https://github.com/vookimedlo "vookimedlo (1 commits)")[![diegoweb](https://avatars.githubusercontent.com/u/12632119?v=4)](https://github.com/diegoweb "diegoweb (1 commits)")[![gringus](https://avatars.githubusercontent.com/u/3704589?v=4)](https://github.com/gringus "gringus (1 commits)")

---

Tags

otpauthphproundcube

### Embed Badge

![Health badge](/badges/alexandregz-twofactor-gauthenticator/health.svg)

```
[![Health](https://phpackages.com/badges/alexandregz-twofactor-gauthenticator/health.svg)](https://phpackages.com/packages/alexandregz-twofactor-gauthenticator)
```

###  Alternatives

[kartik-v/yii2-password

Useful password strength validation utilities for Yii Framework 2.0

761.3M17](/packages/kartik-v-yii2-password)[vitalybaev/laravel5-dkim

Laravel 5/6 package for signing outgoing messages with DKIM.

3163.1k](/packages/vitalybaev-laravel5-dkim)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
