paint-brush
Uso de SuperTokens en una aplicación VueJS con su propia interfaz de usuariopor@supertokens.io
32,959 lecturas
32,959 lecturas

Uso de SuperTokens en una aplicación VueJS con su propia interfaz de usuario

por SuperTokens24m2022/09/08
Read on Terminal Reader
Read this story w/o Javascript

Demasiado Largo; Para Leer

Aprenda a crear su propia interfaz de usuario de inicio de sesión con SuperTokens en su aplicación VueJS.

Companies Mentioned

Mention Thumbnail
Mention Thumbnail

Coin Mentioned

Mention Thumbnail
featured image - Uso de SuperTokens en una aplicación VueJS con su propia interfaz de usuario
SuperTokens HackerNoon profile picture
0-item



Esta publicación lo guiará sobre cómo agregar autenticación a una aplicación VueJS con SuperTokens usando su propia interfaz de usuario. Construiremos nuestros propios formularios de autenticación y supertokens-web-js para que esos formularios funcionen.


¿Qué es SuperTokens?


SuperTokens es un proyecto de código abierto que le permite agregar autenticación a su aplicación rápidamente. Ofrece varios métodos de autenticación (llamados recetas).

Junto con una interfaz de usuario preconstruida, también ofrece un SDK de JS estándar llamado supertokens-web-js que puede usar para crear su propia interfaz de usuario. En este tutorial, aprenderemos cómo usar supertokens-web-js para agregar autenticación a una aplicación VueJS. Nos centraremos en la contraseña del correo electrónico y el flujo de inicio de sesión social, pero también puede elegir otro método de autenticación .


Arquitectura


SuperTokens está construido a partir de tres componentes:

  • SDK de interfaz
  • SDK de servidor
  • Un microservicio que se comunica con una base de datos (llamada SuperTokens Core).

Crearemos nuestros propios formularios de inicio de sesión, registro y restablecimiento de contraseña. Luego, usaremos el supertokens-web-js en nuestra aplicación Vue para hacer que estos formularios sean funcionales al invocar las funciones relevantes para cada acción. Estas funciones interactuarán con las API expuestas a través del SDK de SuperTokens que está integrado en su capa de back-end.

Para el backend, usaremos el SDK supertokens-node . Las API expuestas por este SDK seguirán hablando con SuperTokens Core para leer/escribir información en la base de datos.

El servicio central de SuperTokens puede ser autohospedado (y conectado a su propia base de datos), o ser alojado por el equipo detrás de SuperTokens (regístrese en supertokens.com ). En el blog, usaremos una versión de demostración gratuita del núcleo alojado en https://try.supertokens.com


Interfaz


Comience creando una nueva aplicación Vue:

 npm init vue@latest


Habilitaremos Vue Router y Typescript para el proyecto. Elija sí para ellos en el aviso:


 ✔ Project name: … <your-project-name> ... ✔ Add TypeScript? … Yes ✔ Add Vue Router for Single Page Application development? … Yes ... Scaffolding project in ./<your-project-name>... Done.


Una vez hecho esto, dirígete al proyecto e instala las siguientes dependencias:


 npm i supertokens-node supertokens-web-js cors dotenv express npm-run-all


La supertokens-web-js se usará en el frontend para agregar funciones de autenticación y restablecimiento de contraseña a su interfaz de usuario personalizada y la supertokens-node se usará en el backend para exponer las rutas API de autenticación.

Llame a la función de init supertokens-web-js


Inicializaremos el supertokens-web-js en el archivo raíz de nuestra aplicación Vue, es decir, /src/main.ts :


 import ThirdPartyEmailPassword from "supertokens-web-js/recipe/thirdpartyemailpassword"; import Session from "supertokens-web-js/recipe/session"; SuperTokens.init({ appInfo: { appName: "SuperTokens Vue ThirdPartyEmailPassword Example", apiDomain: "http://localhost:3001", }, recipeList: [ThirdPartyEmailPassword.init(), Session.init()], });

En el código anterior, la función init inicializa supertokens-web-js en la interfaz. Llamamos a esta función en el archivo raíz de nuestra aplicación, para que podamos usar la función de administración de sesiones en toda la aplicación. También indica el tipo de autenticación que queremos usar; en nuestro caso, es inicio de sesión social + contraseña de correo electrónico (receta ThirdPartyEmailPassword ).

Crear plantilla HTML de AuthView

Ahora comenzaremos por crear la plantilla HTML que representa la interfaz de usuario de registro e inicio de sesión. Como ejemplo, puede consultar esta plantilla HTML .

El archivo de plantilla llama a las siguientes funciones para manejar el inicio de sesión social y el registro/inicio de sesión con correo electrónico y contraseña:

  • onGithubPressed : esta función permite a los usuarios autenticarse a través de su cuenta de Github
  • onGooglePressed : esta función permite a los usuarios autenticarse a través de su cuenta de Google
  • onSubmitPressed : esta función se activa cuando el usuario ingresa su correo electrónico y contraseña para registrarse o iniciar sesión.

Crear funciones de plantilla y estado de AuthView

Presentaremos esta plantilla HTML en un componente AuthView dentro /src/views/AuthView.vue que también contendrá las implementaciones de las funciones anteriores:


 <template src="../html/authView.html"></template>


Comenzaremos creando estados para almacenar los datos para la autenticación, como el correo electrónico, la contraseña y los mensajes de error de nuestra plantilla:


 // ... data() { return { // we allow the user to switch between sign in and sign up view isSignIn: true, // this will store the email and password entered by the user. email: "", password: "", // any generic error states error: false, errorMessage: "Something went wrong", // any error states specific to the input fields. emailError: "", passwordError: "", }; }


Luego, crearemos una función de inicio de signIn que usará el supertokens-web-js . Pasaremos el correo electrónico y la contraseña a este método y redirigiremos al usuario a la ruta "/" si la autenticación es exitosa. Esta función signIn se llamará desde la función onSubmitPressed si el estado isSignIn es true .


 signIn: async function (_: Event) { const response = await ThirdPartyEmailPassword.emailPasswordSignIn({ formFields: [ { id: "email", value: this.email, }, { id: "password", value: this.password, }, ], }); if (response.status === "WRONG_CREDENTIALS_ERROR") { // the input email / password combination did not match, // so we show an appropriate error message to the user this.errorMessage = "Invalid credentials"; this.error = true; return; } if (response.status === "FIELD_ERROR") { response.formFields.forEach((item) => { if (item.id === "email") { // this means that something was wrong with the entered email. // probably that it's not a valid email (from a syntax point of view) this.emailError = item.error; } else if (item.id === "password") { this.passwordError = item.error; } }); return; } // login is successful, and we redirect the user to the home page. // Note that session cookies are added automatically and nothing needs to be // done here about them. window.location.assign("/"); }


Si el campo de status en el cuerpo de la respuesta es "FIELD_ERROR" y la id es "email" , implica que el usuario ingresó una cadena que falló en la validación del correo electrónico en el backend (probablemente porque no es un correo electrónico válido). Así que almacenamos el estado de error y mostramos el mensaje de error en la interfaz de usuario para el usuario. Este es un ejemplo de cómo puede hacer que aparezca el mensaje de error debajo del campo de correo electrónico:


Similarmente, podemos implementar el signUp donde invocamos la función emailPasswordSignUp de supertokens-web-js para manejar el flujo de emailPasswordSignUp .


Para el inicio de sesión social, usamos los proveedores de autenticación de Google y Github. Cuando se llama a las funciones onGithubPressed o onGooglePressed , llamamos al método getAuthorisationURLWithQueryParamsAndSetState y pasamos el nombre del proveedor en los parámetros. También proporcionamos una URL de devolución de llamada como parámetro de URL de authorisationURL a la que los proveedores redirigirán una vez que se complete el proceso de autenticación. En nuestro ejemplo, usamos http://localhost:3000/auth/callback/google para Google y http://localhost:3000/auth/callback/github para GitHub.


Estas URL también deben configurarse en el tablero del proveedor.


Aquí están las funciones para Github y Google respectivamente:


 onGithubPressed: async function () { const authUrl = await ThirdPartyEmailPassword.getAuthorisationURLWithQueryParamsAndSetState({ providerId: "github", // This is where github should redirect the user back after login or error. // This URL goes on the github dashboard as well. authorisationURL: "http://localhost:3000/auth/callback/github", }); window.location.assign(authUrl); }, onGooglePressed: async function () { const authUrl = await ThirdPartyEmailPassword.getAuthorisationURLWithQueryParamsAndSetState({ providerId: "google", // This is where google should redirect the user back after login or error. // This URL goes on the google dashboard as well. authorisationURL: "http://localhost:3000/auth/callback/google", }); window.location.assign(authUrl); }


Una vez que el usuario finaliza la autenticación en el sitio web del proveedor, se le redirige a la ruta http://localhost:3000/auth/callback/<provider> . Aquí llamamos a la función thirdPartySignInAndUp de supertokens-web-js que consume el código de autorización (que se envía de vuelta desde el proveedor) para iniciar la sesión del usuario.

Esta es la función que maneja el flujo anterior en el componente AuthCallbackView dentro del archivo /src/views/AuthCallbackView.vue :


 mounted: async function () { try { const response = await ThirdPartyEmailPassword.thirdPartySignInAndUp(); if (response.status !== "OK") { // either the user did not complete the login process, or something else went wrong. return window.location.assign("/auth?error=signin"); } // sign in successful. // The session tokens are handled automatically via our SDK. window.location.assign("/"); } catch (_) { window.location.assign("/auth?error=signin"); } }

Configuración de enrutamiento para mostrar los formularios de registro/inicio de sesión

Vue CLI ya genera el enrutamiento inicial para nuestra aplicación dentro /src/router.index.ts .

Actualizaremos este archivo para que la ruta /auth cargue el componente AuthView y la ruta /auth/callback/:provider cargue el componente AuthCallbackView que creamos anteriormente:


 import { createRouter, createWebHistory } from "vue-router"; import AuthView from "../views/AuthView.vue"; const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: [ { path: "/auth", name: "auth", component: () => AuthView, }, { path: "/auth/callback/:provider", name: "authcallback", component: () => AuthCallbackView, } ], }); export default router;


Integración de back-end


Puede ver la sección de configuración rápida del backend en nuestros documentos en supertokens.com , o incluso copiar el código de nuestra aplicación de ejemplo . Como un resumen:


  • Debe inicializar el supertokens-node y proporcionarle la lista de recipeList (similar a como lo hizo en la interfaz).
  • Luego, debe configurar CORS y agregar el middleware errorHandler y el controlador de errores a su aplicación. El middleware SuperTokens expone todas las rutas API relacionadas con la autenticación (como iniciar sesión, registrarse, cerrar sesión, etc.) en la interfaz.
  • Finalmente, debe proporcionar el URI de connectionURI (ubicación) del núcleo de SuperTokens. Para comenzar rápidamente, puede proporcionarlo "https://try.supertokens.com" (este es un núcleo que alojamos con fines de demostración).

Una vez que haya configurado correctamente su servidor, ahora puede intentar registrarse en la interfaz.


Gestión de sesiones


Después de la autenticación, mostraremos un componente HomeView en la página dentro de /src/views/HomeView.vue . Primero, crearemos la plantilla HTML en /src/html/homeView.html :


 <div v-if="session"> <div class="fill"> <div class="top-bar"> <div class="sign-out" v-on:click="signOut">SIGN OUT</div> </div> <div class="fill home-content"> <span class="home-emoji">🥳🎉</span> Login successful <div style="height: 20px" /> Your user ID is <br /> {{ `${userId}` }} <div style="height: 40px" /> <div class="session-button" v-on:click="callAPI">CALL API</div> <div style="height: 30px" /> ------------------------------------ <div style="height: 40px" /> <a href="https://github.com/supertokens/supertokens-web-js/tree/master/examples/vuejs/with-thirdpartyemailpassword" target="_blank" rel="noreferrer"> View the code on GitHub </a> </div> <div class="bottom-banner">Vue Demo app. Made with ❤️ using supertokens.com</div> </div> </div>


Luego, dentro de /src/views/HomeView.vue , verificaremos si el usuario está autenticado mediante el método doesSessionExist expuesto por la receta de sesión del supertokens-web-js .

Para los usuarios autenticados, mostramos un botón de cierre de sesión con información sobre su sesión. Cuando un usuario hace clic en este botón, llamamos al método signOut de supertokens-web-js que borra la sesión del usuario.


Para usuarios no autenticados, podemos redirigirlos a la página /auth .


 <script lang="ts"> import { defineComponent } from "vue"; import Session from "supertokens-web-js/recipe/session"; import ThirdPartyEmailPassword from "supertokens-web-js/recipe/thirdpartyemailpassword"; const apiPort = import.meta.env.VUE_APP_API_PORT || 3001; const apiDomain = import.meta.env.VUE_APP_API_URL || `http://localhost:${apiPort}`; export default defineComponent({ data() { return { // if session is false, we show a blank screen // else we render the UI session: false, userId: "", }; }, methods: { signOut: async function () { await ThirdPartyEmailPassword.signOut(); window.location.assign("/auth"); }, checkForSession: async function () { if (!(await Session.doesSessionExist())) { // since a session does not exist, we send the user to the login page. return window.location.assign("/auth"); } const userId = await Session.getUserId(); // this will render the UI this.session = true; this.userId = userId; }, callAPI: async function () { const response = await fetch(`${apiDomain}/sessionInfo`); if (response.status === 401) { // this means that the session has expired and the // user needs to relogin. window.location.assign("/auth"); return; } const json = await response.json(); window.alert("Session Information:\n" + JSON.stringify(json, null, 2)); }, }, mounted() { // this function checks if a session exists, and if not, // it will redirect to the login screen. this.checkForSession(); }, }); </script> <template src="../html/homeView.html"></template>


Para la ruta /auth , redirigiremos al usuario a la página de inicio si ya existe una sesión:


 checkForSession: async function () { if (await Session.doesSessionExist()) { // since a session already exists, we redirect the user to the HomeView.vue component window.location.assign("/"); } },


Finalmente, para cargar el componente HomeView en "/" actualizaremos el archivo /src/router/index.ts :


 const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: [ { path: "/", name: "home", component: () => HomeView, }, // ... ], }); export default router;


Si ahora visita http://localhost:3000 después de la autenticación, debería ver la siguiente página:



Olvidé el flujo de contraseña


En la interfaz de usuario de inicio de sesión, tenemos un enlace a la página de contraseña olvidada. En esta página, el usuario puede ingresar su correo electrónico y recibir un enlace de restablecimiento de contraseña en su bandeja de entrada. Cuando visitan ese enlace, pueden ingresar su nueva contraseña en esa página para cambiar su contraseña.

Primero, crearemos la plantilla HTML dentro /src/html/forgotPassword.html . Aquí hay un ejemplo que puede usar.


Crearemos un componente dentro del archivo /src/views/ForgotPassword.vue donde representaremos la plantilla anterior:


 <template src="../html/forgotPassword.html"></template>


En la plantilla HTML, representamos condicionalmente un formulario, basado en una variable llamada tokenPresent , que es una variable de estado que representa si se ha generado o no un token de restablecimiento de contraseña. Esta variable tokenPresent se establece en función del token presente en los parámetros de consulta de la URL de la página. En el caso de que el usuario haya hecho clic en el botón de contraseña olvidada (en la página de inicio de sesión), no hay ningún token presente en los parámetros de consulta de la URL de la página, por lo que la variable tokenPresent se establece en false .


Dado que tokenPresent es false , representamos el formulario donde el usuario ingresará su correo electrónico para obtener el enlace de restablecimiento de contraseña. Cuando el usuario ingresa su correo electrónico en este formulario y lo envía, llamamos al método sendPasswordResetEmail de supertokens-web-js y pasamos su correo electrónico. Esta función interactúa con una API de back-end para enviar un enlace de restablecimiento de contraseña en el correo electrónico del usuario, si ese correo electrónico existe en SuperTokens.


El enlace de restablecimiento de contraseña es como http://localhost:3000/auth/reset-password?token=....&rid=thirdpartyemailpassword . Este enlace tiene la misma ruta que la página de contraseña olvidada, sin embargo, dado que la URL tiene el parámetro de consulta de token , debe mostrar el formulario donde el usuario puede ingresar su nueva contraseña.


Cuando ingresan su nueva contraseña en el formulario, llamamos a la función submitNewPassword con la nueva contraseña. Esta función leerá automáticamente el token de la URL y llamará a la API de backend de SuperTokens para cambiar la contraseña del usuario.


En caso de que el token de restablecimiento de contraseña ya se haya consumido o haya caducado, la llamada de función devolverá un estado no "OK" y luego podemos mostrar un mensaje en la interfaz de usuario para solicitar al usuario que regrese a la pantalla de inicio de sesión.


 <script lang="ts"> import ThirdPartyEmailPassword from "supertokens-web-js/recipe/thirdpartyemailpassword"; import { defineComponent } from "vue"; export default defineComponent({ data() { /** * If the URL has a token query param, it means that we should show the * "enter new password" screen, else we should ask the user for their email * to send the password reset link. */ const urlParams = new URLSearchParams(window.location.search); const token = urlParams.get("token"); return { // the email property is used for the enter email screen email: "", error: false, errorMessage: "Something Went Wrong", didSubmit: false, // if tokenPresent is true, it means that the user has clicked on the // reset password link. tokenPresent: token !== null, password: "", }; }, methods: { onSubmitClicked: async function () { if (this.tokenPresent) { // we try and change the user's password now by consuming the token try { const response = await ThirdPartyEmailPassword.submitNewPassword({ formFields: [ { id: "password", value: this.password, }, ], }); if (response.status === "FIELD_ERROR") { // this indicates that the password entered by the user // did not match the backend password validation logic. throw new Error(response.formFields[0].error); } else if (response.status === "RESET_PASSWORD_INVALID_TOKEN_ERROR") { // the password reset token was consumed already, or has expired. // in this case, the user should go back to the login screen or the // enter email screen throw new Error("Password reset token has expired, please go back to the sign in page"); } // password reset successful. window.location.assign("/auth"); } catch (e: any) { this.errorMessage = e.message; this.error = true; } } else { // the user has entered an email for whom the password reset link // will be sent. try { const response = await ThirdPartyEmailPassword.sendPasswordResetEmail({ formFields: [ { id: "email", value: this.email, }, ], }); if (response.status !== "OK") { // this means that the email validation logic failed. throw new Error(response.formFields[0].error); } // a password reset email was sent successfully. if (this.didSubmit !== true) { // we change the UI to show that the email has been sent this.didSubmit = true; } } catch (e: any) { this.errorMessage = e.message; this.error = true; } } }, }, }); </script>


Si la función submitNewPassword tiene éxito, significa que la contraseña del usuario se ha restablecido correctamente y redirigimos al usuario a la página /auth para que ahora pueda iniciar sesión con su nueva contraseña.

Para cargar el componente ForgotPassword en la ruta /auth/reset-password , realizaremos los siguientes cambios en el archivo /src/router/index.ts :


 const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: [ // ... { path: "/auth/reset-password", name: "resetPassword", component: () => ForgotPasswordView, }, ], });


Una vez que haga eso, si ahora visita http://localhost:3000/auth/reset-contraseña , deberías ver la siguiente página:


Si ingresa su correo electrónico y presiona el botón "Enviarme un correo electrónico", debería recibir un enlace para restablecer su contraseña en el correo electrónico ingresado:

Después de hacer clic en el enlace, puede ingresar su nueva contraseña y presionar el botón "Cambiar contraseña" para actualizar su contraseña:


Configuración básica de Supertokens


Mientras realizamos la configuración del back-end, estamos usando "https://try.supertokens.com" como el URI de connectionURI para el núcleo. Esta es una instancia central de demostración alojada por el equipo de SuperTokens. Puede usar esto durante el tiempo que desee, pero cuando se comprometa a usar SuperTokens, debe cambiar a una versión autohospedada o administrada del núcleo.


Conclusión


Usamos el supertokens-web-js para agregar contraseña de correo electrónico y autenticación social junto con la funcionalidad de contraseña olvidada a una aplicación Vue. Enlaces útiles:



Escrito por la gente de SuperTokens . ¡Espero que lo hayas disfrutado! Siempre estamos disponibles en nuestro servidor Discord. Únase a nosotros si tiene alguna pregunta o necesita ayuda.

También publicado aquí .