-
Notifications
You must be signed in to change notification settings - Fork 555
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(mfa): add MFA code input screen for /ro endpoint
We will show MFA screen when mfa is required for an user and the customer is using the /ro endpoint instead of popup or redirect mode (push notifications not allowed).
- Loading branch information
Showing
15 changed files
with
516 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import React from 'react'; | ||
import MFACodePane from '../../field/mfa-code/mfa_code_pane'; | ||
|
||
export default class MFAPane extends React.Component { | ||
|
||
render() { | ||
const { | ||
mfaInputPlaceholder, | ||
i18n, | ||
instructions, | ||
lock, | ||
title | ||
} = this.props; | ||
|
||
const headerText = instructions || null; | ||
const header = headerText && <p>{headerText}</p>; | ||
|
||
const pane = (<MFACodePane | ||
i18n={i18n} | ||
lock={lock} | ||
placeholder={mfaInputPlaceholder} | ||
/>); | ||
|
||
const titleElement = title && <h2>{ title }</h2>; | ||
|
||
return (<div>{titleElement}{header}{pane}</div>); | ||
} | ||
|
||
} | ||
|
||
MFAPane.propTypes = { | ||
mfaInputPlaceholder: React.PropTypes.string.isRequired, | ||
title: React.PropTypes.string.isRequired, | ||
i18n: React.PropTypes.object.isRequired, | ||
instructions: React.PropTypes.any, | ||
lock: React.PropTypes.object.isRequired | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import React from 'react'; | ||
import Screen from '../../core/screen'; | ||
import MFAPane from '../../connection/database/mfa_pane'; | ||
import * as i18n from '../../i18n'; | ||
import { cancelMFALogin, logIn } from '../../connection/database/actions'; | ||
import { hasScreen } from '../../connection/database/index'; | ||
import { renderSignedInConfirmation } from '../../core/signed_in_confirmation'; | ||
|
||
const Component = ({i18n, model}) => { | ||
|
||
return <MFAPane | ||
mfaInputPlaceholder={i18n.str("mfaInputPlaceholder")} | ||
i18n={i18n} | ||
instructions={i18n.str("mfaLoginInstructions")} | ||
lock={model} | ||
title={i18n.str("mfaLoginTitle")} | ||
/>; | ||
}; | ||
|
||
export default class MFALoginScreen extends Screen { | ||
|
||
constructor() { | ||
super("mfa.mfaCode"); | ||
} | ||
|
||
renderAuxiliaryPane(lock) { | ||
return renderSignedInConfirmation(lock); | ||
} | ||
|
||
submitButtonLabel(m) { | ||
return i18n.str(m, ["mfaSubmitLabel"]); | ||
} | ||
|
||
submitHandler(m) { | ||
return (id) => logIn(id, true); | ||
} | ||
|
||
render() { | ||
return Component; | ||
} | ||
|
||
backHandler(m) { | ||
return hasScreen(m, "login") ? cancelMFALogin : undefined; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import React from 'react'; | ||
import MFACodeInput from '../../ui/input/mfa_code_input'; | ||
import * as c from '../index'; | ||
import { swap, updateEntity } from '../../store/index'; | ||
import * as l from '../../core/index'; | ||
import { setMFACode, getMFACodeValidation } from '../mfa_code'; | ||
|
||
export default class MFACodePane extends React.Component { | ||
|
||
handleChange(e) { | ||
const { lock } = this.props; | ||
swap(updateEntity, "lock", l.id(lock), setMFACode, e.target.value); | ||
} | ||
|
||
render() { | ||
const { i18n, lock, placeholder } = this.props; | ||
|
||
return ( | ||
<MFACodeInput | ||
value={c.getFieldValue(lock, "mfa_code")} | ||
invalidHint={i18n.str("mfaCodeErrorHint", getMFACodeValidation().length)} | ||
isValid={!c.isFieldVisiblyInvalid(lock, "mfa_code")} | ||
onChange={::this.handleChange} | ||
placeholder={placeholder} | ||
disabled={l.submitting(lock)} | ||
/> | ||
); | ||
} | ||
|
||
} | ||
|
||
MFACodePane.propTypes = { | ||
i18n: React.PropTypes.object.isRequired, | ||
lock: React.PropTypes.object.isRequired, | ||
onChange: React.PropTypes.func, | ||
placeholder: React.PropTypes.string.isRequired | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { setField } from './index'; | ||
import { validateEmail } from './email'; | ||
import { databaseConnection } from '../connection/database'; | ||
import trim from 'trim'; | ||
|
||
|
||
const DEFAULT_VALIDATION = { mfa_code: { length: 6 } }; | ||
const regExp = /^[0-9]+$/; | ||
|
||
function validateMFACode(str, settings = DEFAULT_VALIDATION.mfa_code) { | ||
const value = trim(str); | ||
|
||
// check min value matched | ||
if (value.length < settings.length) { | ||
return false; | ||
} | ||
|
||
// check max value matched | ||
if (value.length > settings.length) { | ||
return false; | ||
} | ||
|
||
// check allowed characters matched | ||
const result = regExp.exec(value); | ||
return result && result[0]; | ||
} | ||
|
||
export function setMFACode(m, str) { | ||
return setField(m, "mfa_code", str, validateMFACode); | ||
} | ||
|
||
export function getMFACodeValidation(m) { | ||
return DEFAULT_VALIDATION.mfa_code; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.