No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Proteger el Acceso

9/20
Recursos

Aportes 2

Preguntas 4

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Cómo proteger nuestras rutas con CanActivate

// Desde la terminal creamos servicio de token y escapamos los tests

ng g s services/token --skip-tests

// Este servicio es el que va a persistir el token y va a escoger la estrategia adecuada para guardar el token

(*) Solo en ésta clase vamos a guardar el token en el localStorage, en la siguiente clase vamos a ver cómo guardar el token de forma más segura en cookies.
  • En el servicio de token, creamos los métodos para guardar, obtener y remover el token:
// token.service.ts

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class TokenService {

  constructor() { }

  saveToken(token: string) {
    localStorage.setItem('token', token);
  }

  getToken() {
    const token = localStorage.getItem('token');
    return token;
  }

  removeToken() {
    localStorage.removeItem('token');
  }
}
  • En nuestro servicio de auth, en el método login a través del operador tap de rxjs, recibimos la respuesta que es el token.
  • Importamos el servicio de token y le pasamos el token.
  • Para tipar la respuesta, creamos un auth.model.ts
// auth.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

import { environment } from '@environments/environment';
import { switchMap, tap } from 'rxjs';
import { TokenService } from './token.service';
import { ResponseLogin } from '@models/auth.model';

@Injectable({
  providedIn: 'root'
})
export class AuthService {

  apiUrl = environment.API_URL;

  constructor(
    private http: HttpClient,
    private tokenService: TokenService
  ) { }

  login(email: string, password: string) {
    return this.http.post<ResponseLogin>(`${this.apiUrl}/api/v1/auth/login`, {
      email,
      password
    })
    .pipe(
      tap(response => {
        this.tokenService.saveToken(response.access_token);
      })
    )
  }

  register(name: string, email: string, password: string) {
    return this.http.post(`${this.apiUrl}/api/v1/auth/register`, {
      name,
      email,
      password
    });
  }

  registerAndLogin(name: string, email: string, password: string) {
    return this.register(name, email, password)
    .pipe(
      switchMap(() => this.login(email, password))
    )
  }

  isAvailable(email: string) {
    return this.http.post<{ isAvailable: boolean }>(`${this.apiUrl}/api/v1/auth/is-available`, { email });
  }

  recovery(email: string) {
    return this.http.post(`${this.apiUrl}/api/v1/auth/recovery`, { email });
  }

  changePassword(token: string, newPassword: string) {
    return this.http.post(`${this.apiUrl}/api/v1/auth/change-password`, { token, newPassword })
  }
}
  • Creamos auth.model.ts para tipar la respuesta
// auth.model.ts

export interface ResponseLogin {
  access_token: string;
  refresh_token: string;
}
// Desde la terminal creamos un guardián para proteger nuestras rutas

ng g g guards/auth --skip-tests

// Seleccionamos el tipo CanActivate
  • Importamos el Router y el TokenService y mediante una validación le decimos que si no hay token me redirija al login, y para mayor seguridad también retornamos false, y si hay token retornamos true, por lo tanto me habilita las rutas del módulo de layout.
// auth.guard.ts

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';

import { TokenService } from '@services/token.service';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {

  constructor(
    private tokenService: TokenService,
    private router: Router
  ){}
  canActivate(): boolean {
    const token = this.tokenService.getToken();
    if (!token) {
      this.router.navigate(['/login']);
      return false;
    }
    return true
  }

}
  • Finalmente en el app.routing.module.ts, le decimos qué ruta queremos proteger si hay token, en este caso, en el path: ‘app’, añadimos el guardián que hemos creado.
// app.routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { AuthGuard } from '@guards/auth.guard';

const routes: Routes = [
  {
    path: '',
    loadChildren: () => import('./modules/auth/auth.module').then((m) => m.AuthModule),
  },
  {
    path: 'app',
    canActivate: [ AuthGuard ], // (*)
    loadChildren: () => import('./modules/layout/layout.module').then((m) => m.LayoutModule),
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

// (*) Protegiendo la ruta app, por herencia se protegen también las rutas hijas.
Para los que estén en Angular 17 o 18, solo tienen que importar el guard en la ruta del componente que quieran proteger. ![](https://app.codeimage.dev/45123cdf-4b5c-4538-bd6e-a16cd3626f66)```ts { path: 'boards', canActivate: [authGuard], // This is the guard loadComponent: () => import('./pages/boards/boards.component') }, { path: 'board', canActivate: [authGuard], // This is the guard loadComponent: () => import('./pages/board/board.component') } ```