Implementación de una función de restablecimiento de contraseña con rutas dinámicas Next.js

 

 

 

  • SmashingConf UX y diseño, Amberes 2024
  • Patrones de diseño de interfaces inteligentes, vídeo de 10h + formación UX

  • Índice
    1. Una descripción general del flujo de restablecimiento de contraseña
    2. Comprender las rutas dinámicas
    3. Lectura de parámetros de URL con el gancho Userouter
    4. Construyendo las formas
    5. Pensamientos finales
      1. Lecturas adicionales sobre la revista Smashing

    La mayoría de los usuarios tienden a olvidar sus contraseñas, así que cree experiencias que siempre serán valiosas para las personas cuando utilicen sus productos. En este artículo, analizaremos cómo implementar una función de restablecimiento de contraseña con rutas dinámicas de Next.js mientras priorizamos la UX.

     

    En un sentido general, la autenticación se presenta como un obstáculo para muchas personas cuando intentan comenzar con un marco en particular, y Next.js no se queda atrás.

    Sin embargo, existen muchos recursos sobre la creación de aplicaciones autenticadas con Next.js. Bueno, incluso hay un proyecto de código abierto que literalmente maneja la autenticación desde cero.

    Pero el alcance de este artículo no gira en torno al concepto completo de autenticación. Solo estamos eligiendo un patrón específico del proceso de autenticación: el flujo de “restablecimiento de contraseña” y cómo se puede implementar en el lado del cliente (frontend) de una aplicación web.

    En este artículo, verá cómo se puede implementar esta función utilizando la herramienta común de obtención de datos, Axios, la función de rutas dinámicas incorporada de Next.js y el useRoutergancho.

    Una descripción general del flujo de restablecimiento de contraseña

    Desde la llegada de la Web, los ingenieros siempre se han esforzado por brindar soluciones a los problemas que surgieron durante los primeros días de la Web, y la seguridad del software en la Web no es una excepción.

    Existe un dicho popular que dice así: “Los usuarios siempre olvidarán sus contraseñas”, y esa es la absoluta verdad. Mucha gente incluso teme la página de “restablecer contraseña” porque, pensándolo bien, después de pasar mucho tiempo intentando adivinar sus contraseñas (todo en vano), se sienten frustrados o enojados cuando llegan a esta página. página concreta.

    A medida que creamos interfaces de usuario, también debemos intentar en la medida de lo posible que la experiencia sea agradable para los usuarios. Por mucho que nos encantaría superar el flujo del proceso de restablecimiento de contraseña, también se debe priorizar la UX de ese flujo.

     

    El flujo común del proceso de restablecimiento de contraseña se puede ver a continuación.

    • El usuario se siente frustrado después de intentar firmar sin éxito. Hacen clic en el enlace "restablecer contraseña" y son redirigidos a la página correspondiente. La interfaz de usuario que ven es el típico formulario web que incluirá su dirección de correo electrónico o su nombre de usuario.
    • Cuando escriben su dirección de correo electrónico o nombre de usuario en el campo de entrada, hacen clic en el botón que tiene el texto común "envíeme un enlace de recuperación por correo electrónico".
    • Reciben una confirmación de que se ha enviado un enlace seguro a su correo electrónico. A veces, este texto de confirmación se puede mostrar en un componente similar a una tarjeta o en un modal que se desvanece con el tiempo.

    Nota : Por motivos de seguridad y buena UX, es bueno utilizar un texto bastante similar a este: “Se ha enviado un correo electrónico a su bandeja de entrada. Haga clic en el enlace cuando lo reciba”. Puede construir esta oración de la forma que considere adecuada, siempre y cuando no revele que el correo electrónico o el nombre de usuario que ingresaron existe en la base de datos. Este enfoque evita que los atacantes sepan si ese correo electrónico existe, saboteando así cualquier intento de phishing que quieran intentar con dicha dirección de correo electrónico. En cuanto a la UX, el texto no garantiza al usuario que las credenciales que ingresó sean las correctas. Esto, a su vez, les permite volver a verificar las credenciales que envían.

    • El enlace que se envía a su dirección de correo electrónico contiene un JWT y su dirección de correo electrónico user_id, o en este caso, su dirección de correo electrónico.
    • Al hacer clic en ese enlace, se les redirige a la ruta/página donde pueden ingresar su nueva contraseña. La ruta que seguirá el usuario puede ser del siguiente formulario
    https://localhost:3000/reset-password/user-email/JWToken
    • La última parte del flujo es verificar si el JWT que se genera está asociado con la cuenta del usuario. De lo contrario, arrojamos un error al mostrar el mensaje de error que se obtiene del backend.

    Ahora que ha visto cómo está estructurado el flujo de “restablecer contraseña”, veamos cómo se puede implementar con Next.js.

    Comprender las rutas dinámicas

    En esta sección, repasaremos el concepto de rutas dinámicas ilustrándolo con la estructura de carpetas de un proyecto Next.js y veremos cómo lo integraremos en la función "restablecer contraseña". Pero primero, configuremos una aplicación Next.js.

    npx create-next-app app-name

    El comando anterior hace eso por nosotros. El equipo de Next.js ya envió una nueva actualización al marco y también introdujo un par de carpetas y características nuevas en la estructura predeterminada del proyecto. Sin embargo, no cubriremos mucho sobre ese aspecto, ya que está fuera del alcance de este artículo. Puede leer más sobre las actualizaciones aquí si lo desea.

    En el siguiente fragmento, verá la estructura básica de los archivos con los que interactuaremos en este artículo.

     

    └── pages / ├── forgot-password/ │ └── [token]/ │ └── [email].js ├── _app.js └── index.js

    Arriba, verás que los archivos en la estructura de carpetas son bastante pequeños. Eso es porque quiero ser lo más conciso posible en este artículo.

    Y dado que la implementación del flujo de “restablecimiento de contraseña” es nuestra mayor preocupación, creo que será mejor si tenemos menos desorden. Ahora, comprendamos un poco esta estructura.

    Notarás que tenemos la forgot-passwordcarpeta en el pagesdirectorio, que contiene algunos archivos. Pero la convención de nomenclatura de estos archivos es bastante diferente de la forma en que se nombran otros archivos. El nombre de los archivos (token y email.js) está entre corchetes.

    Las carpetas y archivos con nombres así se denominan rutas dinámicas y, dado que están en el pagesdirectorio, automáticamente se convierten en rutas a las que puede acceder el navegador. Son dinámicas porque los valores que toman estas rutas no son estáticos, lo que significa que cambian con el tiempo.

    Este patrón de nombrar archivos se ve comúnmente en acción cuando decide crear un blog o cuando interactúa con datos que cambian según el tipo de usuario que ha iniciado sesión en una aplicación. Puede ver cómo utilicé esta función de Next.js cuando estaba creando mi blog . También puede obtener más información al respecto en los documentos de Next.js.

    En la forgot-passwordcarpeta, aquí se puede acceder a la ruta donde se puede acceder a la interfaz de usuario que contiene el formulario de contraseña olvidada. Échale un vistazo a continuación.

    https://localhost:3000/forgot-password/token/email

    Dado que es una ruta dinámica, los parámetros de URL tokeny emailsiempre cambiarán según el usuario que intenta restablecer su contraseña. El token y el correo electrónico del usuario A serán diferentes de los del usuario B.

    Lectura de parámetros de URL con el gancho Userouter

    El useRoutergancho en Next.js se puede utilizar para lograr muchas implementaciones prácticas de interfaz de usuario, desde la idea común de implementar un elemento de barra de navegación activa con la .pathnameclave hasta funciones más complejas.

    Veamos useRouterahora cómo podemos leer los parámetros de URL de rutas dinámicas con el gancho, ¿de acuerdo? Para hacer eso, primero deberá importar el módulo a su página/componente.

    import { useRouter } from 'next/router'export default function PageComponent({ children }) { const router = useRouter() return ( React.Fragment {/* page content falls below */} div{children}/div /React.Fragment )}

    El fragmento de arriba muestra el uso básico del gancho. Como estamos interesados ​​en los parámetros de consulta de la URL, será mejor si desestructuramos el querymétodo del gancho en lugar de hacer algo como esto: router.query. Haremos algo similar a continuación.

     

    import { useRouter } from 'next/router'const { query } = useRouter()

    Ahora podemos continuar y crear variables que almacenarán los parámetros de URL que queramos. El siguiente fragmento muestra cómo puede hacerlo.

    const token = query.tokenconst email = query.email

    Tenga en cuenta que los valores query.tokeny query.emailson el resultado del nombre de los archivos. Recuerde de la estructura de carpetas en la forgot-passwordcarpeta donde tenemos los archivos [email].jsy [token]. Si cambia el nombre de esos archivos a [userEmail].jsy [userToken]respectivamente, el patrón de asignación de estas variables será similar al que se muestra a continuación.

    const token = query.userTokenconst email = query.userEmail

    Siempre puedes registrar estas variables en la consola para ver el resultado.

    Ahora que comprende cómo se obtienen estos parámetros de la URL, comencemos por construir la estructura de los formularios.

    Construyendo las formas

    En esta sección, analizaremos el proceso de creación del formulario y cómo puede utilizar Axios para realizar la obtención de datos a través del punto final API arbitrario. No nos centraremos en el estilo de estos formularios ni en la explicación de la estructura. Supongo que ya sabes cómo estructurar y diseñar un formulario básico de React. Entonces, comencemos con el diseño del formulario en la ruta para olvidar la contraseña.

    import React from 'react'import axios from 'axios'import { ErrModal, SuccessModal } from '../components/Modals'export const DefaultResetPassword = () = { const [email, setEmail] = React.useState('') const [loading, setLoading] = React.useState(false) const handleForgot = () = { } // we’ll see this later return ( div form onSubmit={handleForgot} className="reset-password" h1Forgot Password/h1 pYou are not alone. We’ve all been here at some point./p div label htmlFor="email"Email address/label input type="email" name="email" placeholder= “your email address” value={email} onChange={(e) = setEmail(e.target.value)} required / /div button name="reset-pwd-button" className="reset-pwd" {!loading ? ‘Get secure link’: ‘Sending...’} /button /form /div )}

    El fragmento de arriba muestra la estructura básica de la interfaz de usuario que verá cuando llegue a la ruta de contraseña olvidada. Notarás el texto en la etiqueta del párrafo debajo del texto en negrita "Olvidé mi contraseña". Chistes cortos

    pYou are not alone. We’ve all been here at some point/p

    Con un tipo de texto como el anterior, estás mejorando la experiencia de usuario de las personas que acceden a la página de contraseña olvidada de tu aplicación. Les está asegurando que no es gran cosa que hayan olvidado su(s) contraseña(s), así que no hay necesidad de sentirse mal por ello.

     

    No es necesario que utilices exactamente el texto anterior. Puedes simplemente asegurarte de que cualquier texto que utilices tenga un tono de empatía .

    Ahora, pasemos a la parte importante de este formulario, que es donde debemos declarar una función que enviará el correo electrónico que el usuario ingresa en el campo de entrada al backend.

    import { authEndpoints } from '../endpoints'export const DefaultResetPassword = () = { const handleForgot = async (e) = { e.preventDefault() try { setLoading(true) const response = await axios({ method: 'POST', url: authEndpoints.recover, data: { email, }, headers: { 'Content-Type': 'application/json', }, }) setResestSuccess(response.data.msg) setLoading(false) setResetError('') } catch (error) { setLoading(false) const { data } = error.response setResetError(data.msg) setResestSuccess(null) } } return div{/* ...previous form component */}/div}

    En el fragmento anterior, notará que estamos importando el punto final API al que enviaremos una solicitud POST, y es por eso que lo pasamos como una variable a la urlclave en el método Axios.

    La solicitud POST recibe la dirección de correo electrónico del usuario como carga útil, que a su vez será validada en el backend y se generará un JWT para esa dirección de correo electrónico que se utilizará para autorizar el proceso de restablecimiento de contraseña del usuario.

    setResestSuccess(response.data.msg)setLoading(false)setResetError('')catch (error) { setLoading(false) const { data } = error.response setResetError(data.msg) setResestSuccess(null)}

    Cuando observa el fragmento anterior, notará que estamos usando algunas funciones de devolución de llamada de estado ya declaradas de las variables de estado.

    Un ejemplo es la setLoadingfunción que tiene su valor establecido trueen el trybloque. Luego, su valor se establece en falso cuando los datos se han enviado correctamente. Y si no es así, tenemos un catchbloque que "captará" el error y mostrará el mensaje de error que hemos desestructurado desde el punto final.

    También notarás que hay un par de funciones de devolución de llamada de estado en el fragmento anterior, como setResestSuccessy setResetError.

    Los definidores se obtienen de la declaración de las variables de estado. Véalos a continuación.

    import React from 'react'import { ErrModal, SuccessModal } from '../components/Modals'export const DefaultResetPassword = () = { const [resetSuccess, setResestSuccess] = React.useState() const [resetError, setResetError] = React.useState() return ( div {resetError ? ErrModal message={resetError} / : null} {resetSuccess ? SuccessModal message={resetSuccess} / : null} form onSubmit={handleForgot} className="reset-password" {/* form content */} /form /div )}

    Los mensajes de error o éxito obtenidos del backend se pueden representar en la interfaz de usuario para que el usuario conozca el estado de sus acciones.

     

    Notarás que estamos usando componentes modales personalizados para representar el mensaje. Estos componentes reciben el mensaje como accesorios y se pueden reutilizar en todo el código base. Eche un vistazo a la estructura de los componentes a continuación.

    export const SuccessModal = ({ message }) = { return ( div className="auth-success-msg" p{message}/p /div )}export const ErrModal = ({ message }) = { return ( div className="auth-err-msg" p{message}/p /div )}

    Puede diseñar estos componentes de forma única para poder distinguir el modal de "error" del modal de "éxito". La convención común es utilizar el color rojo para los mensajes de error y el color verde para los mensajes de éxito. La forma en que elija diseñar estos componentes depende completamente de usted.

    Además de todo lo dicho, necesitamos una forma de verificar que se esté pasando el tipo de datos correcto como accesorio al componente modal. Esto se puede lograr con el módulo "tipo prop" en reaccionar.

    propTypes.ErrModal = { message: propTypes.string.isRequired,}propTypes.SuccessModal = { message: propTypes.string.isRequired,}

    El proceso de verificación de tipo en el fragmento anterior garantiza que los datos que recibe el componente deben ser una cadena y son obligatorios. Si el componente no recibe una propiedad con un valor de cadena, React arrojará un error.

    Ahora que hemos cubierto el aspecto importante del primer formulario y los componentes básicos de lo que replicaremos en la ruta de restablecimiento de contraseña. Comencemos echando un vistazo al diseño del formulario a continuación.

    import axios from "axios";import React from “react”;import Head from “next/head”;import { useRouter } from "next/router";import { SuccessModal, ErrModal } from "../components/Modals";const ResetPassword = () = { const [newPassword, setNewPassword] = React.useState(""); const [loading, setLoading] = React.useState(false); const [resetPasswordSuccess, setResetPasswordSuccess] = React.useState(); const [resetPasswordError, setResetPasswordError] = React.useState(); const { query } = useRouter(); const token = query.token; const email = query.email; const resetPassword = () = { } // coming in later... return ( React.Fragment Head titleReset your password/title /Head div {email token ? ( div className="auth-wrapper" {resetPasswordSuccess ? ( SuccessModal message={resetPasswordSuccess} / ) : ( null )} {resetPasswordError ? ( ErrModal message={resetPasswordError} / ) : ( null )} form onSubmit={resetPassword} className="reset-password" h1Reset Password/h1 pPlease enter your new password/p div label htmlFor="password"Password*/label input name="password" type="password" placeholder="enter new pasword" value={newPassword} onChange={(e) = setNewPassword(e.target.value)} / /input button name="reset-pwd-button" className="reset-pwd" {!loading ? "Reset" : "Processing..."} /button /form /div ) : ( pThe page you're trying to get to isn't available/p )} /div /React.Fragment );};

    Dado que analizamos los rudimentos de la primera forma en la sección anterior, el fragmento anterior contiene casi lo mismo que la forma anterior.

     

    Puede ver cómo estamos leyendo los parámetros de la URL y también las declaraciones de las variables de error y éxito de restablecimiento de contraseña.

    const [resetPasswordSuccess, setResetPasswordSuccess] = React.useState()const [resetPasswordError, setResetPasswordError] = React.useState()const { query } = useRouter()const token = query.tokenconst email = query.email

    También notará la forma en que renderizamos condicionalmente el formulario de restablecimiento de contraseña al verificar si las variables emaily tokenestán presentes en la URL; si estas variables son falsas (es decir, no están en la URL), representamos un texto que dice que la página que están buscando no está disponible.

    { email token ? ( div className="auth-wrapper" FormComponentt / /div ) : ( pThe page you’re trying to get to isn’t available/p )}

    Ahora, echemos un vistazo a la función de controlador que usaríamos para enviar la nueva contraseña del usuario (junto con el token y el correo electrónico con fines de verificación) al backend a través del punto final de API.

    import { authEndpoints } from '../endpoints'const resetPassword = async (e) = { e.preventDefault() try { setLoading(true) const response = await axios({ method: 'POST', url: authEndpoints.resetPassword, data: { token, email, password: newPassword, }, headers: { 'Content-Type': 'application/json', }, }) setResetPasswordSuccess(response.data.msg) setLoading(false) setTimeout(() = { router.push('/') }, 4000) setResetPasswordError('') } catch (error) { setLoading(false) setResetPasswordError(error.response.data.msg) setResetPasswordSuccess(null) }}

    El fragmento anterior es una función de controlador asincrónica. Lo estamos usando para enviar una solicitud POST con la nueva contraseña del usuario, el token de acceso y la dirección de correo electrónico, que tomamos de los parámetros de consulta en el segmento de URL.

    setTimeout(() = { router.push('/')}, 4000)

    Cuando echas un vistazo al fragmento de arriba, verás cómo estamos usando el setTimeoutmétodo en JavaScript y useRouterel enlace de Next.js para redirigir al usuario a la página de inicio, que es la página de inicio de sesión en este caso, después de cuatro segundos. (Puedes reducir este plazo si lo deseas), para que puedan iniciar sesión nuevamente.

    Hacer esto también aumenta la métrica de la buena experiencia del usuario, ya que evita que el usuario busque un enlace o un botón que lo lleve de regreso a la página de inicio de sesión.

    Pensamientos finales

    Existe mucha información sobre las mejores prácticas y fantásticos patrones de diseño para restablecer contraseñas. Este artículo es solo una implementación frontal de un flujo de restablecimiento de contraseña que también tiene en cuenta la cuestión de la experiencia del usuario. No basta con crear una función de restablecimiento de contraseña sin considerar la UX de las personas que usarían esta función.

    Gracias por leer. ¡Espero que este artículo haya sido útil!

    Lecturas adicionales sobre la revista Smashing

    • “ Cómo implementar la autenticación en Next.js con Auth0 ”, Facundo Giuliani
    • “ Obtención dinámica de datos en una aplicación Next.js autenticada ”, Caleb Olojo
    • “ Localización de su aplicación Next.js ”, Átila Fassina
    • " El estado actual de la autenticación: tenemos un problema de contraseña ", Drew Thomas

    (NL, IL)Explora más en

    • javascript
    • Siguiente.js
    • Actuación
    • Seguridad





    Tal vez te puede interesar:

    1. ¿Deberían abrirse los enlaces en ventanas nuevas?
    2. 24 excelentes tutoriales de AJAX
    3. 70 técnicas nuevas y útiles de AJAX y JavaScript
    4. Más de 45 excelentes recursos y repositorios de fragmentos de código

    Implementación de una función de restablecimiento de contraseña con rutas dinámicas Next.js

    Implementación de una función de restablecimiento de contraseña con rutas dinámicas Next.js

    SmashingConf UX y diseño, Amberes 2024 Patrones de diseño de interfaces inteligentes, vídeo de 10h + formación UX Índice

    programar

    es

    https://pseint.es/static/images/programar-implementacion-de-una-funcion-de-restablecimiento-de-contrasena-con-rutas-dinamicas-next-1154-0.jpg

    2024-04-04

     

    Implementación de una función de restablecimiento de contraseña con rutas dinámicas Next.js
    Implementación de una función de restablecimiento de contraseña con rutas dinámicas Next.js

    Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente

     

     

    Top 20