{"id":300820,"date":"2026-05-01T00:34:09","date_gmt":"2026-05-01T00:34:09","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/super-duper-2fa-login-security\/"},"modified":"2026-08-26T22:05:13","modified_gmt":"2026-08-26T22:05:13","slug":"super-duper-two-factor-login","status":"publish","type":"plugin","link":"https:\/\/hau.wordpress.org\/plugins\/super-duper-two-factor-login\/","author":15303434,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"2.6.4","stable_tag":"2.6.4","tested":"7.1","requires":"6.8","requires_php":"8.2","requires_plugins":null,"header_name":"Super Duper Two-Factor Login","header_author":"Super Duper Plugins","header_description":"Two-factor authentication for WordPress \u2013 TOTP & email, backup codes, recovery keys, trusted devices and role-based enforcement. Completely free.","assets_banners_color":"ca1727","last_updated":"2026-08-26 22:05:13","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/wordpress.org\/plugins\/super-duper-two-factor-login\/","header_author_uri":"https:\/\/superduperplugins.ch","rating":0,"author_block_rating":0,"active_installs":20,"downloads":760,"num_ratings":0,"support_threads":1,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"2.5.11":{"tag":"2.5.11","author":"rogerruckstuhl","date":"2026-05-05 20:42:57","revision":3523798},"2.5.12":{"tag":"2.5.12","author":"rogerruckstuhl","date":"2026-05-11 21:00:35","revision":3529204},"2.5.13":{"tag":"2.5.13","author":"rogerruckstuhl","date":"2026-05-13 08:16:57","revision":3530692},"2.5.14":{"tag":"2.5.14","author":"rogerruckstuhl","date":"2026-05-20 21:17:01","revision":3540130},"2.5.5":{"tag":"2.5.5","author":"rogerruckstuhl","date":"2026-05-01 00:33:49","revision":3520060},"2.5.9":{"tag":"2.5.9","author":"rogerruckstuhl","date":"2026-05-05 20:42:57","revision":3523798},"2.6.0":{"tag":"2.6.0","author":"rogerruckstuhl","date":"2026-08-10 08:41:35","revision":3640228},"2.6.2":{"tag":"2.6.2","author":"rogerruckstuhl","date":"2026-08-10 11:21:42","revision":3640448},"2.6.3":{"tag":"2.6.3","author":"rogerruckstuhl","date":"2026-08-26 06:20:19","revision":3666325},"2.6.4":{"tag":"2.6.4","author":"rogerruckstuhl","date":"2026-08-26 22:05:13","revision":3667839}},"upgrade_notice":{"2.6.4":"<p>The setup QR code was rastered too finely to be scanned off the screen, especially with the site logo enabled. It is now larger and a real image. The setup screen also states clearly why the second factor belongs on a device separate from your password.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3627114,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3627114,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3627114,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3627114,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["2.5.11","2.5.12","2.5.13","2.5.14","2.5.5","2.5.9","2.6.0","2.6.2","2.6.3","2.6.4"],"block_files":[],"assets_screenshots":{"screenshot-1.jpg":{"filename":"screenshot-1.jpg","revision":3520060,"resolution":"1","location":"assets","locale":"","width":1560,"height":756},"screenshot-10.jpg":{"filename":"screenshot-10.jpg","revision":3520060,"resolution":"10","location":"assets","locale":"","width":1816,"height":1426},"screenshot-11.jpg":{"filename":"screenshot-11.jpg","revision":3520060,"resolution":"11","location":"assets","locale":"","width":1762,"height":1104},"screenshot-12.jpg":{"filename":"screenshot-12.jpg","revision":3520060,"resolution":"12","location":"assets","locale":"","width":2354,"height":1604},"screenshot-13.jpg":{"filename":"screenshot-13.jpg","revision":3520060,"resolution":"13","location":"assets","locale":"","width":1732,"height":576},"screenshot-14.jpg":{"filename":"screenshot-14.jpg","revision":3520060,"resolution":"14","location":"assets","locale":"","width":2460,"height":1354},"screenshot-2.jpg":{"filename":"screenshot-2.jpg","revision":3520060,"resolution":"2","location":"assets","locale":"","width":1292,"height":1100},"screenshot-3.jpg":{"filename":"screenshot-3.jpg","revision":3520060,"resolution":"3","location":"assets","locale":"","width":1288,"height":1206},"screenshot-4.jpg":{"filename":"screenshot-4.jpg","revision":3520060,"resolution":"4","location":"assets","locale":"","width":1278,"height":1632},"screenshot-5.jpg":{"filename":"screenshot-5.jpg","revision":3520060,"resolution":"5","location":"assets","locale":"","width":1062,"height":1050},"screenshot-6.jpg":{"filename":"screenshot-6.jpg","revision":3520060,"resolution":"6","location":"assets","locale":"","width":1336,"height":1128},"screenshot-7.jpg":{"filename":"screenshot-7.jpg","revision":3520060,"resolution":"7","location":"assets","locale":"","width":2140,"height":1516},"screenshot-8.jpg":{"filename":"screenshot-8.jpg","revision":3520060,"resolution":"8","location":"assets","locale":"","width":1450,"height":966},"screenshot-9.jpg":{"filename":"screenshot-9.jpg","revision":3520060,"resolution":"9","location":"assets","locale":"","width":1860,"height":1414}},"screenshots":{"1":"Admin notice prompting users to set up 2FA","2":"Setup prompt asking the user to start now or later","3":"Choosing the authentication method: email or authenticator app","4":"App-based authentication \u2013 FreeOTP recommended, with download links","5":"Email-based authentication","6":"Email confirmation step","7":"Backup codes \u2013 send by email, download, or print","8":"Shortcode displaying the 2FA status on any page","9":"2FA status on the user's My Account page \u2013 inactive","10":"2FA status on the user's My Account page \u2013 active, with the chosen method","11":"Backend admin view: per-account 2FA status and the method in use","12":"Settings: enforcement reminder, which roles must use 2FA, grace period, enforcement areas, validation strictness (strict \/ normal \/ tolerant), and trusted-device duration","13":"Shortcode for embedding the 2FA status indicator on any page","14":"Privacy &amp; Hardening: hide user data in the REST API and disable password reset per role"}},"plugin_section":[],"plugin_tags":[9211,9212,600,9217,286],"plugin_category":[38,54],"plugin_contributors":[242870],"plugin_business_model":[],"class_list":["post-300820","plugin","type-plugin","status-publish","hentry","plugin_tags-2fa","plugin_tags-authenticator","plugin_tags-security","plugin_tags-two-factor","plugin_tags-woocommerce","plugin_category-authentication","plugin_category-security-and-spam-protection","plugin_contributors-rogerruckstuhl","plugin_committers-rogerruckstuhl"],"banners":{"banner":"https:\/\/ps.w.org\/super-duper-two-factor-login\/assets\/banner-772x250.png?rev=3627114","banner_2x":"https:\/\/ps.w.org\/super-duper-two-factor-login\/assets\/banner-1544x500.png?rev=3627114","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/super-duper-two-factor-login\/assets\/icon-128x128.png?rev=3627114","icon_2x":"https:\/\/ps.w.org\/super-duper-two-factor-login\/assets\/icon-256x256.png?rev=3627114","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/super-duper-two-factor-login\/assets\/screenshot-1.jpg?rev=3520060","caption":"Admin notice prompting users to set up 2FA"},{"src":"https:\/\/ps.w.org\/super-duper-two-factor-login\/assets\/screenshot-2.jpg?rev=3520060","caption":"Setup prompt asking the user to start now or later"},{"src":"https:\/\/ps.w.org\/super-duper-two-factor-login\/assets\/screenshot-3.jpg?rev=3520060","caption":"Choosing the authentication method: email or authenticator app"},{"src":"https:\/\/ps.w.org\/super-duper-two-factor-login\/assets\/screenshot-4.jpg?rev=3520060","caption":"App-based authentication \u2013 FreeOTP recommended, with download links"},{"src":"https:\/\/ps.w.org\/super-duper-two-factor-login\/assets\/screenshot-5.jpg?rev=3520060","caption":"Email-based authentication"},{"src":"https:\/\/ps.w.org\/super-duper-two-factor-login\/assets\/screenshot-6.jpg?rev=3520060","caption":"Email confirmation step"},{"src":"https:\/\/ps.w.org\/super-duper-two-factor-login\/assets\/screenshot-7.jpg?rev=3520060","caption":"Backup codes \u2013 send by email, download, or print"},{"src":"https:\/\/ps.w.org\/super-duper-two-factor-login\/assets\/screenshot-8.jpg?rev=3520060","caption":"Shortcode displaying the 2FA status on any page"},{"src":"https:\/\/ps.w.org\/super-duper-two-factor-login\/assets\/screenshot-9.jpg?rev=3520060","caption":"2FA status on the user's My Account page \u2013 inactive"},{"src":"https:\/\/ps.w.org\/super-duper-two-factor-login\/assets\/screenshot-10.jpg?rev=3520060","caption":"2FA status on the user's My Account page \u2013 active, with the chosen method"},{"src":"https:\/\/ps.w.org\/super-duper-two-factor-login\/assets\/screenshot-11.jpg?rev=3520060","caption":"Backend admin view: per-account 2FA status and the method in use"},{"src":"https:\/\/ps.w.org\/super-duper-two-factor-login\/assets\/screenshot-12.jpg?rev=3520060","caption":"Settings: enforcement reminder, which roles must use 2FA, grace period, enforcement areas, validation strictness (strict \/ normal \/ tolerant), and trusted-device duration"},{"src":"https:\/\/ps.w.org\/super-duper-two-factor-login\/assets\/screenshot-13.jpg?rev=3520060","caption":"Shortcode for embedding the 2FA status indicator on any page"},{"src":"https:\/\/ps.w.org\/super-duper-two-factor-login\/assets\/screenshot-14.jpg?rev=3520060","caption":"Privacy &amp; Hardening: hide user data in the REST API and disable password reset per role"}],"raw_content":"<!--section=description-->\n<p><strong>Super Duper Two-Factor Login<\/strong> adds robust two-factor authentication to your WordPress site. Unlike many alternatives, this plugin is completely free \u2013 no hidden costs, no premium tiers, no upsells. Every feature is included from the start.<\/p>\n\n<p>\ud83c\udde8\ud83c\udded\ud83c\udde9\ud83c\uddea\ud83c\udde6\ud83c\uddf9 <em>Hinweis f\u00fcr DACH-Nutzer: Plugin und Support sind auf Deutsch (Schweiz\/Deutschland\/\u00d6sterreich) verf\u00fcgbar. Alle Texte und Einstellungen sind vollst\u00e4ndig auf Deutsch \u00fcbersetzt.<\/em><\/p>\n\n<p><strong>Fully translated out of the box<\/strong> in German (Switzerland, Germany, Austria), English, French, Spanish, Italian and Dutch \u2013 no separate language pack required.<\/p>\n\n<h4>PHP 8.2 or higher required (for security reasons)<\/h4>\n\n<p>This plugin requires <strong>PHP 8.2 or higher<\/strong>. PHP 8.0 and 8.1 have both reached End of Life and no longer receive security updates \u2013 running a 2FA plugin on an unmaintained PHP version would defeat its purpose. PHP 8.2 lets us use modern security primitives (immutable configuration, type-safe method handling, strict return contracts) that make the plugin harder to attack.<\/p>\n\n<p><strong>Don't have PHP 8.2 yet?<\/strong> Most hosting providers let you switch the PHP version with a single click in the control panel (Plesk, cPanel, Hostpoint, all-inkl, Cyon, raidboxes, etc.). It usually takes less than a minute and does not require any downtime. If in doubt, ask your hoster's support \u2013 they help with PHP upgrades for free.<\/p>\n\n<h4>Two Verification Methods<\/h4>\n\n<ul>\n<li><strong>TOTP (Authenticator App)<\/strong> \u2013 Works with Google Authenticator, FreeOTP+, Authy, Microsoft Authenticator, and any TOTP-compatible app. Setup via QR code or manual key entry.<\/li>\n<li><strong>Email<\/strong> \u2013 Receive a 6-digit code via email on every login. No smartphone required.<\/li>\n<\/ul>\n\n<h4>Comprehensive Fallback System<\/h4>\n\n<ul>\n<li><strong>10 Backup Codes<\/strong> \u2013 One-time emergency codes in case you lose your phone. Copy, download, print, or email them to yourself.<\/li>\n<li><strong>Administrator Recovery Key<\/strong> \u2013 Each admin receives a personal 32-character key during setup. Works even when all backup codes are used up.<\/li>\n<li><strong>FTP Emergency Recovery (optional, off by default)<\/strong> \u2013 As a last resort, an empty file created via FTP can switch 2FA off for administrators. The file name has to contain a secret token that is generated in the settings and shown once (<code>wp-content\/.sdtfa-recovery-&lt;TOKEN&gt;<\/code>), and it is only accepted for 15 minutes after it was created. All administrators are notified by email, both when it is used and when an invalid file shows up.<\/li>\n<\/ul>\n\n<h4>Enforcement &amp; Trust<\/h4>\n\n<ul>\n<li><strong>Role-Based Enforcement<\/strong> \u2013 Require 2FA for administrators, editors, subscribers, or any role.<\/li>\n<li><strong>Grace Period<\/strong> \u2013 Set a deadline so users have time to set up 2FA before enforcement kicks in.<\/li>\n<li><strong>Hard Enforcement<\/strong> \u2013 Without a grace period, users must complete 2FA setup on the login page before gaining any access.<\/li>\n<li><strong>Enforcement Areas<\/strong> \u2013 Choose where to enforce: admin area, WooCommerce account, checkout, or entire site.<\/li>\n<li><strong>Trust This Device<\/strong> \u2013 Users can save their computer so the 2FA code isn't required on every login. Configurable duration (1\u2013365 days).<\/li>\n<\/ul>\n\n<h4>Integration<\/h4>\n\n<ul>\n<li><strong>WooCommerce<\/strong> \u2013 Adds a \"Two-Factor Authentication\" tab to the My Account page. Enforce 2FA for the account area and checkout.<\/li>\n<li><strong>Shortcode<\/strong> \u2013 Display the user's 2FA status anywhere with <code>[sdtfa_status]<\/code>.<\/li>\n<li><strong>Setup Reminder<\/strong> \u2013 A dismissable admin notice with a \"Set up now\" button. No auto-popups; users open the setup flow only by clicking.<\/li>\n<\/ul>\n\n<h4>Security<\/h4>\n\n<ul>\n<li>AES-256-GCM encryption for TOTP secrets at rest<\/li>\n<li>Secure HttpOnly cookies for trusted devices<\/li>\n<li>Hashed token storage (never stored in plain text)<\/li>\n<li>No external dependencies \u2013 everything runs locally in pure PHP<\/li>\n<li>No third-party API calls, no tracking, no data collection. The only HTTP request the plugin ever makes goes to your own site, and only when you click \"Run live test\" in the hardening section<\/li>\n<\/ul>\n\n<h4>Privacy &amp; Hardening (optional)<\/h4>\n\n<ul>\n<li><p><strong>Hide user data in REST API<\/strong> \u2013 Replace sensitive user fields (name, slug, link, avatar) with neutral values for unauthenticated requests. The REST endpoint stays reachable for SEO and import tools, but anonymous visitors no longer see real display names. Uses a strict whitelist that automatically drops any extra fields injected by SEO, page-builder or e-commerce plugins (Yoast, Rank Math, AIOSEO, Elementor, WooCommerce, \u2026). Example response for an anonymous visitor on <code>\/wp-json\/wp\/v2\/users\/1<\/code>:<\/p>\n\n<p>{\"id\":1,\"name\":\"Author\",\"url\":\"\",\"description\":\"\",\"link\":\"https:\\\/\\\/example.com\\\/\",\"slug\":\"author\",\"avatar_urls\":{}}<\/p><\/li>\n<li><p><strong>Block author archives<\/strong> \u2013 Redirect unauthenticated visitors away from <code>?author=N<\/code> and <code>\/author\/&lt;slug&gt;\/<\/code> to prevent user enumeration.<\/p><\/li>\n<li><strong>Disable password reset<\/strong> \u2013 Disable the \"Lost your password?\" function for administrators and\/or selected roles. Useful when 2FA must be the only authentication path.<\/li>\n<li><strong>Users list column<\/strong> \u2013 A clean \"SDTFA\" column on Users \u2192 All Users that shows the real 2FA status (TOTP, Email, or off) and replaces duplicate columns added by host mu-plugins or other 2FA plugins.<\/li>\n<\/ul>\n\n<h4>Server &amp; File Hardening (optional)<\/h4>\n\n<p>A strong login does not help when a single uploaded file can take over the whole site. This section closes that path. Every switch is optional and off by default.<\/p>\n\n<ul>\n<li><strong>Block PHP in the uploads folder<\/strong> \u2013 The single most effective measure against an uploaded web shell: even if a malicious file makes it into <code>wp-content\/uploads\/<\/code>, the server refuses to execute it. The plugin writes a managed rule block into the uploads and upgrade folders and leaves everything else in those files untouched. A <strong>live test<\/strong> drops a harmless probe file, requests it over HTTP and tells you whether your server really refuses to run it \u2013 the only way to be sure, and it covers nginx too, where .htaccess files are silently ignored. Both probe files are deleted immediately. Ready-made nginx rules are shown for servers without .htaccess support.<\/li>\n<li><strong>Reject dangerous file types<\/strong> \u2013 Uploads of PHP and other server-side scripts are refused before the file is stored. Every extension segment is checked, so the classic <code>photo.php.jpg<\/code> trick is caught as well, and files whose name starts with a dot (<code>.htaccess<\/code>, <code>.user.ini<\/code>) are refused.<\/li>\n<li><strong>Protect sensitive files<\/strong> \u2013 Denies public access to <code>debug.log<\/code>, <code>readme.html<\/code> (which reveals your exact WordPress version), <code>license.txt<\/code>, database dumps, backup and editor left-overs, <code>.env<\/code>, <code>.user.ini<\/code> and version-control folders such as <code>.git<\/code>.<\/li>\n<li><strong>Block XML-RPC<\/strong> \u2013 <code>xmlrpc.php<\/code> allows hundreds of password guesses in a single request and is a popular way around login rate limits. It also powers pingback amplification attacks. The X-Pingback header and the RSD link are removed as well.<\/li>\n<li><strong>Disable the file editor<\/strong> \u2013 Removes the built-in plugin and theme file editors, the same effect as <code>DISALLOW_FILE_EDIT<\/code>. Anyone who gets hold of an administrator account can otherwise write PHP straight into your site from the browser.<\/li>\n<li><strong>Disable plugin\/theme installation<\/strong> \u2013 The same effect as <code>DISALLOW_FILE_MODS<\/code>, so a stolen administrator account cannot install a backdoor plugin. For sites that deploy over FTP, Git or a pipeline. Both options use WordPress' own filters instead of defining constants, so nothing in your <code>wp-config.php<\/code> is touched and an existing setting there always wins.<\/li>\n<li><strong>File permission report<\/strong> \u2013 Shows the current permissions of <code>wp-config.php<\/code>, <code>wp-content<\/code>, uploads, plugins and themes next to the recommended values and flags world-writable paths. This is a report only \u2013 the plugin never changes permissions by itself.<\/li>\n<\/ul>\n\n<p>Rules written to the .htaccess in your WordPress root are verified with a request to your own site afterwards. If your server rejects them, the block is removed again automatically, so a restrictive server configuration can never take your site offline.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin via <strong>Plugins \u2192 Add New \u2192 Upload Plugin<\/strong>, or install it directly from the WordPress plugin directory.<\/li>\n<li>Activate the plugin.<\/li>\n<li>Configure the main 2FA settings under <strong>Two-Factor Login<\/strong> in the admin menu. Optional <strong>Privacy &amp; Hardening<\/strong> features (REST user-data masking, author-archive blocking, password-reset lock-down, users-list status column) are on the same settings page.<\/li>\n<li>Optional: open <strong>Server &amp; File Hardening<\/strong> on the same page, tick \"Block PHP in the uploads folder\", save, and click <strong>Run live test<\/strong> to confirm your server really refuses to execute uploaded scripts.<\/li>\n<li>Users can set up 2FA from their WordPress profile page or WooCommerce My Account.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"which%20authenticator%20apps%20are%20supported%3F\"><h3>Which authenticator apps are supported?<\/h3><\/dt>\n<dd><p>Any TOTP-compatible app works, including Google Authenticator, FreeOTP+, Authy, Microsoft Authenticator, and many others. We recommend FreeOTP+ (Android) and FreeOTP (iOS) as free, open-source options.<\/p><\/dd>\n<dt id=\"can%20i%20store%20the%20one-time%20codes%20in%20my%20password%20manager%3F\"><h3>Can I store the one-time codes in my password manager?<\/h3><\/dt>\n<dd><p>Technically yes \u2013 any password manager with TOTP support accepts the manual key shown underneath the QR code. We advise against it. Two-factor authentication only works because the two factors live in different places. If your password and your one-time codes sit in the same vault, a single compromised vault hands an attacker both factors at once, and you are back to single-factor security. Keep the second factor on a separate device; a free authenticator app on your phone is enough.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20i%20lose%20my%20phone%3F\"><h3>What happens if I lose my phone?<\/h3><\/dt>\n<dd><p>You can log in using one of your 10 backup codes. If those are also gone, administrators can use their personal recovery key on the login page. As a last resort there is the FTP emergency file, but it has to be switched on beforehand under Emergency access \u2013 see the question about it further down.<\/p><\/dd>\n<dt id=\"can%20i%20enforce%202fa%20for%20all%20users%3F\"><h3>Can I enforce 2FA for all users?<\/h3><\/dt>\n<dd><p>Yes. Go to Two-Factor Login settings and select which roles must use 2FA. You can set a grace period with a deadline, or enforce it immediately \u2013 users will then be required to complete 2FA setup on the login page before gaining any access.<\/p><\/dd>\n<dt id=\"does%20this%20plugin%20work%20with%20woocommerce%3F\"><h3>Does this plugin work with WooCommerce?<\/h3><\/dt>\n<dd><p>Yes. It adds a \"Two-Factor Authentication\" tab to the WooCommerce My Account page. You can also enforce 2FA for the WooCommerce account area and checkout.<\/p><\/dd>\n<dt id=\"what%20is%20the%20%22trust%20this%20device%22%20feature%3F\"><h3>What is the \"Trust this device\" feature?<\/h3><\/dt>\n<dd><p>When enabled by the admin, users can check \"Save this computer\" during login. The 2FA code won't be required again on that device for the configured number of days.<\/p><\/dd>\n<dt id=\"are%20external%20services%20or%20images%20used%3F\"><h3>Are external services or images used?<\/h3><\/dt>\n<dd><p>No. Everything runs locally. QR codes are rendered in your own browser by a small bundled script, TOTP calculations happen on the server, and app store badges use local SVG files. No external images, scripts, or API calls are made. The one HTTP request the plugin can make goes to your own website: the optional live test in the hardening section requests a probe file from your own uploads folder to check whether the server executes it. It only runs when you click the button, and no third party is involved.<\/p><\/dd>\n<dt id=\"what%20does%20%22block%20php%20in%20the%20uploads%20folder%22%20actually%20do%3F\"><h3>What does \"Block PHP in the uploads folder\" actually do?<\/h3><\/dt>\n<dd><p>Most break-ins that start with a file upload only become dangerous at the moment the server executes that file. The uploads folder is meant for images and documents \u2013 there is never a legitimate reason to run PHP in there. The plugin writes a rule block into <code>wp-content\/uploads\/.htaccess<\/code> (and the same for <code>wp-content\/upgrade\/<\/code>) that tells the server to refuse PHP and other scripts in that directory. Existing content in those files is preserved; the plugin only manages its own clearly marked block.<\/p><\/dd>\n<dt id=\"the%20live%20test%20says%20%22not%20protected%22.%20what%20now%3F\"><h3>The live test says \"not protected\". What now?<\/h3><\/dt>\n<dd><p>Two common causes. On <strong>nginx<\/strong>, .htaccess files are ignored entirely \u2013 open the \"Rules for nginx\" box below the test and add those lines to your server configuration (or ask your host to). On <strong>Apache<\/strong>, the directives may be disabled by <code>AllowOverride<\/code>; your host can enable them or add the rules to the server configuration for you. In both cases the other options in this section (upload filter, XML-RPC blocking, file editor, plugin installation) still work, because they do not depend on .htaccess.<\/p><\/dd>\n<dt id=\"will%20the%20upload%20filter%20block%20files%20i%20legitimately%20need%3F\"><h3>Will the upload filter block files I legitimately need?<\/h3><\/dt>\n<dd><p>It blocks executable server-side scripts \u2013 PHP, Perl, Python, shell scripts, ASP, JSP and similar \u2013 plus files whose name starts with a dot. Images, PDFs, videos, ZIP archives and office documents are unaffected. If your site genuinely needs to offer one of the blocked types as a download, a developer can adjust the list with the <code>sdtfa_blocked_upload_extensions<\/code> filter.<\/p><\/dd>\n<dt id=\"is%20it%20safe%20to%20switch%20on%20%22disable%20plugin%2Ftheme%20installation%22%3F\"><h3>Is it safe to switch on \"Disable plugin\/theme installation\"?<\/h3><\/dt>\n<dd><p>Only if you update your site another way. The option blocks every install, update and delete through the dashboard \u2013 including WordPress core updates, this plugin's own updates and automatic security updates. It is the right choice for sites deployed over FTP, Git or a pipeline, and the wrong choice for a site that relies on the update button. You can switch it off again in these settings at any time; you are never locked out of the setting itself.<\/p><\/dd>\n<dt id=\"how%20do%20i%20remove%20the%20rules%20the%20plugin%20wrote%3F\"><h3>How do I remove the rules the plugin wrote?<\/h3><\/dt>\n<dd><p>Switch the matching option off and save \u2013 the plugin removes its own block again. Uninstalling the plugin does the same. If you prefer to do it by hand, delete everything between <code># BEGIN Super Duper Two-Factor Login<\/code> and <code># END Super Duper Two-Factor Login<\/code> in the affected .htaccess file. Nothing outside those two markers is ever touched.<\/p><\/dd>\n<dt id=\"how%20does%20the%20ftp%20emergency%20file%20work%2C%20and%20why%20is%20it%20off%20by%20default%3F\"><h3>How does the FTP emergency file work, and why is it off by default?<\/h3><\/dt>\n<dd><p>It is the last rung of the recovery ladder, for the case where 2FA, backup codes and the personal recovery key are all unavailable. Switch it on under <strong>Emergency access<\/strong>; the plugin then shows a file name containing a secret token, exactly once. Note it down and keep it with your recovery key. In an emergency, create an empty file with that exact name in <code>wp-content\/<\/code> via FTP or your hosting file manager, and 2FA is skipped for administrators for the next 15 minutes.<\/p>\n\n<p>It is off by default because up to version 2.6.1 the plain existence of a file named <code>.sdtfa-recovery<\/code> was enough. That turned \"an attacker can write a file into wp-content\" into a way past two-factor authentication, without any code execution. The token in the file name and the 15-minute window close that; leaving the whole mechanism off closes it completely. If you never switched it on, there is nothing to do.<\/p><\/dd>\n<dt id=\"does%20the%20plugin%20change%20file%20permissions%3F\"><h3>Does the plugin change file permissions?<\/h3><\/dt>\n<dd><p>No. The permission report shows what is set and what is recommended, and nothing else. Changing permissions automatically is a good way to lock a web server out of its own files on shared hosting, so the plugin leaves that decision \u2013 and the actual chmod \u2013 to you or your host.<\/p><\/dd>\n<dt id=\"what%20does%20the%20%22privacy%20%26%20hardening%22%20section%20do%3F\"><h3>What does the \"Privacy &amp; Hardening\" section do?<\/h3><\/dt>\n<dd><p>It bundles four optional, independently toggleable features that close common WordPress information-leak and lock-out paths. Hide user data (REST API) replaces sensitive fields (name, slug, link, avatar) with neutral values for unauthenticated requests, while keeping the endpoint reachable so SEO and import plugins still work. Block author archives redirects unauthenticated visitors away from <code>?author=N<\/code> and <code>\/author\/&lt;slug&gt;\/<\/code> to prevent user enumeration. Disable password reset blocks the \"Lost your password?\" function for administrators and\/or selected roles. The users-list column adds a clean \"SDTFA\" status indicator on Users \u2192 All Users. All four features are off by default except the users-list column, which is on by default to clean up duplicate columns from other plugins.<\/p><\/dd>\n<dt id=\"why%20does%20the%20users%20%E2%86%92%20all%20users%20page%20show%20an%20%22sdtfa%22%20column%20instead%20of%20a%20generic%20%222fa%22%20one%3F\"><h3>Why does the Users \u2192 All Users page show an \"SDTFA\" column instead of a generic \"2FA\" one?<\/h3><\/dt>\n<dd><p>Some hosts and other 2FA plugins inject their own \"2FA\" column on the users list. When Super Duper Two-Factor Login is installed, those columns can show outdated or misleading status (for example a red \u2717 even though 2FA is configured here). The plugin replaces them with a single, accurate \"SDTFA\" column that reads the real status from this plugin's own user meta. If you prefer the original column behavior, you can disable this in the Privacy &amp; Hardening section.<\/p><\/dd>\n<dt id=\"will%20this%20plugin%20conflict%20with%20other%202fa%20plugins%3F\"><h3>Will this plugin conflict with other 2FA plugins?<\/h3><\/dt>\n<dd><p>It is not designed to run side-by-side with another active 2FA plugin \u2013 two plugins both intercepting <code>wp-login.php<\/code> will produce unpredictable results. If you are migrating from another 2FA plugin, deactivate the other one first. The \"SDTFA\" users-list column will hide a leftover column from a deactivated plugin only if that plugin still injects it; in normal cases the foreign column simply disappears with the foreign plugin.<\/p><\/dd>\n<dt id=\"is%20this%20plugin%20really%20free%3F\"><h3>Is this plugin really free?<\/h3><\/dt>\n<dd><p>Yes, completely. There is no premium version, no upsells, and no feature restrictions. All features are available to everyone.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>2.6.4 \u2013 26.08.2026<\/h4>\n\n<ul>\n<li><strong>Fixed: the setup QR code was rastered too finely to be read off the screen.<\/strong> The code was scaled to a fixed overall width, so every additional character in its content made the individual squares smaller \u2013 with the site logo switched on it ended up at 3 pixels per square. A phone camera pointed at a monitor, and any password manager that scans the screen, needs roughly 5 to 6. The code is now sized from its content instead and always renders at 5 to 6 pixels per square.<\/li>\n<li>Improved: the QR code is now a real image rather than a canvas element. Right-click to copy or save it works, printing it is reliable, and software that looks for a QR code on the page can actually find one.<\/li>\n<li>New: the setup screen now says plainly that we recommend a separate authenticator app on your phone \u2013 and why. One-time codes kept in the same password manager as the password collapse both factors into a single vault.<\/li>\n<li>Fixed: the FAQ claimed QR codes were generated in PHP. They are rendered in your own browser; either way nothing leaves your site.<\/li>\n<li>Compatibility: tested with WordPress 7.1, which clears the \"not tested with your version of WordPress\" warning.<\/li>\n<\/ul>","raw_excerpt":"Free 2FA for WordPress: authenticator app, email codes, backup codes, WooCommerce, role enforcement, plus optional server and upload hardening.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/hau.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/300820","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hau.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/hau.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/hau.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=300820"}],"author":[{"embeddable":true,"href":"https:\/\/hau.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/rogerruckstuhl"}],"wp:attachment":[{"href":"https:\/\/hau.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=300820"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/hau.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=300820"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/hau.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=300820"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/hau.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=300820"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/hau.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=300820"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/hau.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=300820"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}