diff --git a/src/pages/api/auth/login.ts b/src/pages/api/auth/login.ts index 6a6262f4f..affdee1e2 100644 --- a/src/pages/api/auth/login.ts +++ b/src/pages/api/auth/login.ts @@ -15,7 +15,13 @@ const log = logger.child({}, { msgPrefix: '[api/login] ' }); export interface ILoginResponse { success?: boolean; - error?: 'invalid-credentials' | 'login-failed' | 'failed-userdata-request' | 'invalid-token' | 'method-not-allowed'; + error?: + | 'invalid-credentials' + | 'login-failed' + | 'failed-userdata-request' + | 'invalid-token' + | 'method-not-allowed' + | 'must-reset-credentials'; } export default withIronSessionApiRoute(login, sessionConfig); @@ -100,10 +106,16 @@ export const handleAuthentication = async ( return res.status(200).json({ success: false, error: 'failed-userdata-request' }); } } - log.debug('Login failed', { data }); + log.debug({ data }, 'Login failed'); return res.status(401).json({ success: false, error: 'login-failed' }); - } catch (error) { - log.trace('Login failed', { error }); + } catch (err) { + log.error({ err }, 'Login failed'); + + // if the login failed due to a password reset requirement, return a specific error + if (axios.isAxiosError(err) && err.response && err.response.status === HttpStatusCode.UnprocessableEntity) { + return res.status(401).json({ success: false, error: 'must-reset-credentials' }); + } + return res.status(401).json({ success: false, error: 'login-failed' }); } }; diff --git a/src/pages/user/account/login.tsx b/src/pages/user/account/login.tsx index 7236a22c8..bf8891332 100644 --- a/src/pages/user/account/login.tsx +++ b/src/pages/user/account/login.tsx @@ -34,6 +34,7 @@ const Login: NextPage = () => { ['login'], async (params) => { const { data } = await axios.post('/api/auth/login', params); + if (data?.error) { throw new Error(data.error); } @@ -69,7 +70,7 @@ const Login: NextPage = () => { if (isError) { focus(); } - }, [isError]); + }, [isError, focus]); return ( <> @@ -143,6 +144,14 @@ const LoginErrorMessage = (props: { error: AxiosError | Error }) case 'failed-userdata-request': case 'invalid-token': return ; + case 'must-reset-credentials': + return ( + + ); default: return null; }