=== Sergeev Studio Two-Factor Login – 2FA ===
Contributors: sergeevstudio
Tags: two-factor, 2fa, totp, telegram, login security
Requires at least: 6.2
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.0.6
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Two-factor login for WordPress with codes from an authenticator app or a Telegram bot, backup codes and required 2FA for chosen roles.

== Description ==

A stolen or guessed password is the most common way into a WordPress dashboard. This plugin adds a second step to the login: after the password, the user enters a one-time code that only their phone has.

**Ways to get the code**

* **Authenticator app** — Google Authenticator, Yandex Key, Microsoft Authenticator, 1Password, Bitwarden or any other app that supports TOTP (RFC 6238). Works offline, no external services. The QR code for setup is drawn in the browser, so the secret never leaves the site.
* **Telegram** — the site's own bot sends a 6-digit code to the user's Telegram. Optional; the administrator connects a bot created in @BotFather.
* **Backup codes** — ten one-time codes for when the phone is lost. They are created automatically when the first method is connected.

**For site owners and agencies**

* Require 2FA for chosen roles (off until you choose them). Until they set it up, those users can open nothing in the dashboard except their profile and the Two-Factor Login page.
* "Trust this device" for up to 90 days, configurable or off.
* A 2FA column in the users list and a one-click reset for a user who lost everything.
* Five wrong codes lock the login for 15 minutes.
* Password logins over XML-RPC are refused for users with 2FA (application passwords keep working).
* Emergency switch in wp-config.php if every administrator is locked out.

**Privacy and security**

* App secrets and the bot token are encrypted in the database with a key from wp-config.php, so a database dump alone does not reveal them.
* Backup codes are stored as password hashes; Telegram codes and login tickets as keyed hashes.
* Nothing is logged in until the second factor is passed: WordPress's auth cookie is not even sent after the password step.
* No tracking, no ads, no calls home. The only external service is Telegram, and only if you connect a bot.

Fully translatable; translations are delivered through translate.wordpress.org.

Telegram is a trademark of its owner. This plugin is an independent project and is not affiliated with or endorsed by Telegram.

== External services ==

This plugin can use the **Telegram Bot API** (https://api.telegram.org), operated by Telegram, to deliver login codes. It is off until an administrator enters a bot token on Settings → Two-Factor.

When it is on, the site sends requests to `api.telegram.org` from the server:

* when the administrator saves a bot token: the token, to check it (`getMe`);
* when a user connects Telegram on their Two-Factor Login page: the bot token, to read messages sent to the bot (`getUpdates`), and a confirmation message to the user's chat;
* each time a user who chose Telegram logs in: the user's Telegram chat ID and a message with the one-time code and the site name (`sendMessage`).

No passwords, e-mail addresses or other personal data from the site are sent. Telegram's terms: https://telegram.org/tos — privacy policy: https://telegram.org/privacy

Authenticator apps work entirely on the user's phone and the site; no service is contacted.

== Installation ==

1. Install and activate the plugin.
2. Go to **Users → Two-Factor Login** and connect an authenticator app (scan the QR code, enter the code to confirm). Save the backup codes it shows.
3. Optional: in **Settings → Two-Factor** choose the roles that must use 2FA and connect a Telegram bot.

Nothing is forced after activation: administrators see a one-time suggestion to turn 2FA on for themselves, and you decide in Settings → Two-Factor which roles must use it.

== Frequently Asked Questions ==

= I lost my phone. How do I log in? =

Use one of your backup codes: on the code screen click "Use a backup code". If you have none, another administrator can reset your 2FA from your user page (Users → Edit → Reset two-factor authentication).

= Every administrator is locked out. What now? =

Add this line to wp-config.php: `define( 'SS2FA_DISABLE', true );` — logins will need only the password. Log in, fix the account, then remove the line. Deleting the plugin folder over FTP works too.

= The codes from my app are always "not correct" =

Authenticator codes depend on the time. Make sure the phone sets its time automatically. The server's clock must be right as well; the plugin accepts codes up to 30 seconds early or late.

= After changing the security keys in wp-config.php the app stopped working =

App secrets are encrypted with a key derived from `AUTH_KEY` and `AUTH_SALT`. When they change, stored secrets cannot be read. Log in with a backup code or Telegram and connect the app again. To avoid this, define your own constant `SS2FA_ENCRYPTION_KEY` (a long random string) in wp-config.php before users set up 2FA, and never change it.

= Why does Telegram say the bot "has a webhook used by another service"? =

The plugin reads the bot's messages with `getUpdates`, which Telegram does not allow for bots that have a webhook. Create a separate bot for logins in @BotFather.

= Does it work with WooCommerce and other login forms? =

Yes. Any login that goes through WordPress's standard authentication is stopped after the password and sent to the code screen. After the code the user goes on to the page they asked for, or to the dashboard.

= Can a plugin that redirects on login skip the code? =

No. Auth cookies are not sent after the password step, and the session WordPress created is destroyed before the code screen. Without the code there is nothing to be logged in with.

== Screenshots ==

1. The code screen after the password.
2. Connecting an authenticator app on the Two-Factor Login page.
3. Settings: required roles, trusted devices, Telegram bot.

== Changelog ==

= 1.0.6 =
* Translations are no longer bundled with the plugin; WordPress.org delivers them from translate.wordpress.org.

= 1.0.5 =
* Plugin header: removed the Plugin URI that duplicated the Author URI.

= 1.0.4 =
* New name: Sergeev Studio Two-Factor Login – 2FA.

= 1.0.3 =
* No role is required to use 2FA right after activation; the administrator chooses roles in the settings. Administrators without 2FA see a dismissible suggestion on the dashboard and the plugins screen.

= 1.0.2 =
* Two-factor settings moved to their own page: Users → Two-Factor Login (Profile → Two-Factor Login for users who cannot manage others), also linked from the account menu at the top right. The profile keeps a short status row with a link.
* Users who must set up 2FA are sent straight to that page.

= 1.0.1 =
* The login ticket between the password and the code moved from the URL into an httpOnly cookie, so it no longer shows up in browser history, server logs or Referer headers.
* Changing or resetting a password now revokes all trusted devices.
* After five wrong codes the account owner is warned by e-mail and, if linked, in Telegram.
* The linked Telegram account is shown in the profile.
* Code fields accept digits only (6, or 1234-5678 for backup codes); pasted and autofilled codes are cleaned up.
* New setting: the name shown in authenticator apps.

= 1.0.0 =
* First release: authenticator apps (TOTP), Telegram codes, backup codes, required roles, trusted devices, lockout after wrong codes, XML-RPC protection, emergency switch.

== Third-party code ==

* QR Code Generator for JavaScript by Kazuhiko Arase, MIT license — `assets/js/vendor/qrcode.js`, https://github.com/kazuhikoarase/qrcode-generator
