Security is an important part of every web app, and devs must ensure that they design apps with secure authentication. In this tutorial, you’ll learn how to implement JWT-based authentication in Angular apps with the help of a simple Express server.
The full code can be found in our GitHub repo. The app we’ll be building will look like this:
The Concept of JSON Web Tokens
A JSON Web Token (JWT) is basically an object represented by three strings that are used to transmit user information. The three strings, which are separated by dots, are:
- header
- payload
- signature
When a user logs in to any web page with their username and password, the authenticating server usually creates and sends back a JWT. This JWT is then passed along with subsequent API calls to the server. The JWT remains valid unless it expires or the user signs out of the application.
This process can be illustrated in the diagram below.
Cookies vs. Local Storage
We’ll be using local storage to store tokens. Local storage is a means by which data is stored locally and can only be removed via JavaScript or by clearing the cache in the browser. Data stored in local storage can persist for a very long time. Cookies, on the other hand, are messages that are sent from the server to the browser and offer only limited storage.
Building the Express Server
We will start by building a back-end server that will feature the following endpoints:
- POST
/login - POST
/profile
Let’s get started by creating a directory for the Express application and then run the command npm init
to set up the required files for the project.
mkdir server cd server npm init
Next, create a file server.js and install the modules: express
, jsonwebtoken
, cors
, and bodyParser
.
touch server.js npm install express jsonwebtoken cors bodyParser –save
Now open server.js and start by importing the modules.
// server.js const cors = require('cors'); const bodyParser = require('body-parser'); const jwt = require('jsonwebtoken'); const express = require('express');
Then create an Express app and define the secret key that will be used to encode and decode the user details.
//CREATE EXPRESS APP const app = express(); app.use(cors()); app.use(bodyParser.json()); // DECLARE JWT-secret const JWT_Secret = 'your_secret_key';
We will not be using a database for this example. However, the concepts would be similar if you were building a proper database-backed server.
For our example, we will just use a variable to define a test user as shown below.
var testUser = { email: '[email protected]', password: '1234'};
The final step is to create routes for authenticating the user.
app.post('/api/authenticate', (req, res) => { if (req.body) { var user = req.body; console.log(user) if (testUser.email===req.body.email && testUser.password === req.body.password) { var token = jwt.sign(user, JWT_Secret); res.status(200).send({ signed_user: user, token: token }); } else { res.status(403).send({ errorMessage: 'Authorisation required!' }); } } else { res.status(403).send({ errorMessage: 'Please provide email and password' }); } });
Let’s break down the code for the route above.
We first check if there is any data in the body of the request. If no data is found, we prompt the user to input some data. On the occasion that the user has provided the right data, we compare it to the data from the testUser
and, if it matches, we use the user id to generate a unique token and send back the response to the user.
Finally, we create an endpoint for running the app.
app.listen(5000, () => console.log('Server started on port 5000'));
Our back-end is now complete, and you can test it with Postman or CURL and see the kind of data that will be returned to the user.
Build an Angular Application
Our Angular application will feature the following pages:
- Home—This page will contain links to the login and profile pages.
- Login—On this page, a user will enter their email and password, which will be sent to the server for authentication. If the credentials are correct, then a JWT token will be returned and the user will be redirected to the profile page.
- Profile—This is a protected page that can only be accessed by a user with a valid token.
Create an Angular application and create the Login
and Profile
components as shown below:
ng new angular6jwt cd angular6jwt ng g component Login ng g component Profile
Next, add the code for the home page in app.component.html.
- Home
- Profile
- Login
- Logout
Angular 6 Authentication with JWT Tutorial
Next, import the
RouterModule
and define the routes in app.module.ts.import { RouterModule } from '@angular/router'; @NgModule({ declarations: [ AppComponent, LoginComponent, ProfileComponent ], imports: [ BrowserModule, RouterModule, FormsModule, RouterModule.forRoot([ { path: '', redirectTo: '/', pathMatch: 'full' }, { path: 'login', component: LoginComponent }, { path: 'profile', component: ProfileComponent } ]), ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }Create Login Page
The login page will contain two input fields for email and password, and a submit button as shown below:
Login
Create Profile Page
The profile page will just be a simple message as shown below:
If you can see this page, you are logged in!
Auth With JWT in Angular
We will start by creating an
Auth
Service that will facilitate the validation of user input and communication with the server.// Create authentication service named Auth ng g service AuthThis creates two files, but we will mainly be interested in the auth.service.ts file where we will write all the code that interacts with the server. We will start by defining the REST API and the token as shown below:
export class AuthService { api = 'http://localhost:3000/api'; token; }Next, we will write the code that performs a POST request to the server with the user credentials. Here, we make a request to the API—if it’s successful we store the token in
localStorage
and redirect the user to the profile page.import { Injectable } from '@angular/core'; import { HttpClientModule, HttpClient } from '@angular/common/http'; import { Router } from '@angular/router'; @Injectable({ providedIn: 'root' }) export class AuthService { uri = 'http://localhost:5000/api'; token; constructor(private http: HttpClient,private router: Router) { } login(email: string, password: string) { this.http.post(this.uri + '/authenticate', {email: email,password: password}) .subscribe((resp: any) => { this.router.navigate(['profile']); localStorage.setItem('auth_token', resp.token); }) ); } }We also define login and logout functions as shown below.
logout() { localStorage.removeItem('token'); } public get logIn(): boolean { return (localStorage.getItem('token') !== null); }
- logout—clears the token from the local storage
- logIn—returns a boolean property that determines if a user is authenticated
We then update the
logIn
property on the home page as shown.
- Home
- Profile
- Login
- Logout
Responding to User Events
Now that we are done with the code that interacts with the server, we’ll move on to handling user-generated events for the front-end.
We will write the function that will listen for click events from the login page and then pass the values to the
AuthService
to authenticate the user. Update your login.component.ts file to look like this:import { Component, OnInit } from '@angular/core'; import { Router, ActivatedRoute } from '@angular/router'; import { AuthService } from '../auth.service'; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.css'] }) export class LoginComponent implements OnInit { email = ''; password = ''; constructor(private authService: AuthService) { } Login() { console.log("you are logging in") this.authService.login(this.email, this.password) } ngOnInit() { } }Now if you run
ng serve
and navigate to http://localhost:4200, you can test your app.ng serveClick on the login link and supply the user credentials—remember, the valid credentials are defined in the Express app. Now, when you click on the login button, you will be redirected to the profile page.
Conclusion
In this tutorial, you learned how to get started with JWT authentication in Angular. Now you can authenticate and authorize with JWT in your Angular applications. There are many aspects of JWT that were not covered in this tutorial—see if you can explore some of them on your own!
Note that this tutorial was written for Angular 6, but the same concepts should work with Angular 2 or Angular 4.
Powered by WPeMatico