¿Cómo se implementa la autorización en una aplicación web?
La capacidad de un sistema para distinguir qué acciones pueden realizar los usuarios autenticados es crucial. En esta lección, exploramos cómo implementar esta lógica, diferenciando autenticación y autorización. Mientras la autenticación se encarga de identificar a los usuarios, la autorización determina qué permisos tienen. Comenzamos a construir el sistema observando los roles en una aplicación de manejo de contenido.
¿Cómo configuro roles de usuario en una aplicación?
Lista de administradores:
El primer paso en nuestra implementación es crear una lista de administradores.
Aunque normalmente esta lista viviría en un backend, por ahora se simula con un arreglo estático en JavaScript.
const adminList =['Iris','Retaxmaster','Freddy'];
Asignación de propiedad isAdmin:
Verificamos si el usuario está en la lista de administradores al momento del login.
¿Cómo permitir a los autores editar su propio contenido?
Además de los administradores, es razonable que los autores puedan modificar su propio contenido. Vamos a permitir esto mediante la siguiente lógica condicional:
Variable canDelete:
Definimos una variable que determina si el usuario actual puede eliminar un blogpost, ya sea porque es administrador o porque es el autor del contenido.
¿Cómo puedo mejorar este sistema con múltiples listas de permisos?
El reto en este contexto es expandir la lógica para manejar múltiples roles, posiblemente con listas separadas para administradores, editores, y beta testers, cada una capaz de realizar diferentes acciones. Por ejemplo, los beta testers podrían tener acceso a funcionalidades exclusivas, mientras que los editores podrían modificar el contenido sin eliminarlo.
Listas múltiples:
Crear listas para cada tipo de usuario con permisos especiales.
Añadir lógica para verificar la pertenencia de un usuario a cada lista y actuar en consecuencia.
Crear un sistema de autorización robusto no solo protege la integridad del contenido, sino que también permite a los usuarios una interacción más personalizada y segura con la aplicación. Experimente y adapte estos ejemplos a sus necesidades, ¡la práctica perfecciona!
Roles y permisos en aplicaciones web: Autenticación y autorización
¡Wohoo! Soy el admin 😎 jajaja. Para el caso del final yo crearía roles. Asignarle roles a cada usuario (ya no solo un campo de user.isAdmin, sino un campo user.role) y con base en ese campo validar cada acción para saber si su rol le permite o no hacer X acción :p
Pensé en una idea similar.
Le agregaría el campo que dices, pero que sea un objeto u array (no sabría que conviene en este caso) y comparas según donde corresponda.
Genial!
En mi caso, del lado del backend lo había definido justo así, cada usuario tiene un rol y desde el mismo backend al momento de editar o eliminar algún elemento se valida si la persona que esta realizando la petición es admin o si es el creador.
Luego, desde reac unicamente se hace la validación del rol del usuario para mostrar los botones tal y como el profe lo indica 😊👌
Roles y permisos
La autorización es la que le permite a los usuarios tener cierto tipo de roles que nos permiten saber a que permisos tenemos acceso en nuestra aplicación, actualizar información o borrarla, tener permisos solo de lectura de la información, poder subir información etc .
Podemos tener distintos tipos de roles, por mencionar algunos pueden ser el administrador, moderadores, usuarios premiun o freemiun y demás.
Para empezar a implementar esta lógica de autorización vamos a nuestro archivo auth.js:
// Listas de Autorizaciónconst adminList =['RetaxMaster','freddier','juandc'];constAuthContext=React.createContext();functionAuthProvider({ children }){/* Dentro de nuestra función de login veremos si el usuario a
ingresar es administrador */constlogin=({ username })=>{/* Esta es la validación para saber si el usuario que ingresa a
la aplicación es administrador o no */const isAdmin = adminList.find(admin=> admin === username);/* Ahora nuestros usuarios van a tener una propiedad para saber
si son admis */setUser({ username, isAdmin });navigate('/profile');}}
Ahora en nuestra aplicación vamos a crear los permisos que van a tener nuestros administradores.
BlogPost.js
import{ useAuth }from'../../auth/auth';functionBlogPost(){...// Vamos a hacer uso de la autenticaciónconst auth =useAuth();/* Aqui buscamos al momento de registrarnos si el usuario es parte
de la lista de administradores */const blogpost = blogdata.find(post=> post.slug== slug );return(<> ...
{/* Si nuestro usuario existe y es admin vamos a renderizar
este botón */}{auth.user?.isAdmin &&(<button>Eliminar blogpost</button>)}</>);}
Ahora si entramos a alguno de los BlogPost con el nombre de algún administrador vamos a poder ver renderizado nuestro botón de eliminar BloPost.
Ya tenemos la lógica para mostrar contenido dependiendo del rol.
Ahora si vemos los blogpost que tienen autores, digamos que el autor del blog desea eliminarlo, pero ¿como lo va a hacer?
Vamos a crear la lógica para que los autores del contenido puedan eliminar sus propios Blogs.
functionBlogPost(){.../* Aquí validaremos si al acceder al blog soy el autor del blog y
pueda eliminarlo o tenga el rol de administrador para ello */const canDelete = auth.user?.isAdmin || blogpost.author=== auth.user?.username;constreturnToBlog=()=>{navigate('/blog');}return(<> ...
{/* Ahora vamos a preguntar si puedo borrar el BlogPost*/}{canDelete &&(<button>Eliminar blogpost</button>)}</>);}
Ahora en caso de que seamos lo autores del Blog podemos eliminarlo, super fácil.
Pense que iba a ser complicado pero me resulto sencillo, cambiaria algunos nombres de los objetos.
Todavia tengo dudas de como se crean las API y los objetos JSON, si tienen una regla de planificar y organizar
Dentro de AuthProvider asignar el usuario y su rol
functionAuthProvider({ children }){//............constlogin=(username)=>{//revisar si el usuario existe o lo crea como visitanteconst rol = users.find((usu)=> usu.name=== username); rol !==undefined?setUser(rol):setUser({name: username,role: roles.visitor});navigate("/profile");};//............}
finalmente en BlogPost.jsx hacer las validaciones para renderizar un boton o no
dependiendo de los permisos de su rol
Yo era de esos men, que tuvo su propio servidor Habbo Hotel. Este curso me recuerda mucho cuando modificaba y otorgaba los permisos como dueño de ese lugar.
Recuerdo que utilizaba PHP para quitar y poner.
!Ahhh, que recuerdos.!
Inspirado en unos de los compañeros dejo una simple y humilde solucion.
En el primero array determinaremos los roles y lo que pueden hacer.
En el segundo crearemos usuarios con roles.
Apoyándome en los comentarios de los compañeros y lo aprendido en el curso, cree un array, que incluye a las personas autorizadas, los roles y permisos
En el blog, de acuerdo a los permisos que tiene cada rol, cree una condición para que el administrador y el autor puedan borrar, pero solo el autor de cada blog, pueda editar
import{ useAuth }from'./auth';functionBlogPost({ post }){const{ user }=useAuth();// Solo admins y autores pueden eliminarconst canDelete = user.isAdmin|| post.author=== user.username;return(<div><h2>{post.title}</h2><p>Por:{post.author}</p>{canDelete &&(<button onClick={handleDelete}> 🗑️ Eliminar</button>)}</div>);}
⚠️ Crítico: Frontend = UX. Backend = Seguridad. ¡Siempre valida en el servidor!
🚀 Evolución del Sistema
Nivel1: isAdmin boolean
↓
Nivel2:Múltiples roles(isAdmin, isEditor) ↓
Nivel3:Sistema de permisos(hasPermission) ↓
Nivel4:Backend+Base de datos +JWT
Este sistema te permite controlar exactamente qué puede hacer cada usuario en tu aplicación, mejorando tanto la seguridad como la experiencia de usuario. 🎯
English version branch & commitfollowing industry standards
- Implement isAdmin flag in user authentication state
- Add authorization checks for admin-only features
- Set up basic role verification in AuthContext
- Enable admin-specific UI elements and permissions"
Roles y permisos
.
La autenticación consiste en identificar personas, saber quiénes acceden a una aplicación. Mientras que la autorización consiste en saber qué permisos tiene cada persona que haya pasado por la autenticación.
.
Vamos a dar ciertos permisos a los usuarios para que puedan eliminar o editar un blog según el rol que tengan en la aplicación.
.
Lo primero que hacemos en el archivo auth.js es crear una lista de administradores. Al momento de loguear un usuario, revisaremos si el usuario es un administrador. Entonces, ademas del nombre de usuario tendremos también una nueva propiedad llamada isAdmin que indica si se trata de un usuario administrador.
.
.
Posteriormente, desde BlogPost vamos a utilizar permisos para eliminar un blogpost. En primer lugar, hay 2 maneras para que alguien pueda eliminar un blogpost:
.
Un administrador puede eliminar cualquier blogpost.
Los usuarios pueden eliminar sus propios blogposts.
.
Por lo tanto, si se cumple alguna de estas condiciones, guardaremos el resultado en la variable canDelete, lo que indicará si podemos renderizar un botón para eliminar un blogpost.
.
Ya no definiría si el usuario puede hacer tal acción dentro de la app basado en isAdmin.
Para ello generaria una estructura de roles donde se definan desde allí los permisos que aplican para cada uno de ellos, así basado en el rol que tenga cada usuario será las acciones que tienen permitidas.
yo lo hice asi
Yo lo realice de la siguiente manera, me guie de unos de los post de los companeros y fui desarrollando mi idea, si tienen alguna sugerencia por favor me lo pueden comentar abajo.
Como primera medida cree un archivo js para manejar los roles y la asignacion de estos en un objeto
Despues realice el manejo del estado en el archivo auth dependiendo del rol que tenga cada usuario
Me tomo bastante tiempo encontrar esta solucion pero me siento satisfecho de como lo maneje. Gracias
Mi solución
En mi experiencia diseñando interfaces de administración puedo decir que normalmente la información sobre el tipo de permisos que un usuario viene en un solo arreglo dentro de un json, no es recomendable ni practico crear listas separadas para administradores, autores o usuarios normales. Esto debido a que en cualquier tipo de iteración tendríamos que hacerlo sobre cada lista que tengamos, la cual va a variar según los tipos de permisos que nos soliciten afectando seriamente el performance de nuestra aplicación.
Siguiendo esta idea en auth.js creé una lista mixta en donde pueden venir 3 tipos de roles:
Ahora yo cambie la búsqueda que el profe propone por una función llamada assignRole la cual retorna el nombre del tipo de permiso que le hemos asignado (Se supone que esta información esta almacenada en una base de datos(DB) ). Como nuestra aplicación acepta cualquier nombre como autenticación en caso de no encontrarse en la DB, le asignamos permisos de solo lectura para evitar errores a futuro.
Ahora mi setUser actualiza pasando el username y rol independientemente de cual sea.
Nos pasamos a BlogPost.js para hacer la comprobación y mostrar un botón, para mostrarse debe cumplir con los siguientes puntos:
Que tengamos un usuario autenticado.
Que nuestro rol para eliminar sea "admin" o "author".
En caso de que tengamos permisos de author, nuestro usuario sea autor del post.
Nuestra comprobación queda algo larga, pero esto nos refuerza la seguridad, pues aunque nuestro usuario sea el autor del post debe tener permisos de edición habilitados.
Esta lógica nos abre la puerta para agregar un botón de edición el cual ni siquiera los "admins" pueden tener. Unicamente el autor del post puede tener este poder.
Esto nos abre la posibilidad de observar el tipo de usuario desde Profile.js y no andar haciendo console.logs para saber que tipo de usuario tenemos
Esta fue la mejor solucion que pude encontrar al reto
.
Inicialmente defini los valores de entrada. Con los diferentes array de roles, los junte en un unico array ya que me parecio la manera mas comoda de trabajar.
Luego, lo que hice fue crear una variable para saber quien es el usuario actual y verificar que exista en alguna de las listas.
.
Para ello utilice el metodo some para que recorriera el Array de arrays y dentro del mismo para cada Array busque aquel que con el metodo find contenga el usuario que se loggeo con el auth.
.
Asi pude sobreescribir la variable currentUser y con esta acceder usando la notacion de corchetes para poder usar una variable en el objeto skills que contiene los diferentes roles con su respectivo componente (en este caso estructura html) a renderizar deacuerdo a sus funciones
Finalmente use esa variable dentro de un div cualquiera en el componente BlogPost y de esta manera sea cual sea el rol se va a renderizar el componente asociado a este rol