You are on page 1of 50

JSON WEB TOKEN(JWT)

BY:
MUHAMMAD RASHID MUKHTAR
CONTENTS

1. Introduction
2. Cookie Based Authentication
3. Token Based Authentication
4. JSON Web Token
5. When to use JWT?
6. JWT Structure
7. How JWT works?
8. JWT v/s other methods
9. Cons
10. Server Side Application
11. Client Side Application
INTRODUCTION

1. Authentication
2. Ways to authenticate
(i). Cookie based (Stateful Authentication)
(ii). Token based (Stateless Authentication)
Cookie Based Authentication

 Stateful : An authentication record or session must


be maintained. The server needs to keep track of
active sessions in a database.
 Every request is accompanied by a cookie.
 Whenever the user makes a request, the server
validates the cookie and session Id.
 Basic flow using cookie authentication:
Procedure

 User enters their login credentials.


 Server verifies the credentials are correct and creates
a session which is then stored in a database.
 A cookie with the session ID is placed in the users
browser.
 On further requests, the session ID is verified against
the database and if valid, the request processed.
 Once a user logs out of the app, the session is
destroyed both client and server side.
Features

 Stateful
 Coupling with web framework
 Cross Origin Request Sharing(CORS)
 No data storage
 Performance
Token Based Authentication

 Stateless: The server does not keep a record of which


users are logged in . Instead, every request to the
server is accompanied by a token which the server
uses to verify the authenticity of the request.

 Basic Flow of token based authentication:


Procedure

 User enters their login credentials.


 Server verifies the credentials are correct and returns a
signed token.
 This token is stored client-side, most commonly in local
storage.
 Subsequent requests to the server include this token as
an additional Authorization header.
 The server decodes the JWT and if the token is valid
processes the request
 Once a user logs out, the token is destroyed client-side.
Features

 Stateless
 CORS / Cross-Domain
 Data Storage
 Performance
 Compact and Self Contained
 Easy implementation on Mobile

Hence, Token based authentication is better than


Cookie based authentication.
JSON Web Tokens

 JSON Web Token (JWT) is a compact, open standard means of


representing claims to be transferred between two parties. These are
encoded as a JSON object that is used as the payload of a JSON Web
Signature (JWS) structure or as the plain text of a JSON Web Encryption
(JWE) structure, enabling the claims to be digitally signed.

 In layman’s language, JSON Web Token(JWT) is a self-verified


encoded string that is used in Modern Web/Mobile app for both
Authentication and Authorization. The fact that it is stateless removes the
maintenance efforts that we need for other Authentication and
Authorization tools. It is used as a replacement to cookies, or rather
improvement over cookies.

 Compact and Self Contained.

 Used by Node.js, Ruby, python etc.


When to use JWT?

 Authentication : Once the user is logged in, each


subsequent request will include the JWT, allowing the
user to access routes, services, and resources that are
permitted with that token. It’s a feature that widely
because of its small overhead and its ability to be easily
used across different domains.

 Information Exchange: JSON Web Tokens are a


good way of securely transmitting information between
parties, because as they can be signed, for example using
public/private key pairs, you can be sure that the senders
are who they say they are. You can also verify that the
content hasn't been tampered. (using header and
payload)
JWT Structure

JWT Tokens consists of three parts appended by a


(dot).
➢ Header: type of token, hash algorithm
➢ Payload: claims (public, private and reserved)
➢ Signature
HEADER
PAYLOAD

Common claims are:


 Issuer (iss)
 Subject (sub)
 Audience (aud)
 Expiration time (exp)
 Not before (nbf)
 Issued at (iat)
 JWT ID (jti)
SIGNATURE
OUTPUT (JWT)
Simple Mechanism

 In JWT, a token is encoded from a data payload


using a secret.
 That token is passed to the client.
 Whenever the client sends that token along with a
request, the server validates it and sends back the
response.
JWT Mechanism
Step by Step Process

 A client sends username/password combination to the server


 The server validates the authentication
 If authentication is successful, the server creates a JWT token
else establishes an error response
 On successful authentication, the client gets JWT token in the
response body
 Client stores that token in local storage or session storage.
 From next time, the client for making any request supplies the
JWT token in request headers like this. Authorization: Bearer
<jwt_token>
 Server upon receiving the JWT validates it and sends the
successful response else error.
How JWT works?
JWT v/s Other Token Methods

 Better than Simple Web Token(SWT) and


SAML(Simple Assertion Markup Language).
 Less verbose.
 Security
 Common parser
Cons of JWT

➢ Data Overhead.

➢ Security of whole platform will be compromised if the


secret key is leaked.
jsonwebtoken

 There are many libraries available in different


languages developed already.
 You plug them, and you get two main functionalities
to generating JWT, validate JWT, etc.
 Here we pick an NPM library
called jsonwebtoken which is suggested by the
JWT website.
 Install it globally or for specific project
 Npm install jsonwebtoken –g//for global
Server Side Sample Application

 We need to create two files other than app.js in our


application at same level.
 Config.js
 Middleware.js
 In config.js, we just define the secret which is master
password.
 This secret will be read by JWT library while creating and
validating tokens.
 In production, we need to store this secret in
environment variable instead of a file.
module.exports = {
secret: ‘bcs6csp19’
};
Middleware.js
let jwt = require('jsonwebtoken');
const config = require('./config.js'); else {
req.decoded = decoded;
next();
let checkToken = (req, res, next) => {
}
let token = req.headers['x-access-token'] || });
req.headers['authorization’]; } else {
// Express headers are auto converted to lowercase return res.json({
if (token.startsWith('Bearer ')) { success: false,
// Remove Bearer from string message: 'Auth token is not supplied'
});
token = token.slice(7, token.length);
}
} };

if (token) { module.exports = {
jwt.verify(token, config.secret, (err, decoded) => { checkToken: checkToken
}
if (err) {
return res.json({
success: false,
message: 'Token is not valid'
});
}
Middleware.js

 In the middleware.js, we can write a function that acts as


middleware to get a token from a request and proceeds
only when the token is validated.
 In Last Code
 Capture headers with names ‘x-access-token’ or ‘Authorization.’
 If the header is in ‘Authorization: Bearer xxxx…’ format, strip
unwanted prefix before token.
 Using jwt package and secret string, validate the token.
 If anything goes wrong, return an error immediately before passing
control to next handler.
 Export the middleware function for other modules to use.
 At this moment, we haven’t written any code to create a
token. We will do that next.
App.js
const express = require('express'); // return the JWT token for the future API
const bodyParser = require('body- calls
parser'); res.json({
let jwt = require('jsonwebtoken'); success: true,
let config = require('./config'); message: 'Authentication successful!',
let middleware = require('./middleware'); token: token
class HandlerGenerator { });
login (req, res) { }
let username = req.body.username; else {
let password = req.body.password; res.send(403).json({
let mockedUsername = 'admin'; success: false,
let mockedPassword = 'password'; message: 'Incorrect username or
if (username && password) { password'
if (username === mockedUsername });
&& password === mockedPassword) {
let token = jwt.sign({username: } }
username}, else {
config.secret, res.send(400).json({
{ expiresIn: '24h’ success: false,
// expires in 24 hours message: 'Authentication failed! Please
} ); check the request'
});
} }
App.js

index (req, res) {


res.json({ success: true, message: 'Index page'
}); }}
// Starting point of the server
function main () {
let app = express(); // Export app for other routes to use
let handlers = new HandlerGenerator();
const port = process.env.PORT || 8000;
app.use(bodyParser.urlencoded({ // Middleware
extended: true
}));
app.use(bodyParser.json());
// Routes & Handlers
app.post('/login', handlers.login);//login request by client
app.get('/', middleware.checkToken, handlers.index);//get info after checking
app.listen(port, () => console.log(`Server is listening on port: ${port}`));
}
main();
Client Side Implementation

IN ANGULAR
34 Signup, Login & Logout
Adding Signin Component
35

 Login.component.html Creating a login form


<h2 class="page-header">Login </h2>
<form (submit)="onLoginSubmit()">
<div class="form-group">
<label>Username</label>
<input type="text" class="form-control" [(ngModel)]="username" name="username">
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control" [(ngModel)]="password" name="password">
</div>
<input type="submit" class="btn btn-primary" value="Login">
</form>

Username, password values


2-way databinding
import { Component, OnInit } from '@angular/core';
import { AuthService } from '../../services/auth.service';
Login.component.ts
import { Router } from '@angular/router';
import { FlashMessagesService } from 'angular2-flash-messages';
36
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
username: string;
password: string;

constructor(
private authService: AuthService,
private router: Router,
private flashMessage: FlashMessagesService
){}

ngOnInit() {
}

onLoginSubmit(){
const user = {
username: this.username,
password: this.password
}

this.authService.authenticateUser(user).subscribe(data => {
console.log(data);
});
}

}
Creating Service
37

 auth.service.ts
registerUser(user){
let headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.post('http://localhost:8000/users/register', user, {headers: headers})
.map(res => res.json());
}

authenticateUser(username,password){
let headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.post('http://localhost:8000/login', username,password, {headers:
headers})
.map(res => res.json());
}
38
authenticateUser function
39

 Writing authenticateUser function in Login.component.ts


file
this.authService.authenticateUser(user).subscribe(data => {
if(data.success) {
this.authService.storeUserData(data.token, data.user);
this.flashMessage.show('You are now logged in',
{cssClass: 'alert-success', timeout: 5000});
this.router.navigate(['dashboard']);
} else {
this.flashMessage.show(data.msg, {cssClass: 'alert-danger', timeout: 5000});
this.router.navigate(['login']);
}
});

Upon successful login


- Store tokens and user data in local storage (create storeUserData function in auth.service.ts)
- display login success flashMessage
- Redirect to dashboard page
When login fails
- login failed display flashMessage
- Redirect to login page
storeUserData function
40

 Auth.service.ts and storeUserData


authenticateUser(user){
let headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.post('http://localhost:3000/users/authenticate',
user, {headers: headers})
.map(res => res.json());
}

storeUserData(token, user){
localStorage.setItem('id_token', token); Localstorage saved as string
localStorage.setItem('user', JSON.stringify(user));
this.authToken = token;
this.user = user;
}
Dashboard
41

 Upon Successful Login Dashboard

Stored token and user information in localStorage


Logout
42

 Auth.service.ts and logout function


storeUserData(token, user){
localStorage.setItem('id_token', token);
localStorage.setItem('user', JSON.stringify(user));
this.authToken = token;
this.user = user;
}

logout(){
this.authToken = null;
this.user = null; Clear the value of the login variable
localStorage.clear(); Empty local storage
}
Logout HTML
43

 Logout
 Navbar.component.html
<ul class="nav navbar-nav navbar-right">
<li [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}"><a
[routerLinkActive]="['active']" [routerLink]="['/login']">Login</a></li>
<li [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}"><a
[routerLinkActive]="['active']" [routerLink]="['/register']">Register</a></li>
<li><a (click)="onLogoutClick()" href="#">Logout</a></li>
</ul>

Add Logout button to menu


Clicking onLogoutClick () will be executed
onLogoutClick () function in Navbar.component.ts
Logout Feature
44
import { Component, OnInit } from '@angular/core';
import { AuthService } from '../../services/auth.service';
import { Router } from '@angular/router';
import { FlashMessagesService } from 'angular2-flash-messages';

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

constructor(
private authService: AuthService,
private router: Router,
private flashMessage: FlashMessagesService
){}

ngOnInit() {
}

onLogoutClick(){
this.authService.logout();
this.flashMessage.show('You are logged out', {
cssClass: 'alert-success',
timeout: 3000
});
this.router.navigate(['/login']);
return false;
}

}
45 Protected Requests & Auth Guard
Protected Request
46

▪ Token authentication for page requests


▪ Set up accessible pages only by presenting tokens while
logged in
▪ The Dashboard page is only accessible when logged in
▪ The Profile page requires a token to be presented (token
validation on the server)
▪ Server-side http: // localhost: 3000 / users / profile page
already has token authentication enabled
▪ How do I set it up?
Setting up the token authentication service
47

 Add the token authentication service to the getProfile () function


in the Auth.service.ts file.
getProfile(){
let headers = new Headers();
this.loadToken();
headers.append('Authorization', this.authToken);
headers.append('Content-Type', 'application/json');
return this.http.get('http://localhost:3000/users/profile', {headers: headers})
.map(res => res.json());
}

storeUserData(token, user){
localStorage.setItem('id_token', token);
localStorage.setItem('user', JSON.stringify(user));
this.authToken = token;
this.user = user;
}

loadToken(){
const token = localStorage.getItem('id_token');
this.authToken = token;
}
profile.component.ts
48

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


import { AuthService } from '../../services/auth.service';
import { Router } from '@angular/router';

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

constructor(
private authService: AuthService,
private router: Router
){}

ngOnInit() {
this.authService.getProfile().subscribe(profile => {
this.user = profile.user;
},
err => {
console.log(err);
return false;
});
}
}
Profile
49

 Profile.component.html

Display user information only when logged in


Create div area only if user information user exists

<div *ngIf="user">
<h2 class="page-header">{{user.name}}</h2>
<ul class="list-group">
<li class="list-group-item">Username: {{user.username}}</li>
<li class="list-group-item">Email: {{user.email}}</li>
</ul>
</div>
Thank you!

You might also like