Making WordPress.org

Changeset 6737


Ignore:
Timestamp:
02/25/2018 04:46:39 AM (8 years ago)
Author:
obenland
Message:

2FA: First pass at new user edit UI.

Needs more work around changing devices, backup codes, and (possibly) application passwords.

See #77.

Location:
sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-two-factor
Files:
2 added
1 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-two-factor/wporg-two-factor.php

    r6735 r6737  
    1414        public function __construct() {
    1515                add_filter( 'two_factor_providers', [ $this, 'two_factor_providers' ] );
     16
     17                remove_action( 'edit_user_profile', [ 'Two_Factor_Core', 'user_two_factor_options' ] );
     18                remove_action( 'show_user_profile', [ 'Two_Factor_Core', 'user_two_factor_options' ] );
     19
     20                if ( ! is_admin() ) {
     21                        add_action( 'edit_user_profile', [ $this, 'user_two_factor_options' ] );
     22                        add_action( 'show_user_profile', [ $this, 'user_two_factor_options' ] );
     23                }
     24
     25                add_action( 'wp_ajax_two-factor-totp-verify-code',[ $this, 'ajax_verify_code' ] );
     26                add_action( 'wp_ajax_two-factor-disable',[ $this, 'ajax_disable' ] );
    1627        }
    1728
     
    3142                return $wporg_providers;
    3243        }
     44
     45        /**
     46         * Displays the UI to set up and remove 2FA.
     47         *
     48         * @param \WP_User $user User object.
     49         */
     50        public function user_two_factor_options( $user ) {
     51                wp_enqueue_script( 'two-factor-edit', plugins_url( 'js/profile-edit.js' , __FILE__ ), [ 'jquery' ], 1, true );
     52
     53                $key       = get_user_meta( $user->ID, Two_Factor_Totp::SECRET_META_KEY, true );
     54                $is_active = !! $key;
     55                ?>
     56
     57                <h2 class="entry-title"><?php esc_html_e( 'Two Factor Authentication', 'wporg' ); ?></h2>
     58                <?php Two_Factor_Totp::admin_notices(); ?>
     59                <fieldset id="two-factor-active" class="bbp-form two-factor" <?php if ( ! $is_active ) { echo 'style="display:none;"'; } ?>>
     60                        <legend><?php esc_html_e( 'Two Factor Authentication', 'wporg' ); ?></legend>
     61                        <div><?php echo wp_kses_post( __( '<strong>Status:</strong> Two Factor Authentication is currently <span>ACTIVE</span>.', 'wporg' ) ); ?></div>
     62                        <div><?php esc_html_e( 'While enabled, logging in to WordPress.org requires you to enter a unique passcode, generated by an app on your mobile device, in addition to your username and password.', 'wporg' ); ?></div>
     63                        <div><?php esc_html_e( 'Switching to a new device? Follow these steps to avoid losing access to your account.', 'wporg' ); ?></div>
     64                        <div><button type="cancel" class="button button-secondary alignright"><?php esc_html_e( 'Disable Two Factor Authentication', 'wporg' ); ?></button></div>
     65                </fieldset>
     66                <?php
     67                if ( empty( $key ) ) {
     68                        $key = Two_Factor_Totp::generate_key();
     69                }
     70
     71                wp_nonce_field( 'user_two_factor_totp_options', '_nonce_user_two_factor_totp_options' );
     72                ?>
     73                <fieldset id="two-factor-start" class="bbp-form two-factor" <?php if ( $is_active ) { echo 'style="display:none;"'; } ?>>
     74                        <legend><?php esc_html_e( 'Two Factor Authentication', 'wporg' ); ?></legend>
     75                        <div><?php esc_html_e( 'Two-Step Authentication adds an extra layer of security to your account. Once enabled, logging in to WordPress.org will require you to enter a unique passcode generated by an app on your mobile device, in addition to your username and password.', 'wporg' ); ?></div>
     76                        <div><button type="button" id="two-factor-start-toggle" class="button button-primary"><?php esc_html_e( 'Get Started', 'wporg' ); ?></button></div>
     77                </fieldset>
     78
     79                <fieldset id="two-factor-qr-code" class="bbp-form two-factor" style="display: none;">
     80                        <legend><?php esc_html_e( 'Two Factor Authentication', 'wporg' ); ?></legend>
     81                        <div>
     82                                <p><?php esc_html_e( 'Scan this QR code with your mobile app.', 'wporg' ); ?></p>
     83                                <p><button type="button" class="button-link"><?php esc_html_e( 'Can&#8217;t scan the code?', 'wporg' ); ?></button></p>
     84                                <img src="<?php echo esc_url( Two_Factor_Totp::get_google_qr_code( 'wordpress.org:' . $user->user_login, $key, 'wordpress.org' ) ); ?>" id="two-factor-totp-qrcode" />
     85                                <p><?php esc_html_e( 'Then enter the authentication code provided by the app:', 'wporg' ); ?></p>
     86                                <p>
     87                                        <label class="screen-reader-text" for="two-factor-totp-authcode"><?php esc_html_e( 'Authentication Code:', 'wporg' ); ?></label>
     88                                        <input type="hidden" name="two-factor-totp-key" value="<?php echo esc_attr( $key ) ?>" />
     89                                        <input type="tel" name="two-factor-totp-authcode" class="input" value="" size="20" pattern="[0-9]*" placeholder="<?php esc_attr_e( 'e.g. 123456', 'wporg' ); ?>" />
     90                                </p>
     91                                <button type="cancel" class="button button-secondary alignleft"><?php esc_html_e( 'Cancel', 'wporg' ); ?></button>
     92                                <button type="submit" class="button button-primary alignright"><?php esc_html_e( 'Enable', 'wporg' ); ?></button>
     93                        </div>
     94                </fieldset>
     95
     96                <fieldset id="two-factor-key-code" class="bbp-form two-factor" style="display: none;">
     97                        <legend><?php esc_html_e( 'Two Factor Authentication', 'wporg' ); ?></legend>
     98                        <div>
     99                                <p><?php esc_html_e( 'Enter this time code into your mobile app.', 'wporg' ); ?></p>
     100                                <p><button type="button" class="button-link"><?php esc_html_e( 'Prefer to scan the code?', 'wporg' ); ?></button></p>
     101                                <p class="key"><strong><?php echo esc_html( $key ); ?></strong></p>
     102                                <p><?php esc_html_e( 'Then enter the authentication code provided by the app:', 'wporg' ); ?></p>
     103                                <p>
     104                                        <label class="screen-reader-text" for="two-factor-totp-authcode"><?php esc_html_e( 'Authentication Code:', 'wporg' ); ?></label>
     105                                        <input type="hidden" name="two-factor-totp-key" value="<?php echo esc_attr( $key ) ?>" />
     106                                        <input type="tel" name="two-factor-totp-authcode" class="input" value="" size="20" pattern="[0-9]*" placeholder="<?php esc_attr_e( 'e.g. 123456', 'wporg' ); ?>" />
     107                                </p>
     108                                <button type="cancel" class="button button-secondary alignleft"><?php esc_html_e( 'Cancel', 'wporg' ); ?></button>
     109                                <button type="submit" class="button button-primary alignright"><?php esc_html_e( 'Enable', 'wporg' ); ?></button>
     110                        </div>
     111                </fieldset>
     112
     113                <style>
     114                        #bbpress-forums fieldset.two-factor:not(#two-factor-start) > div {
     115                                margin-left: 20%;
     116                                width: 60% !important;
     117                        }
     118                        #bbpress-forums .two-factor button.button-link {
     119                                color: #4ca6cf;
     120                                padding: 0;
     121                        }
     122                        #bbpress-forums .two-factor .key {
     123                                padding: 2rem 0;
     124                        }
     125                </style>
     126
     127                <?php
     128        }
     129
     130        /**
     131         * AJAX handler to verify a user's 2FA code.
     132         */
     133        public function ajax_verify_code() {
     134                check_ajax_referer( 'user_two_factor_totp_options', '_nonce_user_two_factor_totp_options' );
     135
     136                $user_id = absint( $_POST['user_id'] );
     137                if ( ! current_user_can( 'edit_user', $user_id ) ) {
     138                        wp_send_json_error( __( 'You do not have permission to edit this user.' ) );
     139                }
     140
     141                if ( empty( $_POST['authcode'] ) ) {
     142                        wp_send_json_error( __( 'Please enter a valid authorization code.' ) );
     143                }
     144
     145                if ( Two_Factor_Totp::is_valid_authcode( $_POST['key'], $_POST['authcode'] ) ) {
     146                        if ( ! update_user_meta( $user_id, Two_Factor_Totp::SECRET_META_KEY, $_POST['key'] ) ) {
     147                                wp_send_json_error( __( 'Unable to save Two Factor Authentication code. Please try again.', 'wporg' ) );
     148                        }
     149
     150                        wp_send_json_success();
     151                }
     152
     153                wp_send_json_error( __( 'The authentication code you entered was not valid. Please try again.', 'wporg' ) );
     154        }
     155
     156        /**
     157         * AJAX handler to disable 2FA.
     158         */
     159        public function ajax_disable() {
     160                check_ajax_referer( 'user_two_factor_totp_options', '_nonce_user_two_factor_totp_options' );
     161
     162                $user_id = absint( $_POST['user_id'] );
     163                if ( ! current_user_can( 'edit_user', $user_id ) ) {
     164                        wp_send_json_error( __( 'You do not have permission to edit this user.' ) );
     165                };
     166
     167                if ( ! delete_user_meta( $user_id, Two_Factor_Totp::SECRET_META_KEY ) ) {
     168                        wp_send_json_error( __( 'Unable to remove Two Factor Authentication code. Please try again.', 'wporg' ) );
     169                }
     170
     171                if ( ! update_user_meta( $user_id, Two_Factor_Core::ENABLED_PROVIDERS_USER_META_KEY, [] ) ) {
     172                        wp_send_json_error( __( 'Unable to remove Two Factor Authentication code. Please try again.', 'wporg' ) );
     173                }
     174
     175                wp_send_json_success( __( 'Two Factor authentication disabled. Your account is now less secure.', 'wporg' ) );
     176        }
    33177}
    34178new WPORG_Two_Factor();
Note: See TracChangeset for help on using the changeset viewer.