PHPackages                             camilord/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. camilord/twofactor\_gauthenticator

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

camilord/twofactor\_gauthenticator
==================================

This RoundCube plugin adds the 2-factor authentication during login. This is a forked from https://github.com/alexandregz/twofactor\_gauthenticator

173342PHP

Since Feb 9Pushed 2y ago3 watchersCompare

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

READMEChangelog (4)DependenciesVersions (9)Used By (0)

Roundcube Webmail plugin: 2-Factor Authentication
=================================================

[](#roundcube-webmail-plugin-2-factor-authentication)

**Requirement**

- Roundcube Webmail 1.5.x

**Changelog**

- fixed UI using bootstrap 4.5.x
- improved UI form functionalities

**Features difference from `alexandregz/twofactor_gauthenticator`**

- Remember Device in days can be configured. It was 30 days before, now the default is 7 days. 30 days is too much.
- When you enable the config `force_enrollment_users` to enforce all users to use 2FA, I have added an option to exclude some users/domain enforcing 2FA.
- When you click the Activate checkbox, will generate the `secret key` and `recovery codes` right away
- You can also regenerate the `secret key`
- QR Code always display
- In testing the codes from you app, will display the server time.
- Settings &gt; 2FA form = fixed to work or display well in Roundcube Webmail v1.5.x
- Cleaner code, better indention, reformat codes using PHPStorm

**How to install this plugin?**

- download the package and extract the contents
- should have a folder called `twofactor_gauthenticator`
- move the folder to roundube install destination under `plugins` folder: `{ROUNDCUBE_INSTALL}/plugins/`
- then define your configuration, copy `{ROUNDCUBE_INSTALL}/plugins/config.inc.php.dist` as `{ROUNDCUBE_INSTALL}/plugins/config.inc.php`
- that's it. login to you account, go to config and `2-factor Authentication` option should appear
- activate the 2FA in your account, fill up the form and you're good to go.

[![Login](https://camo.githubusercontent.com/73e58a19f07eafbcee37ff52b2fdad411a412c38277f8406a81c662ca81c8b8d/68747470733a2f2f7261772e6769746875622e636f6d2f63616d696c6f72642f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f7263756265312e355f3030312e706e67)](https://camo.githubusercontent.com/73e58a19f07eafbcee37ff52b2fdad411a412c38277f8406a81c662ca81c8b8d/68747470733a2f2f7261772e6769746875622e636f6d2f63616d696c6f72642f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f7263756265312e355f3030312e706e67)

[![2Steps](https://camo.githubusercontent.com/1449cffff9a924c063a89e88ed045632ae52fe2d50d7bd1c7c958686dffe4e36/68747470733a2f2f7261772e6769746875622e636f6d2f63616d696c6f72642f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f7263756265312e355f3030322e706e67)](https://camo.githubusercontent.com/1449cffff9a924c063a89e88ed045632ae52fe2d50d7bd1c7c958686dffe4e36/68747470733a2f2f7261772e6769746875622e636f6d2f63616d696c6f72642f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f7263756265312e355f3030322e706e67)

[![2Steps](https://camo.githubusercontent.com/b86817dad727891ee48d2ee75a200341dd35913d22f11488853ee65d9aef836c/68747470733a2f2f7261772e6769746875622e636f6d2f63616d696c6f72642f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f7263756265312e355f3030332e706e67)](https://camo.githubusercontent.com/b86817dad727891ee48d2ee75a200341dd35913d22f11488853ee65d9aef836c/68747470733a2f2f7261772e6769746875622e636f6d2f63616d696c6f72642f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f7263756265312e355f3030332e706e67)

NOTES
-----

[](#notes)

- before you save the generated secret key, make sure you tested it using the "Test the generated PIN here"
- If you keep getting "incorrect code", meaning your PC time and the server time is not the same.

---

---

---

2Steps verification
===================

[](#2steps-verification)

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

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 thx to [Victor R. Rodriguez Dominguez](https://github.com/vrdominguez) for some ideas and support

[![Login](https://camo.githubusercontent.com/39affd090c2b8a9a54b27cf29c9a21d131eb5feefc267cc24336ea6aea128740/68747470733a2f2f7261772e6769746875622e636f6d2f616c6578616e647265677a2f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f3030312d6c6f67696e2e706e67)](https://camo.githubusercontent.com/39affd090c2b8a9a54b27cf29c9a21d131eb5feefc267cc24336ea6aea128740/68747470733a2f2f7261772e6769746875622e636f6d2f616c6578616e647265677a2f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f3030312d6c6f67696e2e706e67)

[![2Steps](https://camo.githubusercontent.com/d92fd968b5c4427ccca027cfced8c8c55189884dafcfe1155c91d1a7cfac4123/68747470733a2f2f7261772e6769746875622e636f6d2f616c6578616e647265677a2f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f3030322d3273746570732e706e67)](https://camo.githubusercontent.com/d92fd968b5c4427ccca027cfced8c8c55189884dafcfe1155c91d1a7cfac4123/68747470733a2f2f7261772e6769746875622e636f6d2f616c6578616e647265677a2f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f3030322d3273746570732e706e67)

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

[](#installation)

- Clone from github: HOME\_RC/plugins$ git clone [https://github.com/alexandregz/twofactor\_gauthenticator.git](https://github.com/alexandregz/twofactor_gauthenticator.git)

(Or use composer HOME\_RC$ composer require alexandregz/twofactor\_gauthenticator:dev-master

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

- Activate the plugin into HOME\_RC/config/config.inc.php: $config\['plugins'\] = array('twofactor\_gauthenticator');

Configuration
-------------

[](#configuration)

Go to the Settings task and in the "2steps Google verification" menu, click 'Setup all fields (needs Save)'.

The plugin automatically creates the secret for you.

NOTE: plugin must be base32 valid characters (\[A-Z\]\[2-7\]), see [https://github.com/alexandregz/twofactor\_gauthenticator/blob/master/PHPGangsta/GoogleAuthenticator.php#L18](https://github.com/alexandregz/twofactor_gauthenticator/blob/master/PHPGangsta/GoogleAuthenticator.php#L18)

From [alexandregz#139](https://github.com/alexandregz/twofactor_gauthenticator/issues/139)

To add accounts to the app, you can use the QR-Code (easy-way) or type the secret. After checking the first code click 'Save'.

[![Settings by default](https://camo.githubusercontent.com/211fde0c8dcef99fa736a7046d26921e4d2659c1704d071cfb7beb09146e1b21/68747470733a2f2f7261772e6769746875622e636f6d2f616c6578616e647265677a2f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f3030332d73657474696e67735f64656661756c742e706e67)](https://camo.githubusercontent.com/211fde0c8dcef99fa736a7046d26921e4d2659c1704d071cfb7beb09146e1b21/68747470733a2f2f7261772e6769746875622e636f6d2f616c6578616e647265677a2f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f3030332d73657474696e67735f64656661756c742e706e67)

[![Settings OK](https://camo.githubusercontent.com/7654ee631d31eda405f81a4a18c1e3a5ac6a77ea403783dcef46137ac4f71d4e/68747470733a2f2f7261772e6769746875622e636f6d2f616c6578616e647265677a2f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f3030342d73657474696e67735f6f6b2e706e67)](https://camo.githubusercontent.com/7654ee631d31eda405f81a4a18c1e3a5ac6a77ea403783dcef46137ac4f71d4e/68747470733a2f2f7261772e6769746875622e636f6d2f616c6578616e647265677a2f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f3030342d73657474696e67735f6f6b2e706e67)

[![QR-Code example](https://camo.githubusercontent.com/84c556e7562aa1403ae5948266ce346a3f8192d5c49807ffa218f6cea1538966/68747470733a2f2f7261772e6769746875622e636f6d2f616c6578616e647265677a2f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f3030352d73657474696e67735f71725f636f64652e706e67)](https://camo.githubusercontent.com/84c556e7562aa1403ae5948266ce346a3f8192d5c49807ffa218f6cea1538966/68747470733a2f2f7261772e6769746875622e636f6d2f616c6578616e647265677a2f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f3030352d73657474696e67735f71725f636f64652e706e67)

Also, you can add "Recovery codes" for use one time (they delete when are used). Recovery codes are OPTIONAL, so they can be left blank.

[![Recovery codes](https://camo.githubusercontent.com/1301b2105f2e6ceec188acb2f549ef8246f7b2be3c7463cefb562804973a88cb/68747470733a2f2f7261772e6769746875622e636f6d2f616c6578616e647265677a2f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f3030362d7265636f766572795f636f6465732e706e67)](https://camo.githubusercontent.com/1301b2105f2e6ceec188acb2f549ef8246f7b2be3c7463cefb562804973a88cb/68747470733a2f2f7261772e6769746875622e636f6d2f616c6578616e647265677a2f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f3030362d7265636f766572795f636f6465732e706e67)

[![Check codes](https://camo.githubusercontent.com/98c34a3f273ae8733218d3adce50b16bafa9846f4a6ff04c4b51bf5798e6977b/68747470733a2f2f7261772e6769746875622e636f6d2f616c6578616e647265677a2f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f3030372d636865636b5f636f64652e706e67)](https://camo.githubusercontent.com/98c34a3f273ae8733218d3adce50b16bafa9846f4a6ff04c4b51bf5798e6977b/68747470733a2f2f7261772e6769746875622e636f6d2f616c6578616e647265677a2f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f3030372d636865636b5f636f64652e706e67)

[![Recovery codes](https://camo.githubusercontent.com/3da22b26ede3ed00d510bfa10fb707c1b6ecc0dfef5b940a4ec7a3fe85fc8bd3/68747470733a2f2f7261772e6769746875622e636f6d2f616c6578616e647265677a2f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f3030382d6d73675f696e666f725f61626f75745f656e726f6c6c6d656e742e706e67)](https://camo.githubusercontent.com/3da22b26ede3ed00d510bfa10fb707c1b6ecc0dfef5b940a4ec7a3fe85fc8bd3/68747470733a2f2f7261772e6769746875622e636f6d2f616c6578616e647265677a2f74776f666163746f725f6761757468656e74696361746f722f6d61737465722f73637265656e73686f74732f3030382d6d73675f696e666f725f61626f75745f656e726f6c6c6d656e742e706e67)

Enrollment Users
----------------

[](#enrollment-users)

If config value *force\_enrollment\_users* is true, **ALL** users needs to login with 2-step method. They receive alert message about that, and they can't skip without save configuration

Samefield
---------

[](#samefield)

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)

Actually only into samefield branch

Codes
-----

[](#codes)

Codes have a 2\*30 seconds clock tolerance, like by default with Google app (Maybe editable in future versions)

License
-------

[](#license)

MIT, see License

Notes
-----

[](#notes-1)

Tested with RoundCube 0.9.5 and Google app. Also with Roundcube 1.0.4

Remember, sync time it's essential for 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 [http://en.wikipedia.org/wiki/Time-based\_One-time\_Password\_Algorithm](http://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm))

Author
------

[](#author)

Alexandre Espinosa Menor

Issues
------

[](#issues)

Open issues using github, don't send me emails about that, please -usually Gmail marks messages like SPAM

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 [alexandregz#29 (comment)](https://github.com/alexandregz/twofactor_gauthenticator/issues/29#issuecomment-156838186) by

Client implementations
----------------------

[](#client-implementations)

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

Logs
----

[](#logs)

Suggested by

To log errors with bad codes, change the $\_enable\_logs variable to true.

The logs are stored to the file HOME\_RC/logs/log\_errors\_2FA.txt -directory must be created

Whitelist
---------

[](#whitelist)

You can define whitelist IPs into config file (see config.inc.php.dist) to automatic login -the plugin don't ask you for code

Uninstall
---------

[](#uninstall)

To deactivate the plugin, you can use two methods:

- To only one user: restore the user prefs from DB to null (rouncubeDB.users.preferences) -the user plugin options stored there.
- To all: remove the plugin from config.inc.php/remove the plugin itself

Activate only for specific users
--------------------------------

[](#activate-only-for-specific-users)

- Use config.inc.php file (see config.inc.php.dist example file)
- Modify array **users\_allowed\_2FA** with users that you want to use plugin. NOTE: you can use regular expressions

Use with 1.3.x version
----------------------

[](#use-with-13x-version)

Use *1.3.9-version* branch

`$ git checkout 1.3.9-version`

If you download 1.4.x RC version (with *elastic skin*), use *master* version normally (thx to [tborgans](https://github.com/tborgans))

[![Elastic Skin start](https://raw.githubusercontent.com/alexandregz/twofactor_gauthenticator/master/screenshots/009-elastic_skin_start.png)](https://raw.githubusercontent.com/alexandregz/twofactor_gauthenticator/master/screenshots/009-elastic_skin_start.png)

[![Elastic Skin config](https://raw.githubusercontent.com/alexandregz/twofactor_gauthenticator/master/screenshots/010-elastic_skin_config.png)](https://raw.githubusercontent.com/alexandregz/twofactor_gauthenticator/master/screenshots/010-elastic_skin_config.png)

Security incident 2022-04-02
----------------------------

[](#security-incident-2022-04-02)

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

I make a little modification on script to not allow to save config without param session generated from a rendered page, to force user to introduce previously 2FA code and navigate across site.

NOTE: Also I check if user have 2FA activated because with only first condition -check SESSION- app kick out me before to activate 2FA.

#### `twofactor_gauthenticator_save()`

[](#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

[](#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

29

—

LowBetter than 60% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity22

Limited adoption so far

Community22

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 71% 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/36291d0ff9126e11641fe3805397bab26324f5514741f5b48b18fa8f183fdbd8?d=identicon)[camilo3rd](/maintainers/camilo3rd)

---

Top Contributors

[![alexandregz](https://avatars.githubusercontent.com/u/1374718?v=4)](https://github.com/alexandregz "alexandregz (147 commits)")[![corbolais](https://avatars.githubusercontent.com/u/5993400?v=4)](https://github.com/corbolais "corbolais (9 commits)")[![cooldark](https://avatars.githubusercontent.com/u/15010571?v=4)](https://github.com/cooldark "cooldark (7 commits)")[![bukowski12](https://avatars.githubusercontent.com/u/1533077?v=4)](https://github.com/bukowski12 "bukowski12 (6 commits)")[![helmo](https://avatars.githubusercontent.com/u/104120?v=4)](https://github.com/helmo "helmo (5 commits)")[![tborgans](https://avatars.githubusercontent.com/u/1382329?v=4)](https://github.com/tborgans "tborgans (4 commits)")[![camilord](https://avatars.githubusercontent.com/u/2794294?v=4)](https://github.com/camilord "camilord (4 commits)")[![bilbolodz](https://avatars.githubusercontent.com/u/4696144?v=4)](https://github.com/bilbolodz "bilbolodz (2 commits)")[![condless](https://avatars.githubusercontent.com/u/55792802?v=4)](https://github.com/condless "condless (2 commits)")[![limer-org](https://avatars.githubusercontent.com/u/2848202?v=4)](https://github.com/limer-org "limer-org (2 commits)")[![numericOverflow](https://avatars.githubusercontent.com/u/3429424?v=4)](https://github.com/numericOverflow "numericOverflow (2 commits)")[![PeteLawler](https://avatars.githubusercontent.com/u/168658?v=4)](https://github.com/PeteLawler "PeteLawler (2 commits)")[![Anagastes](https://avatars.githubusercontent.com/u/17494592?v=4)](https://github.com/Anagastes "Anagastes (2 commits)")[![Zerogiven](https://avatars.githubusercontent.com/u/389319?v=4)](https://github.com/Zerogiven "Zerogiven (1 commits)")[![bartnv](https://avatars.githubusercontent.com/u/2384399?v=4)](https://github.com/bartnv "bartnv (1 commits)")[![christiannageby](https://avatars.githubusercontent.com/u/3834522?v=4)](https://github.com/christiannageby "christiannageby (1 commits)")[![diegoweb](https://avatars.githubusercontent.com/u/12632119?v=4)](https://github.com/diegoweb "diegoweb (1 commits)")[![FlorianLaunay](https://avatars.githubusercontent.com/u/12810801?v=4)](https://github.com/FlorianLaunay "FlorianLaunay (1 commits)")[![k-aino](https://avatars.githubusercontent.com/u/20009629?v=4)](https://github.com/k-aino "k-aino (1 commits)")[![michal-zila](https://avatars.githubusercontent.com/u/88778495?v=4)](https://github.com/michal-zila "michal-zila (1 commits)")

### Embed Badge

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

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

###  Alternatives

[namshi/jose

JSON Object Signing and Encryption library for PHP.

1.8k99.6M101](/packages/namshi-jose)[league/oauth1-client

OAuth 1.0 Client Library

99698.8M106](/packages/league-oauth1-client)[bezhansalleh/filament-shield

Filament support for `spatie/laravel-permission`.

2.8k2.9M88](/packages/bezhansalleh-filament-shield)[gesdinet/jwt-refresh-token-bundle

Implements a refresh token system over Json Web Tokens in Symfony

70516.4M35](/packages/gesdinet-jwt-refresh-token-bundle)[league/oauth2-google

Google OAuth 2.0 Client Provider for The PHP League OAuth2-Client

41721.2M118](/packages/league-oauth2-google)[illuminate/auth

The Illuminate Auth package.

9327.3M1.0k](/packages/illuminate-auth)

PHPackages © 2026

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