Skip to content

Make the Two Factor settings portable to other settings screens #335

Description

@kasparsd

Currently the two-factor setup for each user is tied to the standard user profile page. This makes it impossible to configure the two-factor authentication for sites that don't allow users to access the standard profile page.

Activity

  1. georgestephanis commented on Mar 24, 2020

    @georgestephanis
    Collaborator

    My main concern here would be portability of styles -- it may not render correctly.

    What other plugins create user screens on the front-end, and do they have any consistent hook usage that can be used to add extra fields? Or would it be better if we provided a function that they could use to render our stuff?

    Or sort out a common action?

  2. gytisrepecka commented on May 7, 2020

    @gytisrepecka

    Ideal situation would be to have a shortcode which would display two-factor settings.

    I recently attempted to include two-factor settings into WooCommerce's my-account/edit-account page. I could enable/disable two-factor methods, but AJAX didn't work (recovery codes, showing QR code for TOTP, etc.) - I probably missed some JavaScripts that are available in wp-admin.

    Here are modifications I've done:

    Edited class-two-factor-core.php: following WordPress hooks (edit_user_profile and edit_user_profile_update) I have used corresponding functions in WooCommerce hooks:

    add_action( 'woocommerce_edit_account_form', array( __CLASS__, 'user_two_factor_options' ) );
    add_action( 'woocommerce_update_customer', array( __CLASS__, 'user_two_factor_options_update' ) );
    

    Then, to make sure after showing two-factor settings page doesn't die rendering, also added following to providers/class.two-factor-fido-u2f-admin.php:

    In function add_hooks changed:

    add_action( 'show_user_security_settings', array( __CLASS__, 'show_user_profile' ) );
    

    To:

    add_action( 'show_user_security_settings', array( __CLASS__, 'show_user_profile', 'woocommerce_edit_account_form' ) );
    

    Though in frontend settings does not display e-mail address, nor QR code, so I believe there is something still missing...

    I am also unsure if enqueue_assets function should be hooked into frontend - when I tried nothing changed anyway (didn't get AJAX working):

    add_action( 'wp_enqueue_scripts',       array( __CLASS__, 'enqueue_assets' ) );
    

    Anyone care to join into solving this?

  3. luisjavierbautista commented on Sep 18, 2020

    @luisjavierbautista

    Hi there,

    There is any update about this?
    I'm trying to include two-factor settings into UltimateMember profile pages, but does not display e-mail address, nor QR code

  4. gytisrepecka commented on Oct 19, 2020

    @gytisrepecka

    Currently the two-factor setup for each user is tied to the standard user profile page. This makes it impossible to configure the two-factor authentication for sites that don't allow users to access the standard profile page.

    WooCommerce redirect customers to frontend my-account page if one tries to visit wp-admin/profile.php or any other page under wp-admin.

    So if we want to use two-factor with WooCommerce, we need frontent shortcodes.

  5. r-a-y commented on Oct 29, 2020

    @r-a-y
    Contributor

    When I integrated the two-factor plugin onto the frontend for BuddyPress, these are the following issues I encountered:

    1. Save routines do not return useful information

    See #244.

    2FA core uses the user_two_factor_options_update() method to save the enabled and primary providers:

    public static function user_two_factor_options_update( $user_id ) {

    Unfortunately, this method doesn't return what type of info is being saved. So to determine if a new 2FA method or primary provider was saved, you currently have to duplicate this logic.

    Likewise, the TOTP 2FA routine saves error notices into user meta:

    public function user_two_factor_options_update( $user_id ) {

    So you have to manually retrieve the notices to display them yourself.

    2. Reliance on admin functions

    convert_to_screen() and get_column_headers() are the bare minimum functions needed to be used on the frontend. These are admin-only functions., so to use on the frontend, these functions need to be either included or plugged. I chose to redeclare the functions to plug them.

    3, User settings URL needs to be filtered

    The Two_Factor_Core::get_user_settings_page_url() method returns the admin user-edit.php URL:

    protected static function get_user_settings_page_url( $user_id ) {
    $page = 'user-edit.php';
    if ( defined( 'IS_PROFILE_PAGE' ) && IS_PROFILE_PAGE ) {
    $page = 'profile.php';
    }
    return add_query_arg(
    array(
    'user_id' => intval( $user_id ),
    ),
    self_admin_url( $page )
    );
    }

    This won't work for the frontend, especially with TOTP saving. Workaround is to use the 'self_admin_url' filter to bypass this.

    4. U2F fido-u2f-admin JS looks for the "Users > Your Profile" submit button

    See:

    // See: http://stackoverflow.com/questions/833032/submit-is-not-a-function-error-in-javascript
    $( '<form>' )[0].submit.call( $( '#your-profile' )[0] );

    To workaround this, I had to register my own fido-u2f-admin script just to replace this submit form call.

    5. 2FA <table> uses a nested table

    The user_two_factor_options() method uses a nested table for display:

    <table class="form-table" id="two-factor-options">
    <tr>
    <th>
    <?php esc_html_e( 'Two-Factor Options', 'two-factor' ); ?>
    </th>
    <td>
    <table class="two-factor-methods-table">

    This is problematic for use on the frontend since themes can style tables in a myriad of ways.

    You can workaround this with CSS, but it's annoying to have to resort to CSS hacks to remove the first table from being displayed.


    Other than that, calling on the options table, enqueued JS hooks and validation methods should work. You just have to write some code to workaround these issues. I'll post my code for my BuddyPress 2FA plugin later once I've cleaned things up. Update - BP Two Factor is available here: https://github.com/r-a-y/bp-two-factor

    Also see #261 where some of this is being worked on.

  6. wuniversales commented on Apr 10, 2021

    @wuniversales

    Why not add an option in the plugin configuration to add custom style to the 2fa field?

  7. solaceten commented on Oct 25, 2021

    @solaceten

    Hi there what's the status with compatibility with Woocommerce ? Possible ?

    PS - I would be happy to pay for this plugin. Maybe make a "pro" version and sell it @ $15 similar to the one on codecanyon (I would rather support this plugin).

    However, it looks like it's just not yet there for my needs. I will keep an eye on dev.

  8. added
    CompatibilityCompatibility with other plugins, Core, back-compat
    on Oct 20, 2022
  9. iandunn commented on Mar 2, 2023

    @iandunn
    Member

    #504 laid some groundwork for this

  10. added this to the Future Release milestone on Sep 17, 2024
  11. opicron commented on Jun 29, 2025

    @opicron

    Proof of concept here: #704

  12. masteradhoc commented on Apr 25, 2026

    @masteradhoc
    Collaborator

    Another request from @AliferSouza
    Additionally, it would be valuable to include a Gutenberg block that enables authentication directly from the frontend. This would allow anyone to create their own custom login area, whether integrated with WooCommerce or used on a standalone authentication page.

    This approach would offer greater flexibility for developers and administrators, enabling the creation of more intuitive login interfaces aligned with the project’s visual identity, without relying solely on the default WordPress login screens.

    It is also possible to add an option/configuration to synchronize access keys between multiple WordPress instances, allowing for an experience similar to SSO (Single Sign-On).

    see #779 (comment)

  13. chetanupare commented on Jun 30, 2026

    @chetanupare

    I’ve been thinking about this, and I totally understood that rewriting all the existing save logic just for frontend compatibility is way too risky right now. We shouldn't break how things currently work on profile.php.

    What if we took a lightweight "adapter" approach instead?

    We could create a simple [two_factor_settings] shortcode (or Gutenberg block) that reuses the exact same UI rendering function we already have. But instead of relying on profile.php, the shortcode wraps the UI in a form that submits to admin-post.php (e.g., action=two_factor_frontend_save).

    That handler would just pass the data straight into our existing legacy save functions and then redirect the user right back to the frontend page they were on.

    This would give WooCommerce/BuddyPress developers a fully portable frontend shortcode to use immediately, with literally zero breaking changes to how the backend currently operates. Thoughts on this?

  14. 0n3m0r3 commented on Sep 8, 2026

    @0n3m0r3

    @solaceten one-off frontend shortcode. profile.php is still the only screen that both renders and saves two-factor options; WooCommerce / Ultimate Member send customers away from it.

    [two_factor_settings] wraps Two_Factor_Core::user_two_factor_options() in a form that POSTs to admin-post.php and saves with user_two_factor_options_update() for the current user only. Same nonce as profile.php (_nonce_user_two_factor_options). javascript: / off-site return URLs are dropped.

    This is the standalone, integration-agnostic plugin @kasparsd asked for on #704. It is not a fork of https://github.com/opicron/two-factor-woo (Woo hooks). Put the shortcode on any logged-in page.

    https://gist.github.com/0n3m0r3/13e18094a5f695d1b7df949e9b5c36dc

    php test_frontend.php all passed (PHP 8.4). Copy frontend.php + two-factor-frontend.php into wp-content/mu-plugins/ (root).

    You offered to pay for portable settings. One-off 20 USDC on Base if the shortcode is the slice: 0x89324980acaf83Bc065f1cE7A613BF43f9E5692d. PayPal/bank: say so on this issue (no secrets). Nothing else owed. No Woo login-form rewrite, no Gutenberg block, no Ultimate Member skin unless newly paid. No SLA. No warranty.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    CompatibilityCompatibility with other plugins, Core, back-compat

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions