
En este tutorial, revisaremos brevemente cómo se implementan las solicitudes REST a la API que requieren que el usuario esté autorizado, y crearemos un "contenedor" asíncrono para la solicitud, que verificará la autorización y la actualizará de manera oportuna.
Información de inicio de sesión
Después de haber realizado una solicitud REST a la API, donde enviamos el nombre de usuario y la contraseña, a cambio obtenemos json del siguiente formato (los valores son aleatorios y las líneas suelen ser más largas):
{ "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSld", "refresh_token": "1eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgS", "expires_in": 124234149563 }
Puede haber más
campos en la respuesta, por ejemplo,
"token_type" ,
"expires_on" , etc., pero, para esta implementación, solo necesitamos los tres campos anteriores.
Echemos un vistazo más de cerca a ellos:
- access_token : el token que necesitaremos enviar en el encabezado de cada solicitud para recibir datos en respuesta
- refresh_token : el token que necesitaremos enviar para recibir un nuevo token cuando caduque el anterior
- expires_in - token de por vida en segundos
Recibiendo token
Ahora cree una función que recibirá el json descrito anteriormente y guárdelo.
Almacenaremos datos para autorización en
sessionStorage o
localStorage , según nuestras necesidades. En el primer caso, los datos se almacenan hasta que el usuario completa la sesión o cierra el navegador, en el segundo caso, los datos se almacenarán en el navegador por un tiempo ilimitado hasta que por alguna razón se borre el almacenamiento local.
Función para guardar el token en sessionStorage:
function saveToken(token) { sessionStorage.setItem('tokenData', JSON.stringify(token)); }
Función para recibir un token:
function getTokenData(login, password) { return fetch('api/auth', { method: 'POST', credentials: 'include', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify({ login, password, }), }) .then((res) => { if (res.status === 200) { const tokenData = res.json(); saveToken(JSON.stringify(tokenData));
Por lo tanto, recibimos un token con los campos
"access_token" ,
"refresh_token" y
"expires_in" y lo
guardamos en
sessionStorage para su uso posterior.
Actualización de token
El token que recibimos anteriormente tiene una vida útil limitada, que se establece en el campo
"expires_in" . Una vez que caduca su vida útil, el usuario no podrá recibir nuevos datos enviando este token en la solicitud, por lo que debe obtener un nuevo token.
Podemos obtener el token de dos maneras: la primera es iniciar sesión nuevamente enviando el nombre de usuario y la contraseña al servidor. Pero esto no nos conviene, porque obligar al usuario a volver a ingresar los datos de autorización cada vez que transcurre un cierto período de tiempo es incorrecto; esto debe hacerse automáticamente. Pero almacenar un par de inicio de sesión / contraseña en algún lugar de la memoria para el envío automático no es seguro, es por eso que necesitamos un
refresh_token , que se recibió antes con
access_token y se almacenó en sessionStorage. Al enviar este token a otra dirección que proporciona la API, podemos obtener un nuevo token "nuevo" en respuesta.
Función para actualización de token
function refreshToken(token) { return fetch('api/auth/refreshToken', { method: 'POST', credentials: 'include', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify({ token, }), }) .then((res) => { if (res.status === 200) { const tokenData = res.json(); saveToken(JSON.stringify(tokenData));
Usando el código anterior, reescribimos el token en sessionStorage y ahora podemos enviar solicitudes a la API de una nueva manera.
Crear una función de contenedor
Ahora creamos una función que agregará datos de autorización al encabezado de la solicitud y, si es necesario, la actualizará automáticamente antes de realizar la solicitud.
Dado que si el token ha expirado, necesitaremos solicitar un nuevo token, entonces nuestra función será asíncrona. Para esto usaremos la construcción async / await.
Función de envoltura
export async function fetchWithAuth(url, options) { const loginUrl = '/login';
Usando el código anterior, creamos una función que agregará un token a las solicitudes en la API. Con esta función, podemos reemplazar fetch en las consultas que necesitamos, donde se requiere autorización y para esto no necesitamos cambiar la sintaxis o agregar más datos a los argumentos.
Bastará con "importarlo" en un archivo y reemplazar la búsqueda estándar con él.
import fetchWithAuth from './api'; function getData() { return fetchWithAuth('api/data', options) }