The below code will works perfectly If I add the serialize/deserialize passportjs method, which creates a session. I am working to create Json Web Token, not session. Any tutorial, suggestion or clear sample would be greatly appreciated.I use nodejs.
I understood the pro/con and basic overview of how JWT works. I learned it from the following source.
/
No JWT code
var express = require("express"),
path = require("path"),
bodyParser = require("body-parser"),
mysql = require("mysql"),
connection = require("express-myconnection"),
morgan = require("morgan"),
app = express(),
passport = require("passport"),
GoogleStrategy = require("passport-google-oauth").OAuth2Strategy;
app.use(passport.initialize());
app.get("/", function(req, res) {
res.sendFile(__dirname + "/public/main.html");
});
// #1
passport.use(
new GoogleStrategy({
clientID: "32434m",
clientSecret: "23434",
callbackURL: "http://localhost:3000/auth/google/callback"
},
function(accessToken, refreshToken, profile, done) {
process.nextTick(function() {
console.log("profile.id: " + profile.id);
return done(null, profile.id); // that is being serealized(added in session)
});
}
)
);
// #1
app.get("/auth/google",
passport.authenticate(
"google", {
scope: ["profile", "email"]
}));
// #2
app.get("/auth/google/callback",
passport.authenticate("google", {
failureRedirect: "/google_callback_fail",
successRedirect: "/google_callback_success"
})
);
app.get("/google_callback_success", isLoggedIn, function(req, res) {
res.send("google_callback_success \n");
});
function isLoggedIn(req, res, next) {
console.log("isLoggedIn req.user: " + req.user);
if (req.isAuthenticated()) {
console.log("isAuthenticated TRUE");
return next();
}
res.redirect("/notloggedin");
}
app.get("/notloggedin", function(req, res) {
console.log("req.user: " + req.user);
res.json("not loggedin");
});
app.get("/google_callback_fail", function(req, res) {
res.json("the callback after google DID NOT authenticate the user");
});
app.listen(3000);
JWT code attempt. The problem is I need to add serialize/deserialize, which I don't want to, since, I don't want to use session. I want JWT
var express = require("express"),
path = require("path"),
bodyParser = require("body-parser"),
mysql = require("mysql"),
connection = require("express-myconnection"),
morgan = require("morgan"),
app = express(),
passport = require("passport"),
GoogleStrategy = require("passport-google-oauth").OAuth2Strategy,
jwt = require('jsonwebtoken'),
passportJWT = require("passport-jwt"),
ExtractJwt = require('passport-jwt').ExtractJwt,
JwtStrategy = require('passport-jwt').Strategy;
var jwtOptions = {};
jwtOptions.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
jwtOptions.secretOrKey = 'secret';
app.use(passport.initialize());
app.get("/", function(req, res) {
res.sendFile(__dirname + "/public/main.html");
});
// #1
passport.use(
new GoogleStrategy({
clientID: "s-s.apps.googleusercontent.com",
clientSecret: "23redsf",
callbackURL: "http://localhost:3000/auth/google/callback"
},
function(accessToken, refreshToken, profile, done) {
process.nextTick(function() {
console.log("\nprofile.id: " + profile.id);
return done(null, profile.id); // that is being serealized(added in session)
});
}
)
);
// #1
app.get(
"/auth/google",
passport.authenticate(
"google", {
scope: ["profile", "email"]
}
)
);
// #2
app.get(
"/auth/google/callback",
passport.authenticate("google", {
failureRedirect: "/google_callback_fail",
successRedirect: "/google_callback_success"
})
);
app.get("/google_callback_success", isLoggedIn, function(req, res) {
var payload = { id: user.id };
var token = jwt.sign(payload, jwtOptions.secretOrKey);
var strategy = new JwtStrategy(jwtOptions, function(jwt_payload, next) {
console.log('payload received', jwt_payload);
console.log('jwt_payload.id: ' + jwt_payload.id);
});
passport.use(strategy);
res.send("google_callback_success \n" + 'token: ' + token);
});
function isLoggedIn(req, res, next) {
console.log("isLoggedIn req.user: " + req.user);
if (req.isAuthenticated()) {
console.log("isAuthenticated TRUE");
var payload = { id: user.id };
var token = jwt.sign(payload, jwtOptions.secretOrKey);
console.log('token: ' + token);
return next();
}
res.redirect("/notloggedin");
}
app.get("/notloggedin", function(req, res) {
console.log("req.user: " + req.user);
res.json("not loggedin");
});
app.get("/google_callback_fail", function(req, res) {
res.json("the callback after google DID NOT authenticate the user");
});
app.get("/logout", function(req, res) {
console.log("logged out");
req.logout();
res.redirect("/logout");
});
app.listen(3000);
The code return done(null, profile.id); // that is being serialized(added in session) is the problem. What should I replace it so that I don't have to use sessions? I want to replace it with JWT.
For this, we’ll be using Passport.js, an authentication package for Node.js. We can create a client ID and client secret using its Google API Console. You need to follow below steps once you open Google API Console From the project drop-down, select an existing project, or create a new one by selecting Create a new project
Passport JS is a middleware for express.js. (I will explain about middlewares below). Passport JS supports various login types, Token, Local (username, password), OAuth, OAuth2, etc. We can combine these to authenticate by signing in with Google, FB, or whatever service with a very minimal amount of code.
This can be achieved by opening the google auth screen in a new window and writing the JWT back using window.postMessage ().
If authentication succeeds, passport.authenticate () middleware calls the next function in the stack. In this example, the function is redirecting the authenticated user to the home page. When authentication fails, the user is re-prompted to sign in and informed that their initial attempt was not successful.
https://www.sitepoint.com/spa-social-login-google-facebook/
basically after google authentication is done, you create a jwt for the user.
// src/index.js
function generateUserToken(req, res) {
const accessToken = token.generateAccessToken(req.user.id);
res.render('authenticated.html', {
token: accessToken
});
}
app.get('/api/authentication/google/start',
passport.authenticate('google', { session: false, scope:
['openid', 'profile', 'email'] }
));
app.get('/api/authentication/google/redirect',
passport.authenticate('google', { session: false }),
generateUserToken
);
After a long time spent trying to find a workaround, I finally came across this. The best option thus far, works perfectly for me.
app.get('/auth/google/callback',
passport.authenticate('google',
{ failureRedirect: '/', session: false }), (req, res) => {
const jwt = createJWTFromUserData(req.user);
const htmlWithEmbeddedJWT = `
<html>
<script>
// Save JWT to localStorage
window.localStorage.setItem('JWT', '${jwt}');
// Redirect browser to root of application
window.location.href = '/';
</script>
</html>
`;
res.send(htmlWithEmbeddedJWT);
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With