Tweak MFA login flow (#16254)

* Tweak MFA login flow

* Fix typo
This commit is contained in:
Jason Hu 2018-08-29 01:16:54 -07:00 committed by Paulus Schoutsen
parent 9238261e17
commit f9b1fb5906
5 changed files with 23 additions and 23 deletions

View file

@ -137,8 +137,9 @@ class TotpAuthModule(MultiFactorAuthModule):
await self._async_load()
# user_input has been validate in caller
# set INPUT_FIELD_CODE as vol.Required is not user friendly
return await self.hass.async_add_executor_job(
self._validate_2fa, user_id, user_input[INPUT_FIELD_CODE])
self._validate_2fa, user_id, user_input.get(INPUT_FIELD_CODE, ''))
def _validate_2fa(self, user_id: str, code: str) -> bool:
"""Validate two factor authentication code."""

View file

@ -224,19 +224,27 @@ class LoginFlow(data_entry_flow.FlowHandler):
if user_input is not None:
expires = self.created_at + SESSION_EXPIRATION
if dt_util.utcnow() > expires:
errors['base'] = 'login_expired'
else:
result = await auth_module.async_validation(
self.user.id, user_input) # type: ignore
if not result:
errors['base'] = 'invalid_auth'
return self.async_abort(
reason='login_expired'
)
result = await auth_module.async_validation(
self.user.id, user_input) # type: ignore
if not result:
errors['base'] = 'invalid_code'
if not errors:
return await self.async_finish(self.user)
description_placeholders = {
'mfa_module_name': auth_module.name,
'mfa_module_id': auth_module.id
} # type: Dict[str, str]
return self.async_show_form(
step_id='mfa',
data_schema=auth_module.input_schema,
description_placeholders=description_placeholders,
errors=errors,
)

View file

@ -119,7 +119,7 @@ async def test_login(hass):
result = await hass.auth.login_flow.async_configure(
result['flow_id'], {'pin': 'invalid-code'})
assert result['type'] == data_entry_flow.RESULT_TYPE_FORM
assert result['errors']['base'] == 'invalid_auth'
assert result['errors']['base'] == 'invalid_code'
result = await hass.auth.login_flow.async_configure(
result['flow_id'], {'pin': '123456'})

View file

@ -121,7 +121,7 @@ async def test_login_flow_validates_mfa(hass):
result['flow_id'], {'code': 'invalid-code'})
assert result['type'] == data_entry_flow.RESULT_TYPE_FORM
assert result['step_id'] == 'mfa'
assert result['errors']['base'] == 'invalid_auth'
assert result['errors']['base'] == 'invalid_code'
with patch('pyotp.TOTP.verify', return_value=True):
result = await hass.auth.login_flow.async_configure(

View file

@ -428,10 +428,10 @@ async def test_login_with_auth_module(mock_hass):
'pin': 'invalid-pin',
})
# Invalid auth error
# Invalid code error
assert step['type'] == data_entry_flow.RESULT_TYPE_FORM
assert step['step_id'] == 'mfa'
assert step['errors'] == {'base': 'invalid_auth'}
assert step['errors'] == {'base': 'invalid_code'}
step = await manager.login_flow.async_configure(step['flow_id'], {
'pin': 'test-pin',
@ -571,18 +571,9 @@ async def test_auth_module_expired_session(mock_hass):
step = await manager.login_flow.async_configure(step['flow_id'], {
'pin': 'test-pin',
})
# Invalid auth due session timeout
assert step['type'] == data_entry_flow.RESULT_TYPE_FORM
assert step['step_id'] == 'mfa'
assert step['errors']['base'] == 'login_expired'
# The second try will fail as well
step = await manager.login_flow.async_configure(step['flow_id'], {
'pin': 'test-pin',
})
assert step['type'] == data_entry_flow.RESULT_TYPE_FORM
assert step['step_id'] == 'mfa'
assert step['errors']['base'] == 'login_expired'
# login flow abort due session timeout
assert step['type'] == data_entry_flow.RESULT_TYPE_ABORT
assert step['reason'] == 'login_expired'
async def test_enable_mfa_for_user(hass, hass_storage):