PHPackages                             edunext-eu/simplesamlphp-module-simpletotp - 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. edunext-eu/simplesamlphp-module-simpletotp

ActiveSimplesamlphp-module[Authentication &amp; Authorization](/categories/authentication)

edunext-eu/simplesamlphp-module-simpletotp
==========================================

A highly configurable yet simple to use TOTP based two-factor authentication processing module for SimpleSAMLphp

2.0(3mo ago)11PHP

Since Jan 21Pushed 3mo ago1 watchersCompare

[ Source](https://github.com/edunext-eu/SimpleTOTP)[ Packagist](https://packagist.org/packages/edunext-eu/simplesamlphp-module-simpletotp)[ RSS](/packages/edunext-eu-simplesamlphp-module-simpletotp/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (1)Dependencies (1)Versions (2)Used By (0)

SimpleTOTP
==========

[](#simpletotp)

A SimpleSAMLphp auth processing filter that adds TOTP-based MFA on an IdP or SP. Recommended placement is the IdP to keep TOTP secrets off SPs. Only HMAC-SHA1 TOTP is supported for maximum compatibility with authenticator apps.

Key features
------------

[](#key-features)

- Works as an authproc filter (IdP or SP).
- Configurable secret attribute and validation timeout.
- Optional clock-drift window for TOTP verification.
- Basic per-session brute-force throttling.
- Optional bypass when secret is an empty string.

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

[](#installation)

### Via Git

[](#via-git)

Clone into the SimpleSAMLphp `modules/` directory.

### Via Composer

[](#via-composer)

Install the module from Packagist:

```
composer require edunext-eu/simplesamlphp-module-simpletotp
```

Quick start (IdP recommended)
-----------------------------

[](#quick-start-idp-recommended)

Add to `authproc.idp` in `config.php` or IdP metadata:

```
10 => array(
	'class' => 'simpletotp:mfa',
	'secret_attr' => 'totp_secret', // default
	'enforce_mfa' => false, // default
	'allow_empty_secret' => false, // default
	'not_configured_url' => NULL, // default
	'validation_timeout' => 60, // default (minutes)
	'totp_window' => 0, // default (30s steps)
	// Show a "start over" option in TOTP page (UX)
	'restart_enabled' => false, // default
	'clear_cookies' => [], // empty = use SimpleSAMLphp cookie names
	'max_attempts' => 5, // default
	'attempt_window' => 300, // default (seconds)
	// Optional hardening (requires Store configuration for 'store' or 'both')
	'totp_rate_limit_storage' => 'session', // session|store|both
	'totp_rate_limit_key' => 'uid', // uid|secret|ip|attr:
),
```

Recommended hardening (read the Configuration notes below before enabling):

```
10 => array(
	'class' => 'simpletotp:mfa',
	'totp_rate_limit_storage' => 'store',
	'totp_rate_limit_key' => 'uid',
	'restart_enabled' => true,
),
```

Remove the secret from outbound attributes (use a high priority like 98 if 99 is already taken):

```
98 => array(
	'class' => 'core:AttributeAlter',
	'subject' => 'totp_secret',
	'pattern' => '/.*/',
	'%remove',
),
```

Module enablement
-----------------

[](#module-enablement)

Enable the module via `config.php` by setting:

```
'module.enable' => [
	'simpletotp' => true,
],
```

This is preferred over the legacy `modules//enable` file because it is explicit and visible in configuration management.

SP-side example (not recommended)
---------------------------------

[](#sp-side-example-not-recommended)

Running on the SP requires sending the TOTP secret to the SP. This is not recommended and not tested in this fork:

```
10 => array(
	'class' => 'simpletotp:mfa',
	'secret_attr' => 'totp_secret',
),
```

Configuration notes
-------------------

[](#configuration-notes)

- secret\_attr: defaults to `totp_secret`. If your attributes use a different name (e.g. `ga_secret`), set it explicitly.
- enforce\_mfa: when true, users without a configured secret are blocked (or redirected to `not_configured_url`).
- allow\_empty\_secret: when true, an empty-string secret is treated as "not configured" and the user is allowed to continue.
- Interaction: `allow_empty_secret` only applies when the secret attribute exists but is an empty string. It does not override `enforce_mfa` for truly missing secrets.
- Null vs empty: "missing" means the attribute is absent or null, while "empty" means the attribute exists but the value is an empty string. This lets you use empty strings as an explicit "MFA disabled" flag.
- Recommended for DB-backed secrets: if your DB uses empty strings (e.g., `two_factor_secret = ''`) for "no MFA", set `allow_empty_secret = true` and keep `enforce_mfa = false`. For strict MFA, set `enforce_mfa = true` and require non-empty secrets.
- validation\_timeout: minutes to cache a successful MFA before re-prompting.
- totp\_window: number of 30-second steps to accept before/after the current step.
    - 0 = only the current 30s step (strict, most secure)
    - 1 = accept codes from 30s before or after (90s total window)
    - 2 = accept codes from 60s before or after (150s total window)
- max\_attempts / attempt\_window: throttles brute-force attempts.
- Form fields: new integrations should post `totp` with `autocomplete="one-time-code"`; `code` is accepted for legacy forms.
- Start over button (UX): set `simpletotp.restart_enabled = true` and (optionally) `simpletotp.clear_cookies` to clear session cookies and reload the current page for a fresh login. These options can live in global `config.php` or inside the `simpletotp:mfa` authproc configuration.
    - If `simpletotp.clear_cookies` is omitted or empty, the module uses `session.cookie.name` and `session.authtoken.cookiename` from `config.php`.
- TOTP rate limit storage: defaults to session-only. To make rate limiting robust across sessions/servers, set `totp_rate_limit_storage` to `store` (or `both`) in the `simpletotp:mfa` config and ensure `store.type` is configured (redis/memcache/sql). Use `totp_rate_limit_key` to choose the key source (`secret`, `uid`, `ip`, or `attr:`). The default key is `uid`.
    - If the configured key is missing at runtime, the limiter falls back to the TOTP secret and logs a warning.
    - `totp_rate_limit_key` uses built-in types (`uid`, `secret`, `ip`) or `attr:` to refer to a specific attribute (e.g. `attr:mail`, `attr:eduPersonPrincipalName`). The attribute must exist in the user attributes for your IdP/SP, otherwise it falls back to the secret.
    - For federations that standardize identifiers (e.g. `eduPersonPrincipalName`, `eduPersonUniqueID`, `subject-id`, `pairwise-id`), prefer one of those stable identifiers via `attr:`.
    - If `store.type` is not configured, SimpleSAMLphp falls back to `phpsession`, which is not shared across servers and can be reset by clearing cookies.
    - If `store.type` is set to an unavailable backend, store-based rate limiting falls back to session-only with a warning.
    - TOTP codes are fixed at 6 digits.
    - `clear_cookies` only uses admin-configured cookie names; it is not accepted from user input.
    - Cookie clearing only affects the current host; it does not clear cookies set on other subdomains or parent domains.

Security notes
--------------

[](#security-notes)

- TOTP secrets should remain on the IdP. Remove them from outbound attributes.
- Keep totp\_window small (default 0) to reduce acceptance of old codes.
- Basic brute-force throttling built in.
- Verification uses a timing-safe comparison and stricter base32 validation (backported from ).

Translations
------------

[](#translations)

All user-facing strings are translatable via gettext. Add or edit translations in `locales//LC_MESSAGES/simpletotp.po` (e.g. `locales/it/LC_MESSAGES/simpletotp.po` or `locales/es/LC_MESSAGES/simpletotp.po`). SimpleSAMLphp selects the language based on the user's locale settings. Translations are best-effort and may need review by native speakers; some locales may still use English strings. Pull requests or issues to refine wording are welcome.

Fork notice
-----------

[](#fork-notice)

This repository is maintained at  and is a fork of the original module. If you are upgrading from the original, update your Composer package name to `edunext-eu/simplesamlphp-module-simpletotp`.

Changes in this fork
--------------------

[](#changes-in-this-fork)

- Fixed MFA bypass by setting lastverified only on successful TOTP verification.
- Updated BadRequest class for newer SimpleSAMLphp.
- Added empty-code validation and removed sensitive debug logging.
- Added totp\_window for clock drift tolerance.
- Added rate limiting for TOTP attempts.
- Removed the legacy token generator endpoint.
- Tightened StateId handling to accept only GET/POST (no generic $\_REQUEST).
- Added timing-safe code comparison and stricter base32 validation.
- Added translations and documentation improvements.
- Removed the legacy `default-enable` file; use `module.enable` in config.php instead.

Maintenance
-----------

[](#maintenance)

Long-term maintenance for this module is not guaranteed. If you want to take stewardship, open an issue.

Disclaimer
----------

[](#disclaimer)

This software is provided "as is" without warranty of any kind; use at your own risk.

###  Health Score

33

—

LowBetter than 75% of packages

Maintenance78

Regular maintenance activity

Popularity3

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity34

Early-stage or recently created project

 Bus Factor2

2 contributors hold 50%+ of commits

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.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

117d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/29c64b31adf275e12e22f4830cace48d63af71a5263fcde41ea4c87629bd0a14?d=identicon)[PackEDUNEXT](/maintainers/PackEDUNEXT)

---

Top Contributors

[![clmcavaney](https://avatars.githubusercontent.com/u/5875512?v=4)](https://github.com/clmcavaney "clmcavaney (13 commits)")[![aidan-](https://avatars.githubusercontent.com/u/327286?v=4)](https://github.com/aidan- "aidan- (10 commits)")[![shoaibali](https://avatars.githubusercontent.com/u/180494?v=4)](https://github.com/shoaibali "shoaibali (5 commits)")[![jfautley](https://avatars.githubusercontent.com/u/241795?v=4)](https://github.com/jfautley "jfautley (2 commits)")[![gavio-dot](https://avatars.githubusercontent.com/u/196302292?v=4)](https://github.com/gavio-dot "gavio-dot (1 commits)")[![ziemek99](https://avatars.githubusercontent.com/u/15923635?v=4)](https://github.com/ziemek99 "ziemek99 (1 commits)")

### Embed Badge

![Health badge](/badges/edunext-eu-simplesamlphp-module-simpletotp/health.svg)

```
[![Health](https://phpackages.com/badges/edunext-eu-simplesamlphp-module-simpletotp/health.svg)](https://phpackages.com/packages/edunext-eu-simplesamlphp-module-simpletotp)
```

###  Alternatives

[simplesamlphp/simplesamlphp

A PHP implementation of a SAML 2.0 service provider and identity provider.

1.1k12.4M193](/packages/simplesamlphp-simplesamlphp)[simplesamlphp/simplesamlphp-module-oidc

A SimpleSAMLphp module adding support for the OpenID Connect protocol

5016.9k1](/packages/simplesamlphp-simplesamlphp-module-oidc)[drupalauth/simplesamlphp-module-drupalauth

A SimpleSAMLphp module adding support for Drupal as the authentication source.

25305.4k1](/packages/drupalauth-simplesamlphp-module-drupalauth)

PHPackages © 2026

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