Kselax.ru

Hacker Kselax – the best hacker in the world

Menu
  • Blog
  • Contacts
  • wp plugin generator
  • English
    • Русский
Menu
jwt authentication with passport.js

How to use JWT with passport.js

Posted on 18 May, 201918 May, 2019 by admin

#Content table:

  • Preface
  • Installation
  • Create the authentication router
  • Implementation of a JWT protected router
  • Test the JWT authentication and authorization
  • Conclusions
  • A few words about https and http
  • all the code files /routers/auth.js, /routers/users.js, /app/passport.js and app.js
  • Resources

 

#Preface

JWT is a json web token. It is used for authentication between server and client. So to implement it in a node.js we are going to use such modules:

  1. passport – to set up log in middleware
  2. passport-local – to create a user authentication router
  3. passport-jwt – to create a user authorization router
  4. jsonwebtoken – to generate a JWT itself

So let’s get started.

 

#Installation

we have to install four this module

1
npm i passport passport-local passport-jwt jsonwebtoken

 

#Create the authentication router.

We need a router where a user will send username and password and we will check it and send back a JWT. To implement this we’ll need a passport and its passport.authentication middleware where we use a passport-local.

let’s create a file /routers/auth.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const express = require('express')
const router = express.Router()
const jwt = require('jsonwebtoken')
const passport = require('passport')
 
/* POST login. */
router.post('/login', (req, res, next) => {
  passport.authenticate('local', {session: false}, (err, user, info) => {
    console.log('here we are2 user = ', user);
 
    if (err || !user) {
      return res.status(400).json({
        message: 'Something is not right',
        user: user
      })      
    }
 
    req.login(user, {session: false}, (err) => {
      if (err) {
        res.send(err)
      }
 
      // generate a signed json web token with the contents of user object and return it in the response
 
      const token = jwt.sign({user}, 'your_jwt_secret')
      return  res.json({ user, token })
    })
  })(req, res)
})
 
module.exports = router

 

and include somewhere in the app.js

1
2
3
...
app.use('/auth', require('./routes/auth.js'))
...

 

here is

1
2
3
...
req.login(user, {session: false}, (err) => {
...

req.login is a passport function which logs in the user it accepts callback function where we generate jwt by using a nodejs module jsonwebtoken

 

1
2
3
...
const token = jwt.sign({user}, 'your_jwt_secret')
...

we need a your_jwt_secret and this function jwt.sign accept a lot of parameters

 

1
2
3
...
passport.authenticate('local', {session: false}, (err, user, info) => {
...

here is a call passport.authenticate function where we apply a “local” as a first parameter that will invoke a passport-local strategy and its strategy will have a code of authentication users. So let’s implement this piece of code

 

Let’s create a file /app/passport.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const LocalStrategy = require('passport-local').Strategy
 
 
module.exports = (passport) => {
 
  passport.use(new LocalStrategy(
    (username, password, done) => {
      console.log('here we are');
      // here should be a look up to the database for username and password and comparison with an accepted username and password
      user = "neo"
      return done(null, user, { message: 'Logged In Successfully' })
    }))
 
}

passport.use is a function, which accepts strategies, in this case, LocalStrategy and a callback function where we pass username, password and a callback function done. Here should be a lookup to the database or whatever for username and password and compare with a passed username and password and if they equal we’ll return a callback done with a user.

Ok, so far so good! We have an authentication router which generates and return a JWT token. The next we need to create a protected router where users will send their requests with tokens and get resources

 

#Implementation of a JWT protected router

A router will have a url site.com/users/*. Everything being requested to site.com/users/* will require JWT authentication. To realize JWT authentication we’are going to use passport-jwt strategy. So let’s add the strategy to the /app/password.js file where is already a local strategy

a file /app/passport.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
...
const passportJWT = require('passport-jwt')
const JWTStrategy = passportJWT.Strategy
const ExtractJWT = passportJWT.ExtractJwt
 
 
module.exports = (passport) => {
...
  passport.use(new JWTStrategy({
    jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(),
    secretOrKey: 'your_jwt_secret'
  }, (jwtPayload, done) => {
    // find the user in db if needed. This functionality may be omitted if you store everything you'll need in JWT payload.
    console.log('jwtPayload = ', jwtPayload)
    const user = "here I am"
    return done(null, user)
  }))
}

 

we need ExtractJWT which is a special object of a passport-jwt strategy

1
2
3
...
const ExtractJWT = passportJWT.ExtractJwt
...

which helps us extract a jwt token from the request

1
2
3
...
jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(),
...

The token uses a bearer header. It’s a special header which is used to pass a JWT from a client to a server, they are nothing special but text. As we can see there is a special function fromAuthHeaderAsBearerToken to get it.

 

1
2
3
...
}, (jwtPayload, done) => {
...

JWTStrategy accepts a unanimous callback function, which accepts two arguments jwtPayload and callback done to send the data to the user. Here we can do a lookup to the database to find additional user parameters or not if you enough from the payload.

So, the next left to create a router itself.

Let’s create a file /routers/users.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const express = require('express')
const router = express.Router()
 
/* GET users listing. */
router.get('/', (req, res, next) => {
  res.send('respond with a resource')
})
 
/* GET user profile */
router.get('/profile', (req, res, next) => {
  res.send(req.user)
})
 
module.exports = router

here is nothing special to explain.

 

Now, let’s include the file to the express middleware.

Somewhere in the app.js

1
2
3
4
5
...
app.use('/users',
  passport.authenticate('jwt', {session: false}),
  require('./routes/users.js'))
...

here is we add a passport.authenticate middleware function before including the router. As you can see it uses ‘jwt‘ authenticate strategy that was already be created in the /app/passport.js file.

That’s it!

 

#Test the JWT authentication and authorization

We’ll be using a postman to test, here is an animation how it is going on

jwt authentication with passport.js

 

#Conclusions

So now, everything should work. We created the authenticate login router and the protected router.
The authenticate login router uses passport-local strategy and the protected router uses passport-jwt strategy.
The authenticate login router generates a JWT token by using a nodejs module jsonwebtoken
Clients have to pass the token as a bearer header and it will be extracted in the protected router in the passport-jwt authentication callback function. So that’s it! A simple JWT + passport.js authentication is done.

 

#A few words about https and http

It is inappropriate to use JWT token over http. Why? Because somebody in the middle can get the token as http passes data as plain text. Using JWT token everybody can connect to the protected router. So we have to encrypt the passed data by using https. https encrypts everything even headers so that the JWT token is protected.

Always use https with JWT. Never pass data as plain text

 

#all the code files /routers/auth.js, /routers/users.js, /app/passport.js and app.js

Показать »

/routers/auth.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const express = require('express')
const router = express.Router()
const jwt = require('jsonwebtoken')
const passport = require('passport')
 
/* POST login. */
router.post('/login', (req, res, next) => {
  passport.authenticate('local', {session: false}, (err, user, info) => {
    console.log('here we are2 user = ', user);
 
    if (err || !user) {
      return res.status(400).json({
        message: 'Something is not right',
        user: user
      })      
    }
 
    req.login(user, {session: false}, (err) => {
      if (err) {
        res.send(err)
      }
 
      // generate a signed json web token with the contents of user object and return it in the response
 
      const token = jwt.sign({user}, 'your_jwt_secret')
      return  res.json({ user, token })
    })
  })(req, res)
})
 
module.exports = router

 

/routers/users.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const express = require('express')
const router = express.Router()
 
/* GET users listing. */
router.get('/', (req, res, next) => {
  res.send('respond with a resource')
})
 
/* GET user profile */
router.get('/profile', (req, res, next) => {
  res.send(req.user)
})
 
module.exports = router

 

/app/passport.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const LocalStrategy = require('passport-local').Strategy
const passportJWT = require('passport-jwt')
const JWTStrategy = passportJWT.Strategy
const ExtractJWT = passportJWT.ExtractJwt
 
 
module.exports = (passport) => {
 
  passport.use(new LocalStrategy(
    (username, password, done) => {
      console.log('here we are');
      user = "neo"
      return done(null, user, { message: 'Logged In Successfully' })
    }))
 
 
  passport.use(new JWTStrategy({
    jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(),
    secretOrKey: 'your_jwt_secret'
  }, (jwtPayload, cb) => {
    // find the user in db if needed. This functionality may be omitted if you store everything you'll need in JWT payload.
    console.log('jwtPayload = ', jwtPayload)
    const user = "here I am"
    return cb(null, user)
  }))
}

 

app.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
 
const passport = require('passport')
 
var app = express();
 
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
 
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
 
// we don't use this as we do with sessions
// app.use(passport.initialize())
// app.use(passport.session())
 
app.use('/auth', require('./routes/auth.js'))
app.use('/users',
  passport.authenticate('jwt', {session: false}),
  require('./routes/users.js'))
 
// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});
 
// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};
 
  // render the error page
  res.status(err.status || 500);
  res.render('error');
});
 
const server = require('http').Server(app)
 
// adding passport's strategies local and jwt
require('./app/passport.js')(passport)
 
module.exports = { app, server };

 

 

#Resources:

  1. Learn using JWT with Passport authentication
  2. jsonwebtoken
  3. passport.js
  4. jwt.io

 

 

the end

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Categories

  • bash (1)
  • English (9)
  • JavaScript (4)
  • node.js (22)
  • photoshop (1)
  • php (3)
  • React (9)
  • sclerotic (6)
  • Ubuntu (10)
  • Uncategorized (13)
  • Wordpress (1)

Tags

Ajax apache2 automation bash chrome-extension command line editor ejs email English English-grammar framework functions git graphql handlebars hybrid app installation javascript js linux newbie node.js node.js javascript nodemailer npm objects Performance php phpmyadmin playonlinux promise rabbitmq React react-router redis reverse-proxy session shell socket.io sublime text 3 time zones ubuntu unity webpack

Recent Comments

  • damien on How to install npm and nodejs the latest versions on ubuntu
  • Cam on How to install npm and nodejs the latest versions on ubuntu
  • Pierre on socket.io with apache as a reverse proxy on the CentOS
  • admin on How to use react-router with a few languages
  • admin on How to install npm and nodejs the latest versions on ubuntu
©2021 Kselax.ru Theme by ThemeGiant