Login con Angular y Auth0

ricardochl

Ricardo Chavarria

Posted on April 29, 2021

Login con Angular y Auth0

Auth0 es una solución flexible e integrada para agregar servicios de autenticación y autorización a sus aplicaciones.

¿Por qué usar Auth0?

Como mencione anteriormente desarrollar un sistema de autenticación desde cero puede ser bastante complejo. Auth0 es una plataforma de identidad como servicio (IDaaS) que permite centralizar y autenticación y autorización aplicaciones y brindar un sistema de seguridad seguro para sus usuarios y de esta manera reduciendo la complejidad para la seguridad de sus aplicaciones.

Auth0 brinda funciones de seguridad listas para ser usada en sus apps, con Auth0 podrá integrar en sus app inicio de sesión con correo electrónico y contraseña e inicio de sesión social con terceros como (Google, Facebook, Github, etc)

Contenido

  1. Crear Aplicación de Angular
  2. Configurar Angular App en Auth0.com
  3. Configuración del Auth0 Angular SDK
  4. Autenticar usuario
  5. Recuperar perfil del usuario
  6. Proteger rutas
  7. Conclusión

Iniciemos

1. Crear Aplicación de Angular

Lo primero que debemos hacer es crear la aplicación sobre la cual vamos a trabajar, ejecutamos el siguiente comando:



ng new angular-login-auth0 --routing --style=scss


Enter fullscreen mode Exit fullscreen mode

Una vez creada la app accedemos al directorio



cd angular-login-auth0


Enter fullscreen mode Exit fullscreen mode

2. Configurar Angular App en Auth0.com

Antes de iniciar a integrar el SDK de Auth0 para Angular, tenemos que crear una cuenta en auth0.com y registrar un aplicación de tipo SPA.

Vamos a ir a Auth0 puede ir a la opción de "Sign Up" y crear un cuenta , es super sencillo, también puede iniciar con acceso social con Google o Github.

Auth0 te solicitara la creación de un Auth0 Tenant que no es mas que un contenedor que utiliza Auth0 para para almacenar su configuración de servicio de identidad y sus usuarios de forma aislada.

Ningún otro usuario de Auth0 puede ver el tenant que haz creado ni tu puedes ver el de otros usuarios.

Una vez que ha configurado lo anterior, Auth0 lo lleva al panel de administración donde se podrán administrar y configurar todos los servicios de Auth0.

Alt Text

Crear Aplicación en Auth0

Tenemos que crear una aplicación en Auth0 la cual vamos a conectar con nuestra app de Angular que hemos creado previamente.

En el menu lateral izquierdo vamos, hacemos clic en la opción aplicaciones y luego en crear aplicación.

image

Para este ejemplo nombre la app como "Angular Login", se debe elegir la opción de Single Page Web Applications ya que estamos trabajando en una SPA con Angular.

Una vez crear la aplicación haga clic en la tab de settings aquí es donde esta toda la configuración de su aplicación especifica, incluyendo su ClientId y Client Secret.

Comunicación entre Angular y Auth0

Cuando se trabaja con Auth0, no es necesario que nosotros creemos un formulario de inicio de sesión, Auth0 ya ofrece una página de acceso universal. Este formulario reduce el riesgos a nivel de seguridad.

image

¿Cómo funciona el acceso universal?

Cuando un usuario intente iniciar sesión en la aplicación de Angular se redirigirá a Auth0 y les mostrar la página de inicio de sesión universal. Para que esa redirección se realice de forma segura, debe especificar en la configuración de la aplicación Auth0 las URL a las que Auth0 puede redirigir a los usuarios una vez que los autentica.

Primero configuremos a donde debe ser redirigido el usuario cuando haya iniciado sesión de manera correcta

En la opción "Allowed Callback URLs" colocamos lo siguiente:



http://localhost:4200


Enter fullscreen mode Exit fullscreen mode

Luego hay que configurar también a dónde debe ser redirigido el usuario cuando haya cerrado la sesión de manera correcta.

En la opción "Allowed Logout URLs" colocamos lo siguiente:



http://localhost:4200


Enter fullscreen mode Exit fullscreen mode

Auth0 solo podrá redirigir al usuario a las URL que haya colocado anteriormente como origenes permitidos.

Orígenes web permitidos

Cuando se utiliza el Auth0 Angular SDK, la aplicación de Angular realiza solicitudes bajo el capó a la API de Auth0, esto para manejar las solicitudes de autenticación, es por ello que debe agregar la URL de origen de su aplicación angular para evitar problemas de intercambio de recursos de origen cruzado (CORS).



http://localhost:4200


Enter fullscreen mode Exit fullscreen mode

Para finalizar hacemos clic en "Guardar Cambios".

Variables de configuración

Para permitir que la Aplicación de Angular se comunique con Auth0 se necesitan los valores de ID de cliente y dominio Auth0. Estos valores están en la "pestaña" de settings

En su aplicación de Angular cree un archivo llamado auth_config.json (A nivel del proyecto)

Este archivo debe contener la siguiente información



{
  "domain": "YOUR_AUTH0_DOMAIN",
  "clientId": "YOUR_AUTH0_CLIENT_ID"
}


Enter fullscreen mode Exit fullscreen mode

Estas variables permiten que su aplicación Angular se identifique como una parte autorizada para interactuar con el servidor de autenticación Auth0 para llevar a cabo el proceso de autenticación.

Ahora debemos usar estas variables en la aplicación Angular para eso vamos a utilizar el environment de Angular.

El environment debería verse así:



import { domain, clientId } from '../../auth_config.json';

export const environment = {
  production: false,
  auth: {
    domain,
    clientId,
    redirectUri: window.location.origin,
  },
};


Enter fullscreen mode Exit fullscreen mode

Para poder importar archivos JSON dentro de Angular, tenemos que establecer "resolveJsonModule": true en nuestro tsconfig.json

Con estos pasos realizados se ha completado la configuración de un servicio de autenticación que esta listo para ser consumido por la aplicación de Angular

3. Configuración del Auth0 Angular SDK

Ejecute el siguiente comando:



ng add @auth0/auth0-angular


Enter fullscreen mode Exit fullscreen mode

El nuevo Auth0 Angular SDK brinda varios métodos, variables y tipos que ayudan a integrar Auth0 con una aplicación de Angular de una manera más sencilla, este SDK incluye un módulo de autenticación y un servicio.

Implementar módulo de autenticación

Importar AuthModule y environment en el AppModule y luego inicializarlo en los imports.



import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

import { AuthModule } from '@auth0/auth0-angular';
import { environment as env } from '../environments/environment';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    AuthModule.forRoot({
      ...env.auth,
    }),
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }




Enter fullscreen mode Exit fullscreen mode

4. Autenticar usuario

Auth0 Angular SDK proporciona métodos para activar eventos de autenticación dentro de los componentes Angular: inicio de sesión, cierre de sesión y registro etc.

Creando componentes

Vamos a necesitar algunos componentes de Angular para permitirle a usuario iniciar y cerrar la sesión

  1. Pagina de inicio
  2. Botón para iniciar sesión
  3. Botón para cerrar la sesión
  4. Component para manejar que Botón mostrar si el de inicio o cierre de sesión.

Con los siguientes comando los podemos crear



ng g c pages/home
ng g c components/login-button
ng g c components/logout-button
ng g c components/authentication-button


Enter fullscreen mode Exit fullscreen mode

El component home únicamente lo utilizaremos para mostrar los botones según sea el caso

Nuestro archivo de rutas debería verse así:



import { HomeComponent } from './pages/home/home.component';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  {
    path:'',
    component: HomeComponent
  }
];

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



Enter fullscreen mode Exit fullscreen mode

Ahora el login-button.component.ts



import { Component, OnInit } from '@angular/core';
import { AuthService } from '@auth0/auth0-angular';

@Component({
  selector: 'app-login-button',
  templateUrl: './login-button.component.html',
  styleUrls: ['./login-button.component.scss']
})
export class LoginButtonComponent implements OnInit {

  constructor(public auth: AuthService) {}


  ngOnInit(): void {
  }

  loginWithRedirect(): void {
    this.auth.loginWithRedirect();
  }

}


Enter fullscreen mode Exit fullscreen mode

Y el html



<button (click)="loginWithRedirect()">
  Log in
</button>


Enter fullscreen mode Exit fullscreen mode

Ahora seguimos con el botón para cerrar la sesión

logout-button.component.ts



import { DOCUMENT } from '@angular/common';
import { Component, Inject, OnInit } from '@angular/core';
import { AuthService } from '@auth0/auth0-angular';

@Component({
  selector: 'app-logout-button',
  templateUrl: './logout-button.component.html',
  styleUrls: ['./logout-button.component.scss']
})
export class LogoutButtonComponent implements OnInit {

  constructor(
    public auth: AuthService,
    @Inject(DOCUMENT) private doc: Document
  ) { }

  ngOnInit(): void {
  }

  logout(): void {
    this.auth.logout({ returnTo: this.doc.location.origin });
  }

}


Enter fullscreen mode Exit fullscreen mode

Y el html



<button (click)="logout()">
  Log out
</button>


Enter fullscreen mode Exit fullscreen mode

Se agrega la propiedad returnTo al objeto de configuración para especificar la URL a la que Auth0 debe redirigir a sus usuarios después de cerrar la sesión. En este momento, está trabajando localmente y las "URL de cierre de sesión permitidas" de su aplicación Auth0 apuntan a http://localhost:4200, estas url las configuramos previamente.

Sin embargo, si tuviera que implementar su aplicación Angular en producción , debe agregar la URL de cierre de sesión de producción a la lista "URL de cierre de sesión permitidas.

Otro punto importante es que los componentes de Angular no tiene acceso al objeto document, pero se puede inyectar con el @Inject(DOCUMENT)

Luego tenemos que envolver LoginButtonComponent y LogoutButtonComponent en un solo componente que tiene lógica para decidir qué botón renderizar dependiendo del estado de autenticación del usuario.

authentication-button.component.ts



import { Component, OnInit } from '@angular/core';
import { AuthService } from '@auth0/auth0-angular';

@Component({
  selector: 'app-authentication-button',
  templateUrl: './authentication-button.component.html',
  styleUrls: ['./authentication-button.component.scss']
})
export class AuthenticationButtonComponent implements OnInit {

  constructor(public auth: AuthService) {}

  ngOnInit(): void {
  }

}


Enter fullscreen mode Exit fullscreen mode

Y su html



<app-login-button *ngIf="(auth.isAuthenticated$ | async) === false">
</app-login-button>

<app-logout-button *ngIf="auth.isAuthenticated$ | async">
</app-logout-button>


Enter fullscreen mode Exit fullscreen mode

Auth0 expone un observable "isAuthenticated$" que emite un valor booleano. Cuando el usuario se ha autenticado el valor es true y cuando no es false.

Y por último debemos agregar el app-authentication-button a nuestro home-component



<app-authentication-button></app-authentication-button>


Enter fullscreen mode Exit fullscreen mode

Si haz llegado hasta aquí tu implementación básica esta lista y ya puedes correr la aplicación de Angular y probarla.



ng serve


Enter fullscreen mode Exit fullscreen mode

Cuando hagas clic en el botón "Log In" serás redirigido a la página de acceso universal de Auth0

image

La primera vez que inicies te solicitara que autorices la aplicación.

image

Si iniciaste sesión correctamente deberías de ver el botón de cierre de sesión.

image

Cuando termina de iniciar sesión y Auth0 lo redirige a su aplicación Angular, la interfaz de usuario tiene una pantalla en blanco parpadeando.

La interfaz de usuario parpadea porque su aplicación Angular está cargando sus servicios. Mientras se carga, Angular no sabe si Auth0 ya ha autenticado al usuario. Su aplicación conocerá el estado de autenticación del usuario después de que se cargue Auth0 Angular SDK.

Para arreglar eso vamos a validar la sesión en el AppComponent utilizando el observable "isLoading$" que provee el AuthService.

El app.component.ts quedaría así:



import { Component } from '@angular/core';
import { AuthService } from '@auth0/auth0-angular';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'angular-login-auth0';

  constructor(public auth: AuthService) {}
}


Enter fullscreen mode Exit fullscreen mode

Y el html



<div *ngIf="auth.isLoading$ | async; else loaded">
  <p>Cargando...</p>
</div>


<ng-template #loaded>
  <router-outlet></router-outlet>
</ng-template>


Enter fullscreen mode Exit fullscreen mode

Aquí seria adecuado implementar un componente de "carga" mientras se cargan los servicios.

5. Recuperar el perfil del usuario

Después de que el usuario inicia sesión correctamente, Auth0 envía un token de identificación a su aplicación Angular.

Auth0 utiliza tokens de identificación en la autenticación basada en token para almacenar en caché la información del perfil de usuario y proporcionarla a una aplicación cliente.

Puede utilizar los datos del token de ID para personalizar la interfaz de usuario de su aplicación de Angular. El Auth0 Angular SDK decodifica el token de ID y emite sus datos a través del Observable. Parte de la información del token de ID incluye el nombre, el nickname, la imagen y el correo electrónico del usuario que inició sesión.

Creemos un componente para el perfil



ng g c pages/profile


Enter fullscreen mode Exit fullscreen mode

El profile.component.ts quedaría de la siguiente manera



 import { Component, OnInit } from '@angular/core';
import { AuthService } from '@auth0/auth0-angular';

@Component({
  selector: 'app-profile',
  templateUrl: './profile.component.html',
  styleUrls: ['./profile.component.scss']
})
export class ProfileComponent implements OnInit {

  public profileJson: string = "";
  constructor(public auth: AuthService) {

  }

  ngOnInit(): void {
    this.auth.user$
    .subscribe((profile) => {
      this.profileJson = JSON.stringify(profile, null, 2)
    });
  }

}


Enter fullscreen mode Exit fullscreen mode

Y en el html



<pre>{{profileJson}}</pre>


Enter fullscreen mode Exit fullscreen mode

Y ahora agregamos una nueva ruta en el app-routing.module.ts



import { ProfileComponent } from './pages/profile/profile.component';
import { HomeComponent } from './pages/home/home.component';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  {
    path:'',
    component: HomeComponent
  },
  {
    path:'profile',
    component: ProfileComponent
  }
];

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


Enter fullscreen mode Exit fullscreen mode

Cuando naveguemos a la ruta http://localhost:4200/profile
podremos ver la información del usuario.

6. Protección de rutas

Auth0 Angular SDK expone un AuthGuard que puede usar para proteger rutas.

Para requerir que el usuario inicie sesión es tan fácil como agregar la propiedad canActivate a la ruta que queremos proteger y agregar el AuthGuard

Importemos el AuthGuard en el app-routing.module.ts



import { ProfileComponent } from './pages/profile/profile.component';
import { HomeComponent } from './pages/home/home.component';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from '@auth0/auth0-angular';

const routes: Routes = [
  {
    path:'',
    component: HomeComponent
  },
  {
    path:'profile',
    component: ProfileComponent,
    canActivate: [AuthGuard],
  }
];

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



Enter fullscreen mode Exit fullscreen mode

Extra

Si fue curioso pudo notar que cuando ha iniciado sesión con acceso social (Google) y refresca la página la sesión se pierde esto se debe a que las claves de desarrollador Auth0 se están utilizando en lugar de sus propias credenciales para una conexión social.

En la sección de conexiones sociales del panel de Auth0 podrá configurar sus propias credenciales para resolver este problema. Las claves de desarrollo de Auth0 están diseñadas para pruebas y no se recomiendan para entornos de producción.

Otra solución es usar Refresh Token Rotation y establecer cacheLocation"localstorage" al inicializar el Auth0 Angular SDK.



    AuthModule.forRoot({
      ...env.auth,
      cacheLocation:'localstorage'
    })


Enter fullscreen mode Exit fullscreen mode

El repositorio con el código de este tutorial lo podrá encontrar aquí

7. Conclusión

Hemos implementado la autenticación de usuario en Angular, obtener la información del usuario que inicio sesión y también controlar a que rutas pueden acceder los usuarios.

Auth0 es una poderosa solución que nos permite agregar los servicios de Autenticación a nuestras aplicaciones de una manera sencilla haciendo la mayor parte del trabajo por nosotros.

Déjame saber en los comentarios que te pareció este tutorial.

Gracias por leer está publicación.

💖 💪 🙅 🚩
ricardochl
Ricardo Chavarria

Posted on April 29, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Login con Angular y Auth0
angular Login con Angular y Auth0

April 29, 2021