{"id":307654,"date":"2026-07-19T13:16:18","date_gmt":"2026-07-19T13:16:18","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/coreguard-2fa\/"},"modified":"2026-07-19T13:16:09","modified_gmt":"2026-07-19T13:16:09","slug":"oqwall-2fa","status":"publish","type":"plugin","link":"https:\/\/is.wordpress.org\/plugins\/oqwall-2fa\/","author":21197133,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.0","stable_tag":"1.0.0","tested":"7.0.2","requires":"6.0","requires_php":"8.0","requires_plugins":null,"header_name":"Loqwall 2FA","header_author":"el aaouam Mohamed","header_description":"Lightweight Two-Factor Authentication with Email OTP and Authenticator App support.","assets_banners_color":"","last_updated":"2026-07-19 13:16:09","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"","rating":0,"author_block_rating":0,"active_installs":0,"downloads":42,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"mohamedelaaouam99","date":"2026-07-19 13:16:09"}},"upgrade_notice":{"1.0.0":"<p>Initial release. No upgrade steps required.<\/p>"},"ratings":[],"assets_icons":[],"assets_banners":[],"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.0"],"block_files":[],"assets_screenshots":[],"screenshots":{"1":"The 2FA verification screen shown after a successful password login.","2":"The Authenticator App setup screen with QR code and secret key.","3":"The plugin settings page with all configuration options.","4":"The per-user 2FA settings section on the WordPress profile page.","5":"The audit log page showing recent authentication events."}},"plugin_section":[],"plugin_tags":[9211,710,602,600,9217],"plugin_category":[38,54],"plugin_contributors":[272320],"plugin_business_model":[],"class_list":["post-307654","plugin","type-plugin","status-publish","hentry","plugin_tags-2fa","plugin_tags-authentication","plugin_tags-login","plugin_tags-security","plugin_tags-two-factor","plugin_category-authentication","plugin_category-security-and-spam-protection","plugin_contributors-mohamedelaaouam99","plugin_committers-mohamedelaaouam99"],"banners":[],"icons":{"svg":false,"icon":"https:\/\/s.w.org\/plugins\/geopattern-icon\/oqwall-2fa.svg","icon_2x":false,"generated":true},"screenshots":[],"raw_content":"<!--section=description-->\n<p>Loqwall 2FA adds a secure second authentication step after the standard WordPress username\/password login. After entering their credentials, users must verify their identity with a one-time code before gaining access.<\/p>\n\n<p><strong>Features<\/strong><\/p>\n\n<ul>\n<li><strong>Email OTP<\/strong> \u2014 a 6-digit code is sent to the user's registered email address.<\/li>\n<li><strong>Authenticator App (TOTP)<\/strong> \u2014 time-based codes compatible with Google Authenticator, Authy, Bitwarden, and any RFC 6238 app.<\/li>\n<li><strong>Backup codes<\/strong> \u2014 10 one-time recovery codes generated per user.<\/li>\n<li><strong>Device trust<\/strong> \u2014 optionally remember a trusted device for up to 30 days.<\/li>\n<li><strong>Role enforcement<\/strong> \u2014 admins can be required to use 2FA regardless of their personal preference.<\/li>\n<li><strong>Per-user control<\/strong> \u2014 users enable and configure 2FA from their own profile page.<\/li>\n<li><strong>Rate limiting<\/strong> \u2014 brute-force protection on OTP verification.<\/li>\n<li><strong>Audit log<\/strong> \u2014 every authentication event is recorded in a private database table.<\/li>\n<li><strong>No external dependencies<\/strong> \u2014 all cryptographic operations use PHP's built-in functions. No Composer, no remote APIs.<\/li>\n<li><strong>Developer-friendly<\/strong> \u2014 hooks and filters let you customise behaviour without modifying plugin files.<\/li>\n<\/ul>\n\n<h3>For Developers: Hooks &amp; Filters<\/h3>\n\n<p><strong>Filters<\/strong><\/p>\n\n<pre><code>Loqwall_2FA_required_for_user\n<\/code><\/pre>\n\n<p>Runs on every login attempt. Return <code>false<\/code> to exempt a user, or <code>true<\/code> to force 2FA regardless of settings.<\/p>\n\n<pre><code>add_filter( 'Loqwall_2FA_required_for_user', function( $required, $user ) {\n    \/\/ Exempt the user with ID 5 from 2FA.\n    if ( 5 === $user-&gt;ID ) {\n        return false;\n    }\n    return $required;\n}, 10, 2 );\n\nLoqwall_2FA_otp_email_message\n<\/code><\/pre>\n\n<p>Filters the email body before the OTP is sent. Receives the body string, the <code>WP_User<\/code> object, the plain-text 6-digit code, and a boolean indicating whether the email is HTML.<\/p>\n\n<pre><code>add_filter( 'Loqwall_2FA_otp_email_message', function( $body, $user, $code, $html_mode ) {\n    \/\/ Append a custom footer to every OTP email.\n    return $body . '&lt;p&gt;Need help? Contact support@example.com&lt;\/p&gt;';\n}, 10, 4 );\n<\/code><\/pre>\n\n<p><strong>Actions<\/strong><\/p>\n\n<pre><code>Loqwall_2FA_verified\n<\/code><\/pre>\n\n<p>Fires immediately after a user successfully passes 2FA. Receives the user ID and the method used (<code>'email'<\/code>, <code>'totp'<\/code>, or <code>'backup_code'<\/code>).<\/p>\n\n<pre><code>add_action( 'Loqwall_2FA_verified', function( $user_id, $method ) {\n    \/\/ Log the successful verification to a custom audit system.\n    my_audit_log( $user_id, 'login_verified', $method );\n}, 10, 2 );\n\nLoqwall_2FA_failed\n<\/code><\/pre>\n\n<p>Fires after each failed 2FA verification attempt. Receives the user ID and the method attempted.<\/p>\n\n<pre><code>add_action( 'Loqwall_2FA_failed', function( $user_id, $method ) {\n    \/\/ Notify an admin after a failed attempt.\n    wp_mail( get_option('admin_email'), 'Failed 2FA attempt', \"User #$user_id failed via $method.\" );\n}, 10, 2 );&lt;h3&gt;Third Party Libraries&lt;\/h3&gt;\n<\/code><\/pre>\n\n<p>This plugin bundles the following third-party library:<\/p>\n\n<p><strong>qrcodejs<\/strong>\n* Author: Sangmin Shim (davidshimjs)\n* License: MIT\n* Source: https:\/\/github.com\/davidshimjs\/qrcodejs\n* Files: <code>assets\/js\/qrcode.min.js<\/code>, <code>assets\/js\/qrcode.js<\/code>\n* Purpose: Renders the QR code displayed during Authenticator App setup. Used entirely client-side; makes no external network requests.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the <code>oqwall-2fa<\/code> folder to the <code>\/wp-content\/plugins\/<\/code> directory, or install the plugin through the <strong>Plugins &gt; Add New<\/strong> screen in WordPress.<\/li>\n<li>Activate the plugin through the <strong>Plugins<\/strong> screen in WordPress.<\/li>\n<li>Navigate to <strong>Loqwall 2FA &gt; Settings<\/strong> and enable Two-Factor Authentication.<\/li>\n<li>Each user can then visit their <strong>Profile<\/strong> page to set up their preferred 2FA method.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"what%202fa%20methods%20are%20supported%3F\"><h3>What 2FA methods are supported?<\/h3><\/dt>\n<dd><p>Email OTP (a 6-digit code emailed on each login) and Authenticator App (TOTP, RFC 6238), compatible with Google Authenticator, Authy, Bitwarden, and Microsoft Authenticator.<\/p><\/dd>\n<dt id=\"can%20i%20force%20administrators%20to%20always%20use%202fa%3F\"><h3>Can I force administrators to always use 2FA?<\/h3><\/dt>\n<dd><p>Yes. Enable the <strong>Force Admins<\/strong> option in <strong>Loqwall 2FA &gt; Settings<\/strong>. Administrators will be required to complete 2FA regardless of their personal preference.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20a%20user%20loses%20access%20to%20their%202fa%20method%3F\"><h3>What happens if a user loses access to their 2FA method?<\/h3><\/dt>\n<dd><p>Each user has 10 one-time backup codes generated when they first set up 2FA. These can be regenerated by the user or by an administrator from the user profile page. An administrator can also disable 2FA for the user from their profile.<\/p><\/dd>\n<dt id=\"does%20this%20plugin%20phone%20home%20or%20send%20any%20data%20externally%3F\"><h3>Does this plugin phone home or send any data externally?<\/h3><\/dt>\n<dd><p>No. The plugin makes no outbound HTTP requests. All data (logs, OTP hashes, device cookies) stays on your server.<\/p><\/dd>\n<dt id=\"is%20this%20plugin%20multisite%20compatible%3F\"><h3>Is this plugin multisite compatible?<\/h3><\/dt>\n<dd><p>Yes. The plugin works on standard single-site and multisite WordPress installations.<\/p><\/dd>\n<dt id=\"which%20browsers%20are%20supported%3F\"><h3>Which browsers are supported?<\/h3><\/dt>\n<dd><p>Any modern browser. The QR code for Authenticator App setup is rendered entirely client-side using the bundled <code>qrcode.js<\/code> library.<\/p><\/dd>\n<dt id=\"where%20can%20i%20find%20the%20source%20code%3F\"><h3>Where can I find the source code?<\/h3><\/dt>\n<dd><p>The full source code is available on the plugin's WordPress.org repository page. The unminified version of the bundled <code>qrcode.js<\/code> library is included in <code>assets\/js\/qrcode.js<\/code>.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release.<\/li>\n<li>Email OTP authentication.<\/li>\n<li>Authenticator App (TOTP) authentication.<\/li>\n<li>Backup recovery codes.<\/li>\n<li>Device trust (remember this device).<\/li>\n<li>Role-based 2FA enforcement.<\/li>\n<li>Audit log with configurable retention.<\/li>\n<li>Rate limiting on OTP verification.<\/li>\n<li>Translatable \u2014 bundled French (fr_FR) translation.<\/li>\n<\/ul>","raw_excerpt":"Lightweight Two-Factor Authentication with Email OTP and Authenticator App support. No bloat, no external services.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/is.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/307654","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/is.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/is.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/is.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=307654"}],"author":[{"embeddable":true,"href":"https:\/\/is.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/mohamedelaaouam99"}],"wp:attachment":[{"href":"https:\/\/is.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=307654"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/is.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=307654"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/is.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=307654"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/is.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=307654"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/is.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=307654"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/is.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=307654"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}