Nodejs TokenError: Code was already redeemed - node.js

I attempted to login to my application which utilizes the Google OAuth flow. I have successfully logged in to this application in the past by going to
localhost:5000/auth/google
When I select my email, the process just hangs for about a minute and then I get the:
TokenError: Code was already redeemed.
which occurs at localhost:5000/auth/google/callback, which I thought perhaps that would not be a problem because it is a route that is in my authRoutes.js file below:
const passport = require('passport');
module.exports = (app) => {
app.get(
'/auth/google',
passport.authenticate('google', {
scope: ['profile', 'email']
})
);
app.get('/auth/google/callback', passport.authenticate('google'));
app.get('/api/logout', (req, res) => {
req.logout();
// prove to whoever is
// making request that
// they are no longer signed in
res.send(req.user);
});
app.get('/api/current_user', (req, res) => {
res.send(req.user);
});
};
I thought I would check by going to localhost:5000/api/current_user which should be rendering the googleID and _id of the user as an object, but instead I get a blank screen which means I am not successfully logged in.
I am not sure what is going on here.

When you are attempting to go through the Google OAuth flow in your local application and it just hangs, that is not a problem. Your issue was that you did not have your MongoDB database running, so it was difficult for your application to verify if this was a new user or an old user logging in based off whats stored in the database.

Related

Google Api redirection with passport

I have a google auth API in my app, can I somehow attach user data with redirect function? Or how can I see if the user logged in at my react app.
For example here I'm sending username in my request field, but I don't know the way to access it...
router.get('/google/redirect', passport.authenticate('google'), (req, res) => {
res.redirect('http://localhost:3100/login1/' + req.user.username);
});
Thanks in advance!
you have to request the authentication flow alike this:
router.get('/auth/login',
(req, res, next) => {
// Save the url of the user's current page so the app can redirect back to it after authorization
if (req.query.return) {req.session.oauth2return = req.query.return;}
next();
},
// Start OAuth 2 flow using Passport.js
passport.authenticate('google', { scope: ['email', 'profile'] })
);
and then handle the post-back alike this:
// OAuth 2 callback url.
// Use this url to configure your OAuth client in the Google Developers console.
router.get('/auth/google/callback',
// Finish OAuth 2 flow using Passport.js
passport.authenticate('google'), (req, res) => {
// Redirect back to the original page, if any
const redirect = req.session.oauth2return || '/';
delete req.session.oauth2return;
res.redirect(redirect);
}
);
while your localhost does not have any route-able IP, therefore you will never receive any post-back. hosting the script on-line (with a publicly route-able IP) is required to make it work "as expected".

Unable to reach to the redirecting URL while using passport-google-oauth20

I just started to learn OAuth. I am using passport-google-oauth20 with node.js. Below is the code from the passport-setup.js file of my project.
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20');
const keys = require('./keys')
passport.use(
new GoogleStrategy({
//options for google strategy
callbackURL:'https://localhost:3000/auth/google/redirect',
clientID:keys.google.clientID,
clientSecret:keys.google.clientSecret
}, function(){
//passport callback function
})
);
Code from the auth-route.js file of my project
const router = require('express').Router();
const passport = require('passport');
//auth login
router.get('/login', function(req,res){
res.render('login');
});
//auth logout
router.get('/logout', function(req,res){
//have to handle with passport
res.send('Logging out');
});
//auth with google
router.get('/google', passport.authenticate('google',{
scope:['profile']
}));
//callback route for google
router.get('/google/redirect', passport.authenticate('google'),
function(req,res){
res.send('You logged in');
});
module.exports = router;
Can refer to full code # https://github.com/Ayush-Porwal/OAuth-learning.git
I am trouble with redirect URL. When callbackURL holds the value of "https://localhost:3000/auth/google/redirect", then browser directs me to OAuth consent screen. However, after when I try logging in, the browser(chrome) gives me an error/message as shown in the screenshot.
while on Firefox, the message is as shown(adding only because of error messages are different )
And when callbackURL hold the value of "/auth/google/redirect"(I think both values should give same results). The browser gives the error as
Here is the screenshot for the URI's that I entered in my app on google developer's website.
I tried several things like changing the code a little etc but I'm not able to realize where the problem is arising. Please help.
The process is incomplete. I have now completed my project and I have written an answer regarding the same. Please follow up from here to my answer on Google Oauth giving code redeemed error

NodeJS + Passport.js - no session stored?

I have a problem with sessions in my app. I'm trying to learn Passport.js based on this tutorial: http://www.sitepoint.com/local-authentication-using-passport-node-js/ . What I want to do is to allow the acccess for only authenticated users. The process of login works great, but when I check if the user is authenticated, it always says not. What could go wrong?
Here is the checking function:
if (req.isAuthenticated()) {
return next();
else {
res.redirect('/');
}
Here is the path from the router:
router.get('/secret', isAuthenticated, function(req, res) {
res.send('Welcome to the secret page');
});
I didn't find any domunentation about how to check if the session was established, where it is and so on.
Try this, taken from passport.js documentation.
app.get('/secret', passport.authenticate('local'), function(req, res) {
// If this function gets called, authentication was successful.
// `req.user` contains the authenticated user.
});
http://passportjs.org/guide/authenticate/

Cookie detection inbetween Express and Passport

Users visiting http://localhost/login are instantly redirected to Facebook for confirmation of application usage. Once authorized, Facebook contacts http://localhost/login?code= with a special code that allows the server to obtain the user's information such as their name and gender.
Express().get('/login', Passport().authenticate('facebook', {
failureRedirect: 'http://localhost/',
}), function(req, res) {
database.saveData(req.user, **randomlyGeneratedHash**);
res.cookie('session', **randomlyGeneratedHash**);
res.end();
});
This works as expected, but when authenticated users visit the /login in succession, the whole process is repeated and they get a new cookie.
Is there a way that I can run some code inbetween Express and Passport, to stop Passport from redirecting to Facebook if the user has a valid cookie already?
You can use something similar to ensureAuthenticated on your /login route:
var CheckIfAlreadyLoggedIn = function(req, res, next) {
if (req.isAuthenticated()) {
return res.redirect('/'); // or where you want them to go
}
next();
};
Express().get('/login', CheckIfAlreadyLoggedIn, Passport().authenticate('facebook', ...));
This would redirect users that are already logged in back to / when they try to access /login.

accessing session variables in redirected file in node.js

I am building a crappy login system as a newbie. I have done this so far:
app.post("/verifyLogin",function(request,response){
var usr=request.body.username;
var pass=request.body.password;
userModel.find({$and:[{username:usr},{password:pass}]},function(err,user){
if(user.length==0)
{
response.redirect("/?msg=failed");
}
else
{
request.session.user=user;
response.redirect("/dashboard");
}
});
});
This works fine but after successful login i want to get the user details in the dashboard. I am clueless. Please shed some light.
EDIT
I have the following setup for dashboard in routes:
app.get("/dashboard",function(request,response){
response.sendfile('/lms/site/dashboard.html');
});
If you mean you want to pass the users' details to a template:
app.get('/dashboard', function(req, res) {
res.render('dashboard', {
user : req.session.user
});
});
This assumes a few things though:
you have a working templating setup;
you have a template called dashboard (with an extension matching your templating setup);
you're going to provide some sort of setup to make sure a user is logged in before they can open /dashboard.
EDIT: since you don't want to use templating, you could use AJAX to get the user details from the server into the client:
// server side
app.get('/userdata', function(req, res) {
// check if a user is logged in
...
// return the user details as JSON
res.send(req.session.user);
});
// client side (in 'dashboard.html', this assumes is will load jQuery)
$.getJSON('/userdata', function(user) {
// process user data, insert it into the DOM somewhere...
});
EDIT 2: to check if a user is logged in, you could create a middleware which would check for the existence of req.session.user and redirect to the login page if it's undefined:
var isLoggedIn = function(req, res, next) {
if (req.session && req.session.user)
next(); // user logged in, so pass
else
res.redirect('/'); // not logged in, redirect to login page
};
You would use the isLoggedIn middleware for all routes that require a user to be logged in:
app.get('/userdata', isLoggedIn, function(req, res) {
res.send(req.session.user);
});

Resources