Autenticación Angular Con JWT
() translation by (you can also view the original English article)
La seguridad es una parte importante de cada aplicación web, y los desarrolladores deben asegurarse de que diseñan aplicaciones con autenticación segura. En este tutorial, aprenderá cómo implementar la autenticación basada en JWT en aplicaciones Angular con la ayuda de un simple servidor Express.
El código completo se puede encontrar en nuestro repositorio de GitHub. La aplicación que vamos a construir se verá así:



El concepto de tokens web de JSON
Un JSON Web Token (JWT) es básicamente un objeto representado por tres cadenas que se utilizan para transmitir información de usuario. Las tres cuerdas, que están separadas por puntos, son:
- encabezamiento
- carga útil
- firma
Cuando un usuario inicia sesión en cualquier página web con su nombre de usuario y contraseña, el servidor de autenticación generalmente crea y envía un JWT. Este JWT se pasa junto con las subsiguientes llamadas de API al servidor. El JWT sigue siendo válido a menos que caduque o el usuario cierre sesión en la aplicación.
Este proceso se puede ilustrar en el diagrama a continuación.



Cookies vs. Almacenamiento Local
Usaremos almacenamiento local para almacenar tokens. El almacenamiento local es un medio por el cual los datos se almacenan localmente y solo se pueden eliminar a través de JavaScript o borrando la memoria caché en el navegador. Los datos almacenados en el almacenamiento local pueden persistir durante mucho tiempo. Las cookies, por otro lado, son mensajes que se envían desde el servidor al navegador y ofrecen un almacenamiento limitado.
Construyendo el Servidor Express
Comenzaremos por construir un servidor de servicios de fondo que contará con los siguientes puntos finales:
- POST<webservice>/login
- POST <webservice> / perfil
Comencemos
por crear un directorio para la aplicación Express y luego ejecutar el
comando npm init
para configurar los archivos necesarios para el
proyecto.
1 |
mkdir server
|
2 |
cd server
|
3 |
npm init |
A continuación, cree un archivo server.js e instale los módulos: express
, jsonwebtoken
, cors
y bodyParser
.
1 |
touch server.js
|
2 |
npm install express jsonwebtoken cors bodyParser –save
|
Ahora abra server.js y comience importando los módulos.
1 |
// server.js
|
2 |
const cors = require('cors'); |
3 |
const bodyParser = require('body-parser'); |
4 |
const jwt = require('jsonwebtoken'); |
5 |
const express = require('express'); |
Luego cree una aplicación Express y defina la clave secreta que se utilizará para codificar y descodificar los detalles del usuario.
1 |
//CREATE EXPRESS APP
|
2 |
const app = express(); |
3 |
app.use(cors()); |
4 |
app.use(bodyParser.json()); |
5 |
|
6 |
// DECLARE JWT-secret
|
7 |
const JWT_Secret = 'your_secret_key'; |
No usaremos una base de datos para este ejemplo. Sin embargo, los conceptos serían similares si estuviera creando un servidor con respaldo de base de datos adecuado.
Para nuestro ejemplo, solo usaremos una variable para definir un usuario de prueba como se muestra a continuación.
1 |
var testUser = { email: 'kelvin@gmai.com', password: '1234'}; |
El último paso es crear rutas para autenticar al usuario.
1 |
app.post('/api/authenticate', (req, res) => { |
2 |
|
3 |
if (req.body) { |
4 |
var user = req.body; |
5 |
console.log(user) |
6 |
|
7 |
if (testUser.email===req.body.email && testUser.password === req.body.password) { |
8 |
var token = jwt.sign(user, JWT_Secret); |
9 |
res.status(200).send({ |
10 |
signed_user: user, |
11 |
token: token |
12 |
});
|
13 |
} else { |
14 |
res.status(403).send({ |
15 |
errorMessage: 'Authorisation required!' |
16 |
});
|
17 |
}
|
18 |
} else { |
19 |
res.status(403).send({ |
20 |
errorMessage: 'Please provide email and password' |
21 |
});
|
22 |
}
|
23 |
|
24 |
});
|
Vamos a desglosar el código de la ruta anterior.
Primero verificamos si hay algún dato en el cuerpo de la solicitud. Si no se encuentran datos, le pedimos al usuario que ingrese algunos datos. En la
ocasión en que el usuario ha proporcionado los datos correctos, lo
comparamos con los datos del testUser
y, si concuerda, usamos la
identificación del usuario para generar un token único y enviar la
respuesta al usuario.
Finalmente, creamos un punto final para ejecutar la aplicación.
1 |
app.listen(5000, () => console.log('Server started on port 5000')); |
Nuestro back-end ahora está completo, y puede probarlo con Postman o CURL y ver el tipo de datos que se devolverán al usuario.
Construir una aplicación angular
Nuestra aplicación Angular contará con las siguientes páginas:
- Inicio: esta página contendrá enlaces a las páginas de inicio de sesión y de perfil.
- Inicio de sesión: en esta página, un usuario ingresará su correo electrónico y contraseña, que se enviarán al servidor para su autenticación. Si las credenciales son correctas, entonces se devolverá un token JWT y el usuario será redirigido a la página de perfil.
- Perfil: esta es una página protegida a la que solo puede acceder un usuario con un token válido.
Cree una aplicación Angular y cree los componentes de Login
y Profile
como se muestra a continuación:
1 |
ng new angular6jwt |
2 |
cd angular6jwt
|
3 |
ng g component Login |
4 |
ng g component Profile |
A continuación, agregue el código de la página de inicio en app.component.html.
1 |
<!--The content below is only a placeholder and can be replaced.-->
|
2 |
<div style="text-align:center"> |
3 |
<ul>
|
4 |
<li><a class="nav-link" routerLink="/" routerLinkActive="active">Home</a> </li> |
5 |
<li><a class="nav-link" routerLink="profile" routerLinkActive="active">Profile</a> </li> |
6 |
<li style="float:right" > <a class="nav-link" style="float:right" routerLink="login" routerLinkActive="active">Login</a> </li> |
7 |
<li style="float:right" > <a class ="nav-link" (click)="logout()" href="#">Logout</a></li> |
8 |
</ul>
|
9 |
<div class="text-center"> |
10 |
<p>
|
11 |
Angular 6 Authentication with JWT Tutorial |
12 |
</p>
|
13 |
</div>
|
14 |
<router-outlet></router-outlet>
|
15 |
A continuación, importe el RouterModule
y defina las rutas en app.module.ts.
1 |
import { RouterModule } from '@angular/router'; |
2 |
|
3 |
|
4 |
@NgModule({ |
5 |
declarations: [ |
6 |
AppComponent, |
7 |
LoginComponent, |
8 |
ProfileComponent
|
9 |
],
|
10 |
imports: [ |
11 |
BrowserModule, |
12 |
RouterModule, |
13 |
FormsModule, |
14 |
RouterModule.forRoot([ |
15 |
{ path: '', redirectTo: '/', pathMatch: 'full' }, |
16 |
{ path: 'login', component: LoginComponent }, |
17 |
{ path: 'profile', component: ProfileComponent } |
18 |
|
19 |
|
20 |
]),
|
21 |
],
|
22 |
providers: [], |
23 |
bootstrap: [AppComponent] |
24 |
})
|
25 |
export class AppModule { } |
Crear página de inicio de sesión
La página de inicio de sesión contendrá dos campos de entrada para correo electrónico y contraseña, y un botón de envío como se muestra a continuación:
1 |
<h3>Login</h3> |
2 |
<div>
|
3 |
<div class="spacer"> |
4 |
<label for="Email">Email</label> |
5 |
<input type="text" placeholder="Email" [(ngModel)]="email"> |
6 |
</div>
|
7 |
<div class="spacer"> |
8 |
<label for="password">Password</label> |
9 |
<input type="password" placeholder="password" [(ngModel)]="password" class="form-control"/> |
10 |
</div>
|
11 |
<div class="spacer"> |
12 |
<button type="submit" (click)="Login()">Login</button> |
13 |
</div>
|
14 |
</div>
|
Crear página de perfil
La página de perfil solo será un mensaje simple como se muestra a continuación:
1 |
<p>
|
2 |
If you can see this page, you are logged in! |
3 |
</p>
|
Autentica Con JWT En Angular
Comenzaremos
creando un Servicio Auth
que facilitará la validación de la
entrada y comunicación del usuario con el servidor.
1 |
// Create authentication service named Auth
|
2 |
ng g service Auth |
Esto crea dos archivos, pero principalmente nos interesará el archivo auth.service.ts donde escribiremos todo el código que interactúa con el servidor. Comenzaremos por definir la API REST y el token como se muestra a continuación:
1 |
export class AuthService { |
2 |
|
3 |
api = 'https://localhost:3000/api'; |
4 |
token; |
5 |
|
6 |
}
|
A continuación, escribiremos el código que realiza una solicitud POST al servidor con las credenciales del usuario. Aquí,
hacemos una solicitud a la API: si tiene éxito, almacenamos el token en
localStorage
y redirigimos al usuario a la página de perfil.
1 |
import { Injectable } from '@angular/core'; |
2 |
import { HttpClientModule, HttpClient } from '@angular/common/http'; |
3 |
import { Router } from '@angular/router'; |
4 |
|
5 |
@Injectable({ |
6 |
providedIn: 'root' |
7 |
})
|
8 |
|
9 |
export class AuthService { |
10 |
|
11 |
uri = 'http://localhost:5000/api'; |
12 |
token; |
13 |
|
14 |
constructor(private http: HttpClient,private router: Router) { } |
15 |
login(email: string, password: string) { |
16 |
this.http.post(this.uri + '/authenticate', {email: email,password: password}) |
17 |
.subscribe((resp: any) => { |
18 |
|
19 |
this.router.navigate(['profile']); |
20 |
localStorage.setItem('auth_token', resp.token); |
21 |
|
22 |
})
|
23 |
);
|
24 |
|
25 |
}
|
26 |
|
27 |
}
|
También definimos las funciones de inicio y cierre de sesión como se muestra a continuación.
1 |
logout() { |
2 |
localStorage.removeItem('token'); |
3 |
}
|
4 |
|
5 |
public get logIn(): boolean { |
6 |
return (localStorage.getItem('token') !== null); |
7 |
}
|
- cerrar sesión: borra el token del almacenamiento local
- logIn: devuelve una propiedad booleana que determina si un usuario está autenticado
Luego actualizamos la propiedad logIn
en la página de inicio como se muestra.
1 |
<ul>
|
2 |
<li><a class="nav-link" routerLink="/" routerLinkActive="active">Home</a> </li> |
3 |
<li><a class="nav-link" routerLink="profile" routerLinkActive="active" *ngIf="authService.logIn">Profile</a> </li> |
4 |
<li style="float:right" > <a class="nav-link" style="float:right" routerLink="login" routerLinkActive="active" *ngIf="!authService.logIn">Login</a> </li> |
5 |
<li style="float:right" > <a class ="nav-link" (click)="logout()" href="#" *ngIf="authService.logIn">Logout</a> </li> |
6 |
</ul>
|
Respondiendo a los eventos del usuario
Ahora que hemos terminado con el código que interactúa con el servidor, pasaremos a manejar los eventos generados por el usuario para el front-end.
Escribiremos
la función que escuchará los eventos de clic desde la página de inicio
de sesión y luego pasaremos los valores al AuthService
para autenticar
al usuario. Actualice su archivo login.component.ts para que se vea así:
1 |
import { Component, OnInit } from '@angular/core'; |
2 |
import { Router, ActivatedRoute } from '@angular/router'; |
3 |
|
4 |
import { AuthService } from '../auth.service'; |
5 |
|
6 |
@Component({ |
7 |
selector: 'app-login', |
8 |
templateUrl: './login.component.html', |
9 |
styleUrls: ['./login.component.css'] |
10 |
})
|
11 |
export class LoginComponent implements OnInit { |
12 |
email = ''; |
13 |
password = ''; |
14 |
|
15 |
constructor(private authService: AuthService) { |
16 |
|
17 |
}
|
18 |
Login() { |
19 |
console.log("you are logging in") |
20 |
this.authService.login(this.email, this.password) |
21 |
|
22 |
}
|
23 |
|
24 |
ngOnInit() { } |
25 |
}
|
Ahora, si ejecuta ng serve
y navega a http: // localhost: 4200, puede probar su aplicación.
1 |
ng serve |
Haga clic en el enlace de inicio de sesión y proporcione las credenciales de usuario; recuerde que las credenciales válidas se definen en la aplicación Express. Ahora, cuando haga clic en el botón de inicio de sesión, será redirigido a la página de perfil.
Conclusión
En este tutorial, aprendió cómo comenzar con la autenticación JWT en Angular. Ahora puede autenticar y autorizar con JWT en sus aplicaciones Angular. Hay muchos aspectos de JWT que no se trataron en este tutorial. ¡Vea si puede explorar algunos de ellos por su cuenta!
Tenga en cuenta que este tutorial fue escrito para Angular 6, pero los mismos conceptos deberían funcionar con Angular 2 o Angular 4.