Header Ads Widget

Ticker

6/recent/ticker-posts

Tutorial de autenticación Ionic 5 / Angular JWT: servidor Node & Express.js

 Ionic 5 es la última versión de Ionic. En este tutorial, aprenderemos a usar Ionic 5 y Angular 7 para crear un módulo de inicio de sesión y registro para autenticar usuarios. Aprenderemos sobre el uso de módulos, servicios, formularios (vía FormsModule) y HTTP (vía HttpClient) de Angular, entre otras características.

Aprenderemos a usar HttpClientpara enviar solicitudes POST a un servidor de autenticación back-end creado con Node y Express.js y el BehaviorSubjecttipo de RxJS Observable para rastrear el estado de autenticación.

Aprenderemos cómo usar el módulo de almacenamiento iónico para conservar la información JWT devuelta desde nuestro servidor Express.js, como el token de acceso y la fecha de vencimiento.

Antes de continuar, debe asegurarse de tener Node.js y NPM instalados en su máquina de desarrollo. Debería poder instalarlos descargando los binarios para su sistema desde el sitio web oficial .

Lea también Building Chat App Frontend UI con JWT Auth usando Ionic 5 / Angular 9

¡Ahora, comencemos!

Configuración de Ionic CLI 5

Nuestro primer paso es instalar Ionic CLI 5. Abra su terminal y ejecute este comando:

$ npm install -g ionic

Esto instalará el paquete iónico globalmente en su sistema. Si obtiene algún error de permiso, simplemente utilícelo sudoantes de su comando. Si está en Windows, use un indicador de CMD con acceso de administrador.

Creación de un proyecto Ionic 5

Procedamos ahora creando un proyecto Ionic 5. Regrese a su terminal y ejecute el siguiente comando:

$ ionic start ionic-auth-demo blank --type=angular   

Usamos --typepara especificar el tipo de marco que queremos usar con Ionic. A partir de la v4, Ionic es solo una biblioteca de interfaz de usuario móvil que se puede usar sobre Angular, Vue y React o simplemente JavaScript simple para crear aplicaciones móviles híbridas o aplicaciones web progresivas.

Usamos la blankplantilla para generar un proyecto que viene con una página llamada inicio.

La CLI hará un par de preguntas, por ejemplo, si desea instalar Cordova y si desea instalar el SDK de Ionic Appflow gratuito y conectar su aplicación. Responda esas preguntas como prefiera porque esto no afectará nuestros próximos pasos en este tutorial.

Espere a que se instalen las dependencias, luego navegue en la carpeta raíz de su proyecto y sirva su aplicación usando estos comandos:

$ cd ionic-auth-demo 
$ ionic serve

Puede acceder a su aplicación móvil utilizando su navegador web desde la localhost:8100dirección.

Creando un Módulo Angular

Los módulos se utilizan para organizar el código de su aplicación. Para la función de autenticación en nuestra aplicación, crearemos un módulo que encapsula el servicio y las páginas que manejan la autenticación de usuarios. En su terminal, ejecute:

$ ionic generate module auth

El src/app/auth/auth.module.tsarchivo se creará con el código básico de un módulo:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

@NgModule({
  declarations: [],
  imports: [
    CommonModule
  ]
})
export class AuthModule { }

Nuestro authmódulo sólo importa el CommonModulecual es construido en un módulo angular que las exportaciones de todas las directivas y los tubos angulares básicas, tales como [NgIf](https://angular.io/api/common/NgIf)[NgForOf](https://angular.io/api/common/NgForOf)[DecimalPipe](https://angular.io/api/common/DecimalPipe), y así sucesivamente.

Debe importar el authmódulo en el módulo de la aplicación raíz de nuestra aplicación Ionic 5. Abra el src/app/app.module.tsarchivo e impórtelo, AuthModuleluego agréguelo a la importsmatriz:

import { AuthModule } from  './auth/auth.module';

@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule,
    AuthModule
  ],
  providers: [
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

Vamos a importar otros módulos que son necesarios para nuestra aplicación, como HttpClientpara enviar solicitudes HTTP, FormsModulepara trabajar con formularios y el módulo Ionic Storage para trabajar con almacenamiento local en aplicaciones Ionic.

Importando HttpClient

HttpClientes el cliente http oficial de Angular, por lo que debemos importarlo en nuestro proyecto Ionic / Angular. Abra el src/app/auth/auth.module.tsarchivo e importe HttpClientModule:


import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    HttpClientModule
  ]
})
export class AuthModule { }

Eso es todo lo que necesitamos importar HttpClienten nuestro módulo de autenticación.

Configurar formularios

Angular proporciona potentes API para trabajar con formularios, ya sea a través de formularios basados ​​en plantillas o formularios reactivos. En este tutorial, usaremos formularios basados ​​en plantillas, por lo que necesitamos importar FormsModuleen nuestro módulo de aplicación principal. En el mismo src/app/auth/auth.module.tsarchivo:


import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { FormsModule } from '@angular/forms';

@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    HttpClientModule,
    FormsModule
  ]
})
export class AuthModule { }

Configuración del módulo de almacenamiento iónico

El equipo de Ionic proporciona el módulo Ionic Storage que se puede usar para trabajar con el almacenamiento local del navegador en dispositivos móviles, pero antes de que podamos usarlo en nuestra aplicación, debemos instalarlo desde npm e importarlo en nuestro módulo de autenticación. Regrese a su terminal y ejecute el siguiente comando:

$ npm install --save @ionic/storage

A partir de este escrito, ionic/storage v2.2.0se instalará en su proyecto.

A continuación, incluya IonicStorageModule.forRoot()en la importsmatriz:


import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { FormsModule } from '@angular/forms';

import { IonicStorageModule } from '@ionic/storage';

@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    HttpClientModule,
    FormsModule,
    IonicStorageModule.forRoot()
  ]
})
export class AuthModule { }

Creación del servicio de autenticación angular

Después de configurar los módulos necesarios para nuestro proyecto, ahora creemos un servicio de autenticación que encapsule la comunicación con el servidor Express a través de HttpClientEn su terminal, ejecute:

$ ionic generate interface auth/user

Esto generará una interfaz de usuario en el src/app/auth/user.tsarchivo. Abra el archivo y actualícelo en consecuencia:

export interface User {
    id: number;
    name: string;
    email: string;
    password: string;
}

Nota : Prefijamos el nombre de la interfaz auth/para indicarle a la CLI que la genere dentro del authmódulo.

Además, debe generar una interfaz para la respuesta del servidor:

$ ionic generate interface auth/auth-response

Abra el src/app/auth/auth-response.tsarchivo y actualícelo en consecuencia:

export interface AuthResponse {
    user: {
        id: number,
        name: string,
        email: string,
        access_token: string,
        expires_in: number
    }
}

Esto corresponde a la respuesta que se devolverá desde el servidor de autenticación que crearemos en la siguiente sección con Node y Express.js.

Luego, genere el servicio usando:

$ ionic generate service auth/auth

Se generarán dos archivos src/app/auth/auth.service.tssrc/app/auth/auth.service.spec.ts(pruebas).

Nota : Prefijamos el nombre del servicio auth/para indicarle a la CLI que lo genere dentro del authmódulo.

Abra el src/app/auth/auth.service.tsarchivo y actualícelo siguiendo estos pasos. Primero agregue las importaciones necesarias:

import { Injectable } from  '@angular/core';
import { HttpClient } from  '@angular/common/http';
import { tap } from  'rxjs/operators';
import { Observable, BehaviorSubject } from  'rxjs';

import { Storage } from  '@ionic/storage';
import { User } from  './user';
import { AuthResponse } from  './auth-response';

Importamos:

  • HttpClient para enviar una solicitud POST al servidor Express que maneja la autenticación,
  • El tap()operador para realizar efectos secundarios al suscribirse a los observables devueltos por los HttpClientmétodos,
  • El Storagemódulo para conservar el token de acceso y la fecha de vencimiento en el almacenamiento local,
  • El ObservableBehaviorSubjectAPIs para trabajar con operaciones asíncronas,
  • El UserAuthResponseinterfaces.

Esta es la definición deBehaviorSubject :

Una de las variantes de Sujetos es el BehaviorSubject, que tiene una noción de "valor actual". Almacena el último valor emitido a sus consumidores, y cada vez que se suscribe un nuevo Observer, recibirá inmediatamente el "valor actual" del BehaviorSubject.

A continuación, declare estas variables en la clase de servicio:

AUTH_SERVER_ADDRESS:  string  =  'http://localhost:3000';
authSubject  =  new  BehaviorSubject(false);

El AUTH_SERVER_ADDRESScontiene la dirección del servidor de autenticación Express y authSubjectes un tipo de observables que se utilizará para suscribir el estado de autenticación .

A continuación, inyecte HttpClientStorageservicios a través del constructor del servicio:

constructor(private  httpClient:  HttpClient, private  storage:  Storage) { }

Envío de una solicitud POST HttpClientpara registrar usuarios

A continuación, agregue el register()método que se utilizará para registrar usuarios en el servidor Express:


  register(user: User): Observable<AuthResponse> {
    return this.httpClient.post<AuthResponse>(`${this.AUTH_SERVER_ADDRESS}/register`, user).pipe(
      tap(async (res:  AuthResponse ) => {

        if (res.user) {
          await this.storage.set("ACCESS_TOKEN", res.user.access_token);
          await this.storage.set("EXPIRES_IN", res.user.expires_in);
          this.authSubject.next(true);
        }
      })

    );
  }

Simplemente usamos el post()método para enviar una solicitud POST al /registerpunto final expuesto por nuestro servidor de autenticación que se ejecutará desde la localhost:3000/dirección. Crearemos el servidor con Node y Express.js en la siguiente sección.

Usamos la pipe()función para encadenar múltiples operadores. En nuestro caso, queremos realizar un efecto secundario para almacenar la información JWT (el token de acceso y la fecha de vencimiento) en el almacenamiento local, por lo que usamos el tap()operador que está disponible en RxJS.

En el tap()operador verificamos si la respuesta tiene un objeto de usuario y configuramos persistir el token de acceso y la fecha de vencimiento con las claves ACCESS_TOKENEXPIRES_INA continuación, emitimos un valor verdadero a nuestro authSubjectuso del next()método.

Envío de una solicitud POST HttpClientpara autenticar usuarios

A continuación, agregue el login()método que se utilizará para autenticar usuarios:


  login(user: User): Observable<AuthResponse> {
    return this.httpClient.post(`${this.AUTH_SERVER_ADDRESS}/login`, user).pipe(
      tap(async (res: AuthResponse) => {

        if (res.user) {
          await this.storage.set("ACCESS_TOKEN", res.user.access_token);
          await this.storage.set("EXPIRES_IN", res.user.expires_in);
          this.authSubject.next(true);
        }
      })
    );
  }

Enviamos una solicitud POST HttpCliental /loginpunto final de nuestro servidor Express.js que maneja la autenticación JWT. A continuación, realizamos un efecto secundario utilizando el pipe()método y el tap()operador disponibles en RxJS para conservar el token de acceso JWT y la fecha de vencimiento devuelta por el servidor.

Cerrar sesión de usuarios

A continuación, agregue el logout()método que se utilizará para eliminar la información de autenticación JWT del almacenamiento local:

  async logout() {
    await this.storage.remove("ACCESS_TOKEN");
    await this.storage.remove("EXPIRES_IN");
    this.authSubject.next(false);
  }

También emitimos un falsevalor en la BehaviorSubjectrepresentación del estado de autenticación.

Obtener el estado de autenticación

Finalmente agregue el isLoggedIn()método que se utilizará para verificar la identificación de que el usuario está conectado o no:


  isLoggedIn() {
    return this.authSubject.asObservable();
  }

Simplemente devolvemos la authSubjectvariable convertida a un Observable usando el asObservable()método. Puede comprobar si el usuario ha iniciado sesión suscribiéndose a la llamada de este método.

Creación de páginas iónicas

Ahora que hemos creado el servicio para autenticar usuarios. Creemos la interfaz de usuario con componentes Ionic 5 UI.

Consulte este segundo tutorial: Tutorial de Ionic 5: Cree una interfaz de usuario para iniciar sesión y registrarse .

Creación y ejecución de un servidor de autenticación Express.js

Vamos a crear un servidor de autenticación que expone dos /register/logincriterios de valoración utilizando Node.js y Express.js y un montón de otros módulos.

Primero, cree una carpeta para el código del servidor:

$ mkdir express-auth-demo

Navegue en la carpeta y cree un package.jsonarchivo:

$ npm init -y

A continuación, instale las siguientes dependencias:

$ npm install --save express body-parser sqlite3 bcryptjs jsonwebtoken cors

A continuación, cree un index.jsarchivo y agregue el siguiente código:

"use strict";
const  express  =  require('express');
const  bodyParser  =  require('body-parser');
const cors = require('cors')
const  sqlite3  =  require('sqlite3').verbose();
const  jwt  =  require('jsonwebtoken');
const  bcrypt  =  require('bcryptjs');

const SECRET_KEY = "secretkey23456";

const  app  =  express();
const  router  =  express.Router();
app.use(cors())

router.use(bodyParser.urlencoded({ extended:  false }));
router.use(bodyParser.json());
const database = new sqlite3.Database("./my.db");

const  createUsersTable  = () => {
    const  sqlQuery  =  `
        CREATE TABLE IF NOT EXISTS users (
        id integer PRIMARY KEY,
        name text,
        email text UNIQUE,
        password text)`;

    return  database.run(sqlQuery);
}

const  findUserByEmail  = (email, cb) => {
    return  database.get(`SELECT * FROM users WHERE email = ?`,[email], (err, row) => {
            cb(err, row)
    });
}

const  createUser  = (user, cb) => {
    return  database.run('INSERT INTO users (name, email, password) VALUES (?,?,?)',user, (err) => {
        cb(err)
    });
}

createUsersTable();

router.get('/', (req, res) => {
    res.status(200).send('This is an authentication server');
});

router.post('/register', (req, res) => {

    const  name  =  req.body.name;
    const  email  =  req.body.email;
    console.log(req.body);
    const  password  =  bcrypt.hashSync(req.body.password);

    createUser([name, email, password], (err)=>{
        if(err) return  res.status(500).send("Server error!");
        findUserByEmail(email, (err, user)=>{
            if (err) return  res.status(500).send('Server error!');  
            const  expiresIn  =  24  *  60  *  60;
            const  accessToken  =  jwt.sign({ id:  user.id }, SECRET_KEY, {
                expiresIn:  expiresIn
            });
            res.status(200).send({ "user":  user, "access_token":  accessToken, "expires_in":  expiresIn          
            });
        });
    });
});


router.post('/login', (req, res) => {
    const  email  =  req.body.email;
    const  password  =  req.body.password;
    findUserByEmail(email, (err, user)=>{
        if (err) return  res.status(500).send('Server error!');
        if (!user) return  res.status(404).send('User not found!');
        const  result  =  bcrypt.compareSync(password, user.password);
        if(!result) return  res.status(401).send('Password not valid!');

        const  expiresIn  =  24  *  60  *  60;
        const  accessToken  =  jwt.sign({ id:  user.id }, SECRET_KEY, {
            expiresIn:  expiresIn
        });
        res.status(200).send({ "user":  user, "access_token":  accessToken, "expires_in":  expiresIn});
    });
});

app.use(router);
const  port  =  process.env.PORT  ||  3000;
const  server  =  app.listen(port, () => {
    console.log('Server listening at http://localhost:'  +  port);
}); 

Para obtener más detalles sobre este código, consulte Autenticación JWT de Node Express: jsonwebtoken y bcryptjs .

A continuación, agregue un startscript en package.json:

"scripts": {
    "start": "node index.js"
},

Ahora puede ejecutar su servidor de autenticación usando:

$ npm start

Su servidor se ejecutará desde http://localhost:3000.

Puede usar cURL para enviar solicitudes POST a los puntos finales de autenticación antes de crear la interfaz de usuario de Ionic 5. Primero ejecute este comando en una nueva terminal para registrar un usuario:

 curl -H "Content-Type: applicatiIonic 5 es la última versión de Ionic. En este tutorial, aprenderemos a usar Ionic 5 y Angular 7 para crear un módulo de inicio de sesión y registro para autenticar usuarios. Aprenderemos sobre el uso de módulos, servicios, formularios (vía FormsModule) y HTTP (vía HttpClient) de Angular, entre otras características.

Aprenderemos a usar HttpClientpara enviar solicitudes POST a un servidor de autenticación back-end creado con Node y Express.js y el BehaviorSubjecttipo de RxJS Observable para rastrear el estado de autenticación.

Aprenderemos cómo usar el módulo de almacenamiento iónico para conservar la información JWT devuelta desde nuestro servidor Express.js, como el token de acceso y la fecha de vencimiento.

Antes de continuar, debe asegurarse de tener Node.js y NPM instalados en su máquina de desarrollo. Debería poder instalarlos descargando los binarios para su sistema desde el sitio web oficial .

Lea también Building Chat App Frontend UI con JWT Auth usando Ionic 5 / Angular 9

¡Ahora, comencemos!

Configuración de Ionic CLI 5

Nuestro primer paso es instalar Ionic CLI 5. Abra su terminal y ejecute este comando:

$ npm install -g ionic

Esto instalará el paquete iónico globalmente en su sistema. Si obtiene algún error de permiso, simplemente utilícelo sudoantes de su comando. Si está en Windows, use un indicador de CMD con acceso de administrador.

Creación de un proyecto Ionic 5

Procedamos ahora creando un proyecto Ionic 5. Regrese a su terminal y ejecute el siguiente comando:

$ ionic start ionic-auth-demo blank --type=angular   

Usamos --typepara especificar el tipo de marco que queremos usar con Ionic. A partir de la v4, Ionic es solo una biblioteca de interfaz de usuario móvil que se puede usar sobre Angular, Vue y React o simplemente JavaScript simple para crear aplicaciones móviles híbridas o aplicaciones web progresivas.

Usamos la blankplantilla para generar un proyecto que viene con una página llamada inicio.

La CLI hará un par de preguntas, por ejemplo, si desea instalar Cordova y si desea instalar el SDK de Ionic Appflow gratuito y conectar su aplicación. Responda esas preguntas como prefiera porque esto no afectará nuestros próximos pasos en este tutorial.

Espere a que se instalen las dependencias, luego navegue en la carpeta raíz de su proyecto y sirva su aplicación usando estos comandos:

$ cd ionic-auth-demo 
$ ionic serve

Puede acceder a su aplicación móvil utilizando su navegador web desde la localhost:8100dirección.

Creando un Módulo Angular

Los módulos se utilizan para organizar el código de su aplicación. Para la función de autenticación en nuestra aplicación, crearemos un módulo que encapsula el servicio y las páginas que manejan la autenticación de usuarios. En su terminal, ejecute:

$ ionic generate module auth

El src/app/auth/auth.module.tsarchivo se creará con el código básico de un módulo:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

@NgModule({
  declarations: [],
  imports: [
    CommonModule
  ]
})
export class AuthModule { }

Nuestro authmódulo sólo importa el CommonModulecual es construido en un módulo angular que las exportaciones de todas las directivas y los tubos angulares básicas, tales como [NgIf](https://angular.io/api/common/NgIf)[NgForOf](https://angular.io/api/common/NgForOf)[DecimalPipe](https://angular.io/api/common/DecimalPipe), y así sucesivamente.

Debe importar el authmódulo en el módulo de la aplicación raíz de nuestra aplicación Ionic 5. Abra el src/app/app.module.tsarchivo e impórtelo, AuthModuleluego agréguelo a la importsmatriz:

import { AuthModule } from  './auth/auth.module';

@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule,
    AuthModule
  ],
  providers: [
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

Vamos a importar otros módulos que son necesarios para nuestra aplicación, como HttpClientpara enviar solicitudes HTTP, FormsModulepara trabajar con formularios y el módulo Ionic Storage para trabajar con almacenamiento local en aplicaciones Ionic.

Importando HttpClient

HttpClientes el cliente http oficial de Angular, por lo que debemos importarlo en nuestro proyecto Ionic / Angular. Abra el src/app/auth/auth.module.tsarchivo e importe HttpClientModule:


import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    HttpClientModule
  ]
})
export class AuthModule { }

Eso es todo lo que necesitamos importar HttpClienten nuestro módulo de autenticación.

Configurar formularios

Angular proporciona potentes API para trabajar con formularios, ya sea a través de formularios basados ​​en plantillas o formularios reactivos. En este tutorial, usaremos formularios basados ​​en plantillas, por lo que necesitamos importar FormsModuleen nuestro módulo de aplicación principal. En el mismo src/app/auth/auth.module.tsarchivo:


import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { FormsModule } from '@angular/forms';

@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    HttpClientModule,
    FormsModule
  ]
})
export class AuthModule { }

Configuración del módulo de almacenamiento iónico

El equipo de Ionic proporciona el módulo Ionic Storage que se puede usar para trabajar con el almacenamiento local del navegador en dispositivos móviles, pero antes de que podamos usarlo en nuestra aplicación, debemos instalarlo desde npm e importarlo en nuestro módulo de autenticación. Regrese a su terminal y ejecute el siguiente comando:

$ npm install --save @ionic/storage

A partir de este escrito, ionic/storage v2.2.0se instalará en su proyecto.

A continuación, incluya IonicStorageModule.forRoot()en la importsmatriz:


import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { FormsModule } from '@angular/forms';

import { IonicStorageModule } from '@ionic/storage';

@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    HttpClientModule,
    FormsModule,
    IonicStorageModule.forRoot()
  ]
})
export class AuthModule { }

Creación del servicio de autenticación angular

Después de configurar los módulos necesarios para nuestro proyecto, ahora creemos un servicio de autenticación que encapsule la comunicación con el servidor Express a través de HttpClientEn su terminal, ejecute:

$ ionic generate interface auth/user

Esto generará una interfaz de usuario en el src/app/auth/user.tsarchivo. Abra el archivo y actualícelo en consecuencia:

export interface User {
    id: number;
    name: string;
    email: string;
    password: string;
}

Nota : Prefijamos el nombre de la interfaz auth/para indicarle a la CLI que la genere dentro del authmódulo.

Además, debe generar una interfaz para la respuesta del servidor:

$ ionic generate interface auth/auth-response

Abra el src/app/auth/auth-response.tsarchivo y actualícelo en consecuencia:

export interface AuthResponse {
    user: {
        id: number,
        name: string,
        email: string,
        access_token: string,
        expires_in: number
    }
}

Esto corresponde a la respuesta que se devolverá desde el servidor de autenticación que crearemos en la siguiente sección con Node y Express.js.

Luego, genere el servicio usando:

$ ionic generate service auth/auth

Se generarán dos archivos src/app/auth/auth.service.tssrc/app/auth/auth.service.spec.ts(pruebas).

Nota : Prefijamos el nombre del servicio auth/para indicarle a la CLI que lo genere dentro del authmódulo.

Abra el src/app/auth/auth.service.tsarchivo y actualícelo siguiendo estos pasos. Primero agregue las importaciones necesarias:

import { Injectable } from  '@angular/core';
import { HttpClient } from  '@angular/common/http';
import { tap } from  'rxjs/operators';
import { Observable, BehaviorSubject } from  'rxjs';

import { Storage } from  '@ionic/storage';
import { User } from  './user';
import { AuthResponse } from  './auth-response';

Importamos:

  • HttpClient para enviar una solicitud POST al servidor Express que maneja la autenticación,
  • El tap()operador para realizar efectos secundarios al suscribirse a los observables devueltos por los HttpClientmétodos,
  • El Storagemódulo para conservar el token de acceso y la fecha de vencimiento en el almacenamiento local,
  • El ObservableBehaviorSubjectAPIs para trabajar con operaciones asíncronas,
  • El UserAuthResponseinterfaces.

Esta es la definición deBehaviorSubject :

Una de las variantes de Sujetos es el BehaviorSubject, que tiene una noción de "valor actual". Almacena el último valor emitido a sus consumidores, y cada vez que se suscribe un nuevo Observer, recibirá inmediatamente el "valor actual" del BehaviorSubject.

A continuación, declare estas variables en la clase de servicio:

AUTH_SERVER_ADDRESS:  string  =  'http://localhost:3000';
authSubject  =  new  BehaviorSubject(false);

El AUTH_SERVER_ADDRESScontiene la dirección del servidor de autenticación Express y authSubjectes un tipo de observables que se utilizará para suscribir el estado de autenticación .

A continuación, inyecte HttpClientStorageservicios a través del constructor del servicio:

constructor(private  httpClient:  HttpClient, private  storage:  Storage) { }

Envío de una solicitud POST HttpClientpara registrar usuarios

A continuación, agregue el register()método que se utilizará para registrar usuarios en el servidor Express:


  register(user: User): Observable<AuthResponse> {
    return this.httpClient.post<AuthResponse>(`${this.AUTH_SERVER_ADDRESS}/register`, user).pipe(
      tap(async (res:  AuthResponse ) => {

        if (res.user) {
          await this.storage.set("ACCESS_TOKEN", res.user.access_token);
          await this.storage.set("EXPIRES_IN", res.user.expires_in);
          this.authSubject.next(true);
        }
      })

    );
  }

Simplemente usamos el post()método para enviar una solicitud POST al /registerpunto final expuesto por nuestro servidor de autenticación que se ejecutará desde la localhost:3000/dirección. Crearemos el servidor con Node y Express.js en la siguiente sección.

Usamos la pipe()función para encadenar múltiples operadores. En nuestro caso, queremos realizar un efecto secundario para almacenar la información JWT (el token de acceso y la fecha de vencimiento) en el almacenamiento local, por lo que usamos el tap()operador que está disponible en RxJS.

En el tap()operador verificamos si la respuesta tiene un objeto de usuario y configuramos persistir el token de acceso y la fecha de vencimiento con las claves ACCESS_TOKENEXPIRES_INA continuación, emitimos un valor verdadero a nuestro authSubjectuso del next()método.

Envío de una solicitud POST HttpClientpara autenticar usuarios

A continuación, agregue el login()método que se utilizará para autenticar usuarios:


  login(user: User): Observable<AuthResponse> {
    return this.httpClient.post(`${this.AUTH_SERVER_ADDRESS}/login`, user).pipe(
      tap(async (res: AuthResponse) => {

        if (res.user) {
          await this.storage.set("ACCESS_TOKEN", res.user.access_token);
          await this.storage.set("EXPIRES_IN", res.user.expires_in);
          this.authSubject.next(true);
        }
      })
    );
  }

Enviamos una solicitud POST HttpCliental /loginpunto final de nuestro servidor Express.js que maneja la autenticación JWT. A continuación, realizamos un efecto secundario utilizando el pipe()método y el tap()operador disponibles en RxJS para conservar el token de acceso JWT y la fecha de vencimiento devuelta por el servidor.

Cerrar sesión de usuarios

A continuación, agregue el logout()método que se utilizará para eliminar la información de autenticación JWT del almacenamiento local:

  async logout() {
    await this.storage.remove("ACCESS_TOKEN");
    await this.storage.remove("EXPIRES_IN");
    this.authSubject.next(false);
  }

También emitimos un falsevalor en la BehaviorSubjectrepresentación del estado de autenticación.

Obtener el estado de autenticación

Finalmente agregue el isLoggedIn()método que se utilizará para verificar la identificación de que el usuario está conectado o no:


  isLoggedIn() {
    return this.authSubject.asObservable();
  }

Simplemente devolvemos la authSubjectvariable convertida a un Observable usando el asObservable()método. Puede comprobar si el usuario ha iniciado sesión suscribiéndose a la llamada de este método.

Creación de páginas iónicas

Ahora que hemos creado el servicio para autenticar usuarios. Creemos la interfaz de usuario con componentes Ionic 5 UI.

Consulte este segundo tutorial: Tutorial de Ionic 5: Cree una interfaz de usuario para iniciar sesión y registrarse .

Creación y ejecución de un servidor de autenticación Express.js

Vamos a crear un servidor de autenticación que expone dos /register/logincriterios de valoración utilizando Node.js y Express.js y un montón de otros módulos.

Primero, cree una carpeta para el código del servidor:

$ mkdir express-auth-demo

Navegue en la carpeta y cree un package.jsonarchivo:

$ npm init -y

A continuación, instale las siguientes dependencias:

$ npm install --save express body-parser sqlite3 bcryptjs jsonwebtoken cors

A continuación, cree un index.jsarchivo y agregue el siguiente código:

"use strict";
const  express  =  require('express');
const  bodyParser  =  require('body-parser');
const cors = require('cors')
const  sqlite3  =  require('sqlite3').verbose();
const  jwt  =  require('jsonwebtoken');
const  bcrypt  =  require('bcryptjs');

const SECRET_KEY = "secretkey23456";

const  app  =  express();
const  router  =  express.Router();
app.use(cors())

router.use(bodyParser.urlencoded({ extended:  false }));
router.use(bodyParser.json());
const database = new sqlite3.Database("./my.db");

const  createUsersTable  = () => {
    const  sqlQuery  =  `
        CREATE TABLE IF NOT EXISTS users (
        id integer PRIMARY KEY,
        name text,
        email text UNIQUE,
        password text)`;

    return  database.run(sqlQuery);
}

const  findUserByEmail  = (email, cb) => {
    return  database.get(`SELECT * FROM users WHERE email = ?`,[email], (err, row) => {
            cb(err, row)
    });
}

const  createUser  = (user, cb) => {
    return  database.run('INSERT INTO users (name, email, password) VALUES (?,?,?)',user, (err) => {
        cb(err)
    });
}

createUsersTable();

router.get('/', (req, res) => {
    res.status(200).send('This is an authentication server');
});

router.post('/register', (req, res) => {

    const  name  =  req.body.name;
    const  email  =  req.body.email;
    console.log(req.body);
    const  password  =  bcrypt.hashSync(req.body.password);

    createUser([name, email, password], (err)=>{
        if(err) return  res.status(500).send("Server error!");
        findUserByEmail(email, (err, user)=>{
            if (err) return  res.status(500).send('Server error!');  
            const  expiresIn  =  24  *  60  *  60;
            const  accessToken  =  jwt.sign({ id:  user.id }, SECRET_KEY, {
                expiresIn:  expiresIn
            });
            res.status(200).send({ "user":  user, "access_token":  accessToken, "expires_in":  expiresIn          
            });
        });
    });
});


router.post('/login', (req, res) => {
    const  email  =  req.body.email;
    const  password  =  req.body.password;
    findUserByEmail(email, (err, user)=>{
        if (err) return  res.status(500).send('Server error!');
        if (!user) return  res.status(404).send('User not found!');
        const  result  =  bcrypt.compareSync(password, user.password);
        if(!result) return  res.status(401).send('Password not valid!');

        const  expiresIn  =  24  *  60  *  60;
        const  accessToken  =  jwt.sign({ id:  user.id }, SECRET_KEY, {
            expiresIn:  expiresIn
        });
        res.status(200).send({ "user":  user, "access_token":  accessToken, "expires_in":  expiresIn});
    });
});

app.use(router);
const  port  =  process.env.PORT  ||  3000;
const  server  =  app.listen(port, () => {
    console.log('Server listening at http://localhost:'  +  port);
}); 

Para obtener más detalles sobre este código, consulte Autenticación JWT de Node Express: jsonwebtoken y bcryptjs .

A continuación, agregue un startscript en package.json:

"scripts": {
    "start": "node index.js"
},

Ahora puede ejecutar su servidor de autenticación usando:

$ npm start

Su servidor se ejecutará desde http://localhost:3000.

Puede usar cURL para enviar solicitudes POST a los puntos finales de autenticación antes de crear la interfaz de usuario de Ionic 5. Primero ejecute este comando en una nueva terminal para registrar un usuario:

 curl -H "Content-Type: application/json" -d '{"email":"test@test.com","name":"test", "password":"test"}' http://localhost:3000/register

A continuación, ejecute este comando para iniciar sesión como usuario:

 curl -H "Content-Type: application/json" -d '{"email":"test@test.com", "password":"test"}' http://localhost:3000/login

Conclusión

En este tutorial, hemos aprendido cómo implementar la autenticación JWT con Ionic 5, Angular 7 en el front-end y Node y Express.js en el back-end. Hemos visto cómo enviar solicitudes POST utilizando HttpClienty cómo conservar los valores en el almacenamiento local utilizando el módulo Ionic Storage.

on/json" -d '{"email":"test@test.com","name":"test", "password":"test"}' http://localhost:3000/register

A continuación, ejecute este comando para iniciar sesión como usuario:

 curl -H "Content-Type: application/json" -d '{"email":"test@test.com", "password":"test"}' http://localhost:3000/login

Conclusión

En este tutorial, hemos aprendido cómo implementar la autenticación JWT con Ionic 5, Angular 7 en el front-end y Node y Express.js en el back-end. Hemos visto cómo enviar solicitudes POST utilizando HttpClienty cómo conservar los valores en el almacenamiento local utilizando el módulo Ionic Storage.


Publicar un comentario

0 Comentarios