Skip to content

Commit

Permalink
Rough in TOTP and Backup Code screens
Browse files Browse the repository at this point in the history
These are still WIPs, but having some structure makes it easier to collaborate.

See #30
  • Loading branch information
iandunn committed Jan 6, 2023
1 parent 49c88c7 commit db58453
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 106 deletions.
29 changes: 29 additions & 0 deletions settings/rest-api.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

namespace WordPressdotorg\Two_Factor;
use Two_Factor_Core, Two_Factor_Backup_Codes;

defined( 'WPINC' ) || die();

Expand Down Expand Up @@ -102,6 +103,34 @@ function register_user_fields(): void {
]
]
);

register_rest_field(
'user',
'2fa_enabled_providers',
[
'get_callback' => function( $user ) {
return Two_Factor_Core::get_enabled_providers_for_user( get_userdata( $user['id'] ) );
},
'schema' => [
'type' => 'array',
'context' => [ 'edit' ],
]
]
);

register_rest_field(
'user',
'2fa_backup_codes_remaining',
[
'get_callback' => function( $user ) {
return Two_Factor_Backup_Codes::codes_remaining_for_user( get_userdata( $user['id'] ) );
},
'schema' => [
'type' => 'int',
'context' => [ 'edit' ],
]
]
);
}

/**
Expand Down
21 changes: 13 additions & 8 deletions settings/src/components/account-status.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import { Icon, cancelCircleFilled, check, chevronRight, warning } from '@wordpre
* Render the Account Status.
*/
export default function AccountStatus( { clickScreenLink, userRecord } ) {
const { record } = userRecord;
const emailStatus = record.pending_email ? 'pending' : 'ok';
const totpStatus = 'disabled';
// todo make dynamic
const { record } = userRecord;
const emailStatus = record.pending_email ? 'pending' : 'ok';
const totpStatus = Object.values( record['2fa_enabled_providers'] ).includes( 'Two_Factor_Totp' ) ? 'enabled' : 'disabled';
const backupCodesStatus = Object.values( record['2fa_enabled_providers'] ).includes( 'Two_Factor_Backup_Codes' ) &&
record['2fa_backup_codes_remaining'] > 0 ? 'enabled' : 'disabled';

return (
<>
Expand All @@ -36,18 +37,22 @@ export default function AccountStatus( { clickScreenLink, userRecord } ) {
/>

<SettingStatusCard
screen="two-factor-status"
screen="totp"
status={ totpStatus }
headerText="Two Factor Authentication"
bodyText="You have two-factor authentication enabled using an app."
bodyText={ 'enabled' === totpStatus ?
/* @todo update this when hardware tokens become an additional option. */
'You have two-factor authentication enabled using an app.' :
'You do not have two-factor authentication enabled.'
}
clickScreenLink={ clickScreenLink }
/>

<SettingStatusCard
screen="backup-codes"
status={ emailStatus }
status={ backupCodesStatus }
headerText="Two-Factor Backup Codes"
bodyText="You have verified your backup codes for two-factor authentication."
bodyText={ `You have ${ 'enabled' === backupCodesStatus ? '' : 'not' } verified your backup codes for two-factor authentication.` }
clickScreenLink={ clickScreenLink }
/>
</>
Expand Down
76 changes: 76 additions & 0 deletions settings/src/components/backup-codes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//
export default function TOTP( { userRecord } ) {
const enabledProviders = Object.values( userRecord.record[ '2fa_enabled_providers' ] );
const backupCodesStatus = enabledProviders.includes( 'Two_Factor_Backup_Codes' ) &&
record[ '2fa_backup_codes_remaining' ] > 0 ? 'enabled' : 'disabled';

return (
<>
{ 'disabled' === backupCodesStatus && <Setup /> }
{ 'enabled' === backupCodesStatus && <Manage /> }
</>
);
}

//
function Setup() {
return (
<>
<p>
Backup codes let you access your account if your phone is lost, stolen, or if you run it through the washing machine and the bag of rice trick doesn't work.
We ask that you print this list of ten unique, one-time-use backup codes and keep the list in a safe place.
</p>

<p>
Backup codes let you access your account if your phone is lost or stolen, or even just accidentally run through the washing machine!

</p>

<code>
backup codes
</code>

<p>
red exclamation mark icon
Without access to the app, your phone, or a backup code, you will lose access to your account.


check box
I have printed or saved these codes

all finished primary button

copy icon button
print icon button
download icon button
</p>
</>
);
}

//
function Manage() {
//make this DRY with the setup screen - modularize Setup so that this can call indivitual components

return (
<>
Generate new backup codes button - on click populates area below with new codes

<p>
Backup codes let you access your account if your phone is lost or stolen, or even just accidentally run through the washing machine!
</p>

<p>
red exclamation mark icon
Backup codes have not been verified.
</p>

<p>
Type a Backup Code to Verify
input field with placeholder "e.g. 12345678"
</p>

Verify button
</>
);
}
75 changes: 75 additions & 0 deletions settings/src/components/totp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* WordPress dependencies
*/
import { Button } from '@wordpress/components';

//
export default function TOTP( { userRecord } ) {
const enabledProviders = Object.values( userRecord.record[ '2fa_enabled_providers' ] );
const totpStatus = enabledProviders.includes( 'Two_Factor_Totp' ) ? 'enabled' : 'disabled';

return (
<>
{ 'disabled' === totpStatus && <Setup /> }
{ 'enabled' === totpStatus && <Manage /> }
</>
);
}

//
function Setup() {
// todo after setting this up is done, check if they have backup codes, and if not, redirect them to that screen

return (
<>
<p>
Scan this QR code with the authenticator app on your mobile device.

<a href="">
Can't scan the code?
</a>
</p>

<p>
qr image
</p>

<p>
Then enter the six digit code provided by the app:
</p>

<p>
input field w/ placeholder text
</p>

<p>
Not sure what this screen means? You may need to download Authy or Google Authenticator for your phone
{/* add links to those. maybe pick different ones> */ }
</p>

<p>
<Button isPrimary>
Enable
</Button>

<Button isSecondary>
Cancel
</Button>
</p>
</>
);
}

//
function Manage() {
return (
<>
You've enabled two-step authentication on your account — smart move! When you log in to WordPress.com, you'll need to enter your username and password, as well as a unique passcode generated by an app on your mobile device.

Switching to a new device? Follow these steps to avoid losing access to your account.
https://wordpress.com/support/security/two-step-authentication/#moving-to-a-new-device

Status: Two-step authentication is currently on.
</>
);
}
102 changes: 4 additions & 98 deletions settings/src/script.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { StrictMode, useCallback, useState } from '@wordpress/element';
import { Icon, arrowLeft } from '@wordpress/icons';
import { Spinner } from '@wordpress/components';
Expand All @@ -14,6 +13,8 @@ import { store as coreDataStore, useEntityRecord } from '@wordpress/core-data';
import AccountStatus from './components/account-status';
import Password from './components/password';
import EmailAddress from './components/email-address';
import TOTP from './components/totp';
import BackupCodes from './components/backup-codes';

window.addEventListener( 'DOMContentLoaded', renderSettings );

Expand Down Expand Up @@ -48,9 +49,8 @@ function Main( { userId } ) {
'account-status': AccountStatus,
'email': EmailAddress,
'password': Password,
'two-factor-status': TwoFactorStatus,
'setup-totp': SetupTOTP,
'backup-codes': GenerateBackupCodes,
'totp': TOTP,
'backup-codes': BackupCodes,
};

let currentUrl = new URL( document.location.href );
Expand Down Expand Up @@ -121,97 +121,3 @@ function getUserRecord( userId ) {

return userRecord;
}

/**
* Render the user's 2FA status.
*/
function TwoFactorStatus() {
const totpEnabled = false;
// todo use core user meta data store? or create an upstream API endpoint for this?

//{ totpEnabled && <TwoFactorStatus /> }
//{ ! totpEnabled && <SetupTOTP /> }

return(
<>
<p>
"You've enabled TOTP..." +
"button to disable"
</p>

<p>
"backup codes let you..."
type a backup code to verify
</p>
</>
);
}

/**
* Render the view for setting up TOTP.
*/
function SetupTOTP() {
return (
<div>
<p>
Two-factor auth adds an extra layer of security... once enabled...
</p>

<p>
{ __( 'Scan this QR code with the authenticator app on your mobile device.', 'wporg' ) }

<a href="">
{ __( "Can't scan the code?", 'wporg' ) }
</a>
</p>

<p>
qr image
</p>

<p>
{ __( 'Then enter the six digit code provided by the app:', 'wporg' ) }
</p>

<p>
input field w/ placeholder text
</p>

<p>
{ __( 'Not sure what this screen means? You may need to download Authy or Google Authenticator for your phone', 'wporg' ) }
{/* add links to those. maybe pick different ones> */}
</p>

<p>
enable button
cancel button
</p>
</div>
);
}

/**
* Render the view for generating backup codes.
*/
function GenerateBackupCodes() {
return (
<div>
backup codes let you...

we ask that you...

list of codes in a pre/code block

danger icon
without access...

checkbox
i have printed...

all finished button
copy button
print button
download button
</div>
);
}

0 comments on commit db58453

Please sign in to comment.