Node.js use passport with LocalStrategy in Authentication Part 3

Add Session      

       In this post, we will use passport Local Strategy combined with Session to store user status. We will start from the result in part 1 (use passport default manner). We can remind the usage of session in the post cookie and session.

        As far as I learn, the workflow of Passport and Session will be like below picture. Passport has serialized the userInfo that you passed into the callback(cb) in Strategy verify function. The information is saved into server session storage. When the user access the server later, the server retrieve user content in session storage according to the session ID in the cookie of user request. Passport automatically deserialize the content and load it to req.user (1st argument of handler of route). Then we can access user information in the body of the handler function.


        To implement, first we install the session module npm install express-session. Then, we import the session and add into express as middleware (app.use()). We can find the meaning of each property that passed to session in express-session website. We have to care for the session storage. The default way here is only for development and demonstration. We should specify the storage (regis, sqlite...) in production and release. We enable the passport to use session in authentication. The code now change to follows.

import express from "express";
import bodyParser from "body-parser";
import passport from "passport";
import {Strategy} from "passport-local";
import session from "express-session";

const app = express();

const PORT = 6000;

app.use(bodyParser.urlencoded({extends:false}));
app.use(bodyParser.json());

app.use(session({
secret: 'you should keep this in secret',
resave: false,
saveUninitialized: false,
}));

app.use(passport.authenticate('session'));

        Next, we need to implement passport.serializeUser() and passportdeserializeUser() method so that passport module can save user information into session after authentication and retrieve information back from session when the user request service afterward. 

         You have chance to select what property is going to be stored in the session in serializeUser() function.

passport.serializeUser(function(user, cb) {
process.nextTick(function() {
cb(null, { id: user.id, name: user.name });
});
});


passport.deserializeUser(function(user, cb) {
process.nextTick(function() {
return cb(null, user);
});
});

 The last thing, we need to delete the session:false property in the passport.autenticate() function. Now the passport can save userInfo to session. 

app.post(
"/login",
passport.authenticate(
"local",
{
successRedirect: "/secrets",
failureRedirect: "/login",
//session:false
}
)
);

I have modified the handler body of app.get("/secrets"). It will print the content of session in server console and return message contained user id and user name to the client.

app.get("/secrets", (req, res) =>{
console.log(req.session);
return res.send("This is secrets page. User " + req.user?.id
+ " name " + req.user?.name + " has access this route");
});

 Here is the console of server

Session has a property named "passport", which is a object having "user" object
 and  feedback of postman.

Postman receive message that have user id and user name

        We can find the code(file v2.1) in github that used at this stage.

Restrict access for some pages

         Now we can check the client if it has logined before by checking the content of req.user. This allow us to restrict anonymous access to some API service.

        From code v2.1, we can receive the secrets page message even we haven't login before (delete postman cookie and request GET /secrets again). We want to protect this route. We just call req.isAuthenticated() to check if the client has login before or not. isAuthenticated() return true if req.user has user property.

app.get("/secrets", (req, res) =>{
if(!req.isAuthenticated())
return res.redirect("/login");
console.log(req.session);
return res.send("This is secrets page. User " + req.user?.id
+ " name " + req.user?.name + " has access this route");
});

         Now, the server to redirect to GET /login and return login message to us when we call GET /secrets before login.

        You can find the code(v2.2) for this version in github.

 To find more explanation and example in passport website

Comments

Popular posts from this blog

Use okhttp to download file and show progress bar

Download File into app specific storage with Retrofit

Unzipp file with Zip4j library