Estoy tratando de incorporar 2FA en el flujo de inicio de sesión del administrador de reacción.
El problema es que la forma estándar de validar un inicio de sesión es usar useLogin.
const login = useLogin(); try { await login({username: "joeblack", password: "mybadpassword"}, "/redirectlocation"); } catch (err) { // display an error notice or whatever }Básicamente, la función de inicio de sesión de useLogin completará el proceso de inicio de sesión e iniciará la sesión del usuario o mostrará un error.
Para cosas como 2FA, se requiere una nueva contraseña, etc., debe haber un paso intermedio en el que el usuario aún no esté autenticado para ver los recursos, pero no esté en un estado de error.
Entonces, por ejemplo, tal vez el inicio de sesión devolvería un desafío con el tipo de desafío.
Técnicamente, esto se puede hacer devolviendo esa información en la función de inicio de sesión de authProvider y luego tomando decisiones basadas en eso.
const loginResult = login({username: "joeblack", password: "mybadpassword"}); // loginResult returns { challenge: "2FA" } if (challenge) { // redirect to challenge page } else { // redirect to dashboard or wherever }El problema es que incluso si lo manejamos después de la función de inicio de sesión, una vez que se ejecuta la función de inicio de sesión, técnicamente el usuario está autenticado. Entonces podrían simplemente pasar por alto el desafío e ingresar directamente el recurso que desean y podrían verlo.
La función de inicio de sesión de authProvider solo tiene 2 resultados, una promesa resuelta o una promesa rechazada.
Antes de continuar para descubrir cómo hacer que esto funcione, quería ver si alguien más ha investigado este problema.
Esto es básicamente una solución alternativa, pero creo que es la mejor opción por ahora (aunque me encantaría estar equivocado).
La idea es que, aunque la autenticación de Amplify devuelve una promesa resuelta que contiene al usuario de Cognito, verificamos si hay una propiedad de desafío. Si es así, rechazamos la promesa de inicio de sesión para que react-admin no inicie la sesión del usuario.
Luego devolvemos un mensaje de error en la promesa rechazada que puede ser leído por cualquiera que esté llamando a la función de inicio de sesión. Si es un desafío, la interfaz de inicio de sesión puede manejarlo adecuadamente presentando una pantalla 2FA para confirmar.
Tuvimos que incluir también al usuario de Cognito en nuestro caso porque lo necesitamos para confirmar la 2FA.
Aquí está la función de inicio de sesión de authProvider
login: async ({ username, password }) => { try { const cognitoUser = await Auth.signIn(username, password); if (cognitoUser.hasOwnProperty("challengeName")) { return Promise.reject({ message: cognitoUser.challengeName, cognitoUser: cognitoUser, }); } else { return { ...createUser(cognitoUser) }; } } catch (err) { return Promise.reject({ message: err.code }); } }Espero que eso ayude a alguien. Déjame saber si tienes una mejor solución.