Menu

Clase 3 - Autenticación de Usuarios

angulares6typescript - January 15, 2018 por Carlos Rojas | Edita este Post.
Angular CLI1.6.1Angular5.0angularfire25.0.0-rc.4

La autenticación de usuarios es uno de las tareas mas comunes por parte de los desarrolladores actualmente. Existen protocolos como JWT y OAuth que definen una manera segura de compartir informacion entre un servidor y un Cliente Web.

También, existen servicios como Firebase o auth0 que manejan estos protocolos por ti y los colocan facilmente disponibles para los desarrolladores Frontend. En esta ocasion vamos a utilizar Firebase.

Instalando primeNG.

primeNG es una colección de componentes para Angular similar a Angular Material.

npm install primeng --save

Luego debemos importar los modulos en app.module.ts

import {InputTextModule} from 'primeng/primeng';
import {ButtonModule} from 'primeng/primeng';
import {DialogModule} from 'primeng/primeng';

import { FormsModule, ReactiveFormsModule } from "@angular/forms";

...


@NgModule({
  declarations: [ ... ],
  imports: [
    ...
    InputTextModule,
    ButtonModule,
    FormsModule,
    DialogModule
    ...
  ],
  entryComponents: [ ... ],
  providers: [ ... ]
})

Con esto ya deberiamos poder usar esos componentes en nuestra App. Mas info de primeNG

Instalando Firebase.

Luego de crear la cuenta en Firebase, debemos implementar la librería para empezar a usar cualquier servicio de Firebase y AngularFire2 para facilitar nuestra vida usando Observables. Así que vamos a nuestra terminal y ejecutamos:

npm install angularfire2 firebase promise-polyfill --save

Ahora Debes crear el objeto firebaseConfig para tu app. Esto lo debemos hacer en el archivo app.module.ts y reemplazar la información de la app con la que obtienes de tu proyecto en Firebase.

Define los objetos:


export const firebaseConfig = {
  apiKey: "xxxxxxxxxx",
  authDomain: "your-domain-name.firebaseapp.com",
  databaseURL: "https://your-domain-name.firebaseio.com",
  storageBucket: "your-domain-name.appspot.com",
  messagingSenderId: '<your-messaging-sender-id>'
};

también necesitamos agregar los modulos de AngularFire2 dentro de NgModule.


import { AngularFireModule } from 'angularfire2';
import { AngularFireAuthModule } from 'angularfire2/auth';
...


@NgModule({
  declarations: [ ... ],
  imports: [
    ...
    IonicModule.forRoot(MyApp),
    AngularFireModule.initializeApp(firebaseConfig),
    AngularFireAuthModule
    ...
  ],
  entryComponents: [ ... ],
  providers: [ ... ]
})

Ok, hasta aqui deberiamos tener todo conectado.

Creando componentes a utilizar.

Debido a que voy a tener 4 vistas en mi app ( Login, Registro, Recuperación y Home ) es buena idea crear un componente para cada una y tener un Servicio el cual me maneje información que voy a compartir entre todas.

$ng generate component login
$ng generate component register
$ng generate component forgot
$ng generate component home

y voy a crear el servicio.

$ng generate service user

basicamente en este servicio manejare todos los temas de autenticación en mi App y lo reutilizare en mis distintos componentes. En Angular CLI te creara el servicio pero debes recordar agregarlo como proveedor en tu NgModule.


import { UserService } from "./user.service";
...


@NgModule({
  declarations: [ ... ],
  imports: [
    ...
  ],
  entryComponents: [ ... ],
  providers: [
    UserService
  ],
  ...
})

Agregando enrutamiento.

Como sabes tenemos dividida nuestras vistas en Componentes y debemos mostrarle estas a nuestros usuarios en el momento que el usuario haga una acción. Para esto nos ayudaremos del enrutador de Angular. No voy a tocar muy a fondo esto solo debemos entender que a traves de la URL le voy a decir a Angular que active/desactive un Componente.


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

const appRoutes: Routes = [
  { path: 'login', component: LoginComponent },
  { path: 'register', component: RegisterComponent },
  { path: 'forgot', component: ForgotComponent },
  { path: '**', component: LoginComponent }
];

@NgModule({
  declarations: [ ... ],
  imports: [
    ...
    RouterModule.forRoot(appRoutes)
  ],
  entryComponents: [ ... ],
  providers: [
    ...
  ],
  ...
})

Adicionalmente, debemos ir a app.component.html y cambiar lo que tengas en la plantilla con:


<router-outlet></router-outlet>

Esto lo que le dice a angular es que reemplace router-outlet por lo que diga el enrutador.

Ok, con esto debemos tener el router funcionando.

Finalizando nuestra App.

Ahora vamos a completar nuestro codigo. Lo primero es integrar Firebase en el Servicio en el archivo user.service.ts


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

import { AngularFireAuth } from 'angularfire2/auth';
import * as firebase from 'firebase/app';

import { Observable } from 'rxjs/Observable';

@Injectable()
export class UserService {
  user: Observable<firebase.User>;

  constructor(private firebaseAuth: AngularFireAuth) {
    this.user = firebaseAuth.authState;
  }

  signup(email: string, password: string):any {
    return this.firebaseAuth
      .auth
      .createUserWithEmailAndPassword(email, password);    
  }

  login(email: string, password: string):any {
    return this.firebaseAuth
      .auth
      .signInWithEmailAndPassword(email, password);
  }

  forgot(email:string):any{
    return this.firebaseAuth
    .auth
    .sendPasswordResetEmail(email);
  }

  logout() {
    this.firebaseAuth
      .auth
      .signOut();
  }
}

Luego el login. en /login

login.component.html


<div class="ui-g">
    <div class="ui-g-4">
    </div>
    <div class="ui-g-4">
      <h1>NG-Classroom</h1>  
        <span class="ui-float-label">
            <input id="float-input" [(ngModel)]="email" type="text" size="30" pInputText> 
            <label for="float-input">email</label>
        </span>
      <hr/>
      <span class="ui-float-label">
          <input id="float-pass" [(ngModel)]="password" type="text" size="30" pInputText> 
          <label for="float-pass">Contraseña</label>
      </span>
      <hr/>
      <button pButton type="button" label="Ingresar" (click)="login()"></button>
      <hr/>
      <div><a routerLink="/register">Registrarse</a>&nbsp;|&nbsp;<a routerLink="/forgot">Olvido contraseña</a></div>
    </div>
      
    <div class="ui-g-4"></div>
  </div>
  <p-dialog header="Message" [(visible)]="display">
      
  </p-dialog>
  
  

login.component.ts


import { Component, OnInit } from '@angular/core';
import { UserService } from '../user.service';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
  
  email: string;
  password: string;
  msg: string;
  display:boolean = false;

  constructor(public authService: UserService) {}

  ngOnInit() {
  }

  login() {
    let user = this.authService.login(this.email, this.password);
    user.
    then(value => {
      this.msg = value;
      this.display = true;
    })
    .catch(err => {
      console.log('Algo fue mal:',err.message);
      this.msg = err.message;
      this.display = true;
    });
    this.email = '';
    this.password = '';    
  }

}

Luego el registro. en /register

register.component.html

<div class="ui-g">
    <div class="ui-g-4">
    </div>
    <div class="ui-g-4">
      <h1>NG-Classroom</h1>  
        <span class="ui-float-label">
            <input id="float-input" [(ngModel)]="email" type="text" size="30" pInputText> 
            <label for="float-input">email</label>
        </span>
      <hr/>
      <span class="ui-float-label">
          <input id="float-pass" type="password" [(ngModel)]="password" size="30" pInputText> 
          <label for="float-pass">Contraseña</label>
      </span>
      <hr/>
      <span class="ui-float-label">
          <input id="float-pass" type="password" [(ngModel)]="password2" size="30" pInputText> 
          <label for="float-pass">Repetir Contraseña</label>
      </span>
      <hr/>
      <button pButton type="button" label="Registrar" (click)="signUp()"></button>
      <hr/>
      <div><a routerLink="/login">Ir al Login</a></div>
    </div>
      
    <div class="ui-g-4"></div>
  </div>
  <p-dialog header="Message" [(visible)]="display">
        
  </p-dialog>

register.component.ts


import { Component, OnInit } from '@angular/core';
import { UserService } from '../user.service';

@Component({
  selector: 'app-register',
  templateUrl: './register.component.html',
  styleUrls: ['./register.component.css']
})
export class RegisterComponent implements OnInit {
  email: string ='';
  password: string ='';
  password2: string ='';
  msg: string = '';
  display: boolean = false;

  constructor(public authService: UserService) { }

  ngOnInit() {
  }
  
  signUp() {
    if(this.password === this.password2){ 
      let user = this.authService.signup(this.email, this.password);
      user.
      then(value => {
        this.msg = value;
        this.display = true;
      })
      .catch(err => {
        console.log('Algo fue mal:',err.message);
        this.msg = err.message;
        this.display = true;
      });
    }
    else{
      this.msg="Las contraseñas deben coincidir";
      this.display = true;
    }
    this.email = '';
    this.password = '';
    this.password2 = '';    
  }

}

Luego la recuperacion. en /forgot

forgot.component.html


<div class="ui-g">
    <div class="ui-g-4">
    </div>
    <div class="ui-g-4">
      <h1>NG-Classroom</h1>  
        <span class="ui-float-label">
            <input id="float-input" type="text" size="30" [(ngModel)]="email" pInputText> 
            <label for="float-input">email</label>
        </span>
      <hr/>
      <button pButton type="button" label="Recuperar" (click)="forgot()"></button>
      <hr/>
      <div><a routerLink="/login">Ir al Login</a></div>
    </div>
      
    <div class="ui-g-4"></div>
  </div>
  <p-dialog header="Message" [(visible)]="display">
      
  </p-dialog>

forgot.component.ts

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

import { UserService } from "../user.service";

@Component({
  selector: 'app-forgot',
  templateUrl: './forgot.component.html',
  styleUrls: ['./forgot.component.css']
})
export class ForgotComponent implements OnInit {
  email:string='';
  msg:string='';
  display:boolean=false;

  constructor(public authService:UserService) { }

  ngOnInit() {
  }

  forgot(){
    let user = this.authService.forgot(this.email);
    user.
    then(value => {
      this.msg = value;
      this.display = true;
    })
    .catch(err => {
      console.log('Algo fue mal:',err.message);
      this.msg = err.message;
      this.display = true;
    });
  }

}

Ok, con esto ya debemos tener funcionando nuestro sistema de autenticación. Si quieres ir un poco mas alla intenta agregar un sistema de validación de los formularios.

Bueno esperamos que esta clase te haya sido de utilidad y nos vemos en una proxima.

Ver código

¡Compártelo!