Skip to content

Commit

Permalink
Switch to using an Iframe for the revalidation.
Browse files Browse the repository at this point in the history
  • Loading branch information
dd32 committed May 8, 2023
1 parent 3d77df1 commit c9d7003
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 15 deletions.
10 changes: 4 additions & 6 deletions settings/rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,11 @@ function register_user_fields(): void {
'2fa_revalidation',
[
'get_callback' => function( $user ) {
$revalidate_url = '';
$can_edit = Two_Factor_Core::current_user_can_update_two_factor_options();
if ( ! $can_edit ) {
$revalidate_url = Two_Factor_Core::get_user_two_factor_revalidate_url();
}
$revalidate_url = Two_Factor_Core::get_user_two_factor_revalidate_url( true );
$expiry = apply_filters( 'two_factor_revalidate_time', 10 * MINUTE_IN_SECONDS, $user->ID, '' );
$expires_at = Two_Factor_Core::is_current_user_session_two_factor() + $expiry;

return compact( 'can_edit', 'revalidate_url' );
return compact( 'revalidate_url', 'expires_at' );
},
'schema' => [
'type' => 'array',
Expand Down
37 changes: 37 additions & 0 deletions settings/settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ function replace_core_ui_with_custom() : void {
remove_action( 'edit_user_profile_update', array( 'Two_Factor_Core', 'user_two_factor_options_update' ) );

add_action( 'bbp_user_edit_account', __NAMESPACE__ . '\render_custom_ui' );

// Add some customizations to the revalidate_2fa page for when it's displayed in an iframe.
add_action( 'login_footer', __NAMESPACE__ . '\login_footer_revalidate_customizations' );
}

/**
Expand Down Expand Up @@ -63,3 +66,37 @@ function render_custom_ui() : void {

echo do_blocks( "<!-- wp:wporg-two-factor/settings $json_attrs /-->" );
}

function login_footer_revalidate_customizations() {
// When the revalidate_2fa page is displayed in an interim login on not-login, add some style and JS handlers.
if (
'login.wordpress.org' === $_SERVER['HTTP_HOST'] ||
empty( $_REQUEST['interim-login'] ) ||
'revalidate_2fa' !== ( $_REQUEST['action'] ?? '' )
) {
return;
}

?>
<style>
body.login-action-revalidate_2fa #login h1,
body.login-action-revalidate_2fa #backtoblog {
display: none;
}
</style>
<script>
(function() {
const loginFormExists = !! document.querySelector( '#loginform' );
const loginFormMessage = document.querySelector( '#login .message' )?.textContent || '';

// If the login no longer exists, let the parent know.
if ( ! loginFormExists ) {
window.parent.postMessage( { type: 'reValidationComplete', message: loginFormMessage }, '*' );
}
})();
</script>
<?php
}

// To test, revalidate every 30seconds.
// add_filter( 'two_factor_revalidate_time', function() { return 30; } );
55 changes: 47 additions & 8 deletions settings/src/components/revalidate-modal.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
/**
* WordPress dependencies
*/
import { useContext } from '@wordpress/element';
import { useContext, useEffect, useRef, useState } from '@wordpress/element';
import { GlobalContext } from '../script';
import { Button, Modal, __experimentalHStack as HStack } from '@wordpress/components';
import { useMergeRefs, useFocusableIframe } from '@wordpress/compose';
import { refreshRecord } from '../utilities'

export default function RevalidateModal() {
export default function RevalidateModal( { screen } ) {
const { userRecord, clickScreenLink } = useContext( GlobalContext );
const [ showIframe, setIframe ] = useState( false );

const goBack = ( event ) => clickScreenLink( event, 'account-status' );
const goRevalidate = () => {
var url = new URL( userRecord.record[ '2fa_revalidation' ].revalidate_url );
url.searchParams.set( 'redirect_to', encodeURI( window.location.href ) );
const showRevalidate = () => setIframe( true );

window.location = url.href;
};
if ( showIframe ) {
return (
<Modal title="Confirm your Two Factor" onRequestClose={ goBack }>
<RevalidateIframe screen={ screen } />
</Modal>
);
}

return (
<Modal title="Confirm your Two Factor" onRequestClose={ goBack }>
Expand All @@ -25,10 +31,43 @@ export default function RevalidateModal() {
<Button variant="secondary" onClick={ goBack }>
Cancel
</Button>
<Button variant="primary" onClick={ goRevalidate }>
<Button variant="primary" onClick={ showRevalidate }>
Continue
</Button>
</HStack>
</Modal>
);
}

function RevalidateIframe( { screen } ) {
const { setGlobalNotice, setScreen, userRecord } = useContext( GlobalContext );
const ref = useRef();

useEffect( () => {
function maybeRefreshUser( { event, data: { type, message } = {} } ) {
if ( type != 'reValidationComplete' ) {
return;
}

refreshRecord( userRecord );
setGlobalNotice( message || 'Two Factor confirmed' );
setScreen( screen );
}

window.addEventListener( 'message', maybeRefreshUser );
return () => {
window.removeEventListener( 'message', maybeRefreshUser );
};
}, [] );

return (
<>
<iframe
ref={ useMergeRefs( [ ref, useFocusableIframe() ] ) }
src={ userRecord.record[ '2fa_revalidation' ].revalidate_url }
width="400px"
height="400px"
/>
</>
);
}
2 changes: 1 addition & 1 deletion settings/src/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ function Main( { userId } ) {
twoFactorRequiredScreens.includes( screen ) &&
userRecord.record[ '2fa_available_providers' ] &&
userRecord.record[ '2fa_revalidation' ] &&
! userRecord.record[ '2fa_revalidation' ].can_edit
userRecord.record[ '2fa_revalidation' ].expires_at <= ( (new Date()).getTime()/1000 )
) {
screenContent = (
<RevalidateModal />
Expand Down

0 comments on commit c9d7003

Please sign in to comment.