Comando para crear decorators:
nest g d auth/decorators/nombre --flat
Introducción
Cómo autenticar usuarios con NestJS
Instalación de PlatziStore con MongoDB
Instalación de PlatziStore con TypeORM
Protección con guardianes
Introducción a Guards
Usando un decorador
Guard con variables de ambiente
Autenticación con Passport
Hashing de contraseñas en TypeORM
Hashing de contraseñas en MongoDB
Autenticación con Passport.js
Ruta de login
Autenticación con JSON Web Tokens
Conectando Passport con JWT
Secret desde variables de entorno
Implementando JWT Guard
Extendiendo JWT Guard
Control de roles en NestJS
Obteniendo órdenes del perfil
Deployment
Configurando Mongo Atlas
Deploy de Mongo en Heroku
Configuración de PostgreSQL en Heroku
Deploy de Postgres en Heroku
Corriendo migraciones de Postgres en Heroku
Próximos pasos
¿Quieres más cursos de NestJS?
Crea una cuenta o inicia sesión
¡Continúa aprendiendo sin ningún costo! Únete y comienza a potenciar tu carrera
No se trata de lo que quieres comprar, sino de quién quieres ser. Aprovecha el precio especial.
Antes: $249
Paga en 4 cuotas sin intereses
Termina en:
Nicolas Molina
Aportes 3
Preguntas 0
Comando para crear decorators:
nest g d auth/decorators/nombre --flat
Esto aplica para ambos proyectos
Para proteger todo un controlador en lugar de solo una ruta en especifico, podemos asignarle el guard al controlador.
// src\app.controller.ts
...
@UseGuards(ApiKeyGuard)
@Controller()
...
Podemos crear un decorador para volver publico alguna ruta protegida.
Para ello, modificamos nuestro controlador
...
const isPublic = this.reflector.get('isPublic', context.getHandler());
if (isPublic) {
return true;
}
const request = context.switchToHttp().getRequest<Request>();
const authHeader = request.header('Auth');
return authHeader === '1234';
}
Creamos un decorador que nos facilite el envió de metadata a la request
// src\auth\decorators\public.decortator.ts
import { SetMetadata } from '@nestjs/common'
export const IS_PUBLIC_KEY = 'isPublic';
export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);
Ahora podemos declara como publico alguna ruta protegida
@Public() // usando el decorador
@Get('nuevo')
newEndpoint() {
return 'yo soy nuevo';
}
Una funcionalidad muy útil a la hora de trabajar con nuestros guardianes es que en vez de nosotros tener que programar cual es la condición que debe cumplir el contexto que necesitamos, lo que podemos hacer es usar decoradores que validen esta información por nosotros:
Para nuestro ejemplo, lo que vamos a hacer es que vamos a proteger todos los Endpoints de nuestro controlador:
**src\app.controller.ts**
:// importamos el "SetMetadata"
import { Controller, Get, SetMetadata } from '@nestjs/common';
/* para que todos los enpoints de el controlador esten protegidos colocamos el
decodador arriba del controlador */
// todos los endpoints estarán protegidos
@UseGuards(ApiKeyGuard)
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
// SetMetadata nos permite enviar metadatos que podemos recibir en el contexto del guardian
@SetMetadata('isPublic', true)
getHello(): string {
return this.appService.getHello();
}
// ...
}
La forma en la que vamos a utilizar este metadato que estamos enviando al contexto del guardián, en este caso va a ser para que con esa configuración protejamos todos los Endpoints del controlador, menos, el Endpoint que tenga el metadato **‘isPiblic’**
en **true**
.
Veamos como:
**src/auth/guards/api-key.guard.ts**
:// importamos al reflector
import { Reflector } from '@nestjs/core';
@Injectable()
export class ApiKeyGuard implements CanActivate {
// debemos inyectar el reflector en nuestro guardian
constructor(private reflector: Reflector) {}
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
// con un método del reflector, nos traemos la metadata de "isPublic"
// con el contexto, le indicamos que recibimos un manejador
const isPublic = this.reflector.get('isPublic', context.getHandler());
// el parámetro tiene la propiedad "isPublic" como verdadera?
if (isPublic) {
// no hacemos validación
return true;
}
// si en la metadata, indica que no es publico, hacemos la validación
// ...
}
}
De esta forma, si un parámetro tiene en sus metadatos que es publico, no se realizará la validación, pero si en sus metadatos no lo tienen, re debe realizar la validación.
El crear nuestros propios decoradores con la metadata que necesitamos es útil para que no caigamos en errores de Typos, y también tanto para agilizar la experiencia de desarrollo, como hacer el código mucho más verboso.
Para realizar esto, vamos a crear este decorador de la siguiente forma:
**src\auth\decorators\public.decortator.ts**
:import { SetMetadata } from '@nestjs/common';
// instanciamos como queremos que se va a llamar la metadata
// lo exportamos por si lo queremos reutilizar en otro decodador y en el guardian
export const IS_PUBLIC_KEY = 'isPublic';
// creamos el decorador primero como una función flecha
// va a ser igual al decodador "SetMetadata", pero con el metadato "isPublic" como "true"
export const IsPublic = () => SetMetadata(IS_PUBLIC_KEY, true);
Y ahora solo tendríamos que usar este decorador de la siguiente forma:
**src\app.controller.ts**
:// importamos nuestro decoador
import { IsPublic } from './auth/decorators/public.decorator';
@UseGuards(ApiKeyGuard)
@Controller()
export class AppController {
@Get()
// lo usamos en el parámetro deseado
@IsPublic()
getHello(): string {
return this.appService.getHello();
}
}
Y listo, ahora tenemos un decorador un poco más flexible y personalizado.
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?