Node.js AUTHORIZE endpoints with Oauth2-Google passport - node.js

I'm trying to develop a simple API in node and hiding it behind a google authentification layer, for that I'm using passport-google-oauth2 to enforce a google authentification to do some requests.
....
var GoogleStrategy = require('passport-google-oauth2').Strategy;
var passport = require('passport');
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
passport.use(new GoogleStrategy({
clientID: CLIENT_ID,
clientSecret: CLIENT_SECRET,
callbackURL: "/oauth2callback",
passReqToCallback : true
},
function(request, accessToken, refreshToken, profile, done) {
console.log("passportUse access Profile ", accessToken);
done(null, accessToken);
}
));
app.get('/oauth2callback',
passport.authenticate( 'google', {
successRedirect: '/notesSuccess',
failureRedirect: '/notesNotSuccess'
}));
app.get('/notes',
passport.authenticate('google', { scope:
[ 'https://www.googleapis.com/auth/plus.login', 'https://www.googleapis.com/auth/drive'] }
), function(req, res) {
//res.json({notes: "This is your notebook. Edit this to start saving your notes!"})
})
app.get('/notesSuccess', function(req, res) {
res.json({notes: "This is your notebook. Edit this to start saving your notes!"})
})
app.get('/notesNotSuccess', function(req, res) {
res.json({notes: "AUTHENTICATION FAIL"})
})
app.get('/notes/API1', function(req, res) {
res.json({notes: "API1111111"})
})
....
The code is working more or less, at passport.use I do get all the google plus profile information and a token, so I assume that part is working.
The issue is that when I use the browser to visit localhost:8080/notes, I get the results as expected (/notesSuccess) when I login, if I'm in a private window I can see the google login page, working well so far.
My problem is if I do a query with postman using the token I was given or a new token with the same scopes I get only the login page (as if I had no Authentification header). If I query notes/API1 (no Oauth there) it works properly
Any ideas why the headers are not authentifing the query?

Related

redirect_uri: http://XXX.herokuapp.com/auth/google/callback error

In the 'Authorized redirect uri's' (Google cloud console, oauth2.0) I put https://XXX.herokuapp.com/auth/google/callback but when I try to sign in it gives me Error 400: redirect_uri_mismatch. But when I change it to 'http', the sign in works. My heroku app is https only. But this causes the rest of the site to be http which isn't good and google itself doesn't let me publish unless the http request is turned to https. I don't know what to do...plz help.
This is my auth.js
const express = require("express");
const router = express.Router();
const passport = require("passport");
//Authenticate with google
//GET /auth/google
router.get("/google", passport.authenticate("google", { scope: ["profile"] }));
//Google auth callback
//GET /auth/google/callback
router.get("/google/callback", passport.authenticate("google", { failureRedirect: "/" }),
function (req, res) {
// Successful authentication, redirect home.
res.redirect("/something");
}
);
router.get("/logout", (req, res) => {
req.logout();
res.redirect("/");
});
module.exports = router;
This is the error when using https as the redirect URI
Authorization Error
Error 400: redirect_uri_mismatch
You can't sign in to this app because it doesn't comply with Google's OAuth 2.0 policy.
If you're the app developer, register the redirect URI in the Google Cloud Console.
Learn more
Request Details
The content in this section has been provided by the app developer. This content has not been reviewed or verified by Google.
If you’re the app developer, make sure that these request details comply with Google policies.
redirect_uri: http://XXX.herokuapp.com/auth/google/callback
So I got the answer, in my passport.js, (which I didn't mention in the question) instead of
"auth/google/callback"
as the callbackURL
I wrote the whole url with https, like this:
https://XXX.herokuapp.com/auth/google/callback
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const mongoose=require("mongoose")
const User=require('../models/User');
module.exports=function(passport){
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: "https://XXX.herokuapp.com/auth/google/callback"
}, async(accessToken, refreshToken, profile, done)=>{
const newUser={
googleId:profile.id,
displayName:profile.displayName,
firstName:profile.name.givenName,
lastName:profile.name.familyName,
image:profile.photos[0].value
}
try {
let user=await User.findOne({googleId:profile.id})
if(user){
done(null,user)
}
else{
user=await User.create(newUser)
done(null,user)
}
} catch (err) {
console.error(err);
}
}))
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
}

Oath facebook error: “URL blocked: This redirect failed because...“ and cannot get

I saw all the possible answers online but I just cannot get this to work and don't understand why. First problem I came across is the usual: "URL Blocked: This redirect failed because the redirect URI is not whitelisted in the app's Client OAuth Settings". After a few hours trial and error, trying every possible way (http, https, www, and without) and I managed the app to save the FacebookId in mongoDB (although didn`t prompt me to the Facebook login page), but right after now I have Cannot GET /auth/facebook message.. Now I know I have an issue already in mondoDB because at this point no multiple account can be saved without and email address as username would be NULL and only one allowed, but after wiping the DB I can sign in with Google oath without and issue so, it seems like I have a problem setting up
Facebook and i just don`t know what im doing wrong. Thank you in advanced!
facebooksettings
facebooksettings2
the site url set to: https://app-secret.herokuapp.com/
app.js
...
//use session package with some setup config//
app.use(session({
secret: 'My little secret.',
resave: false,
saveUninitialized: false,
}))
//initalize passport packadge and for also to deal with the session//
app.use(passport.initialize());
app.use(passport.session());
mongoose.connect("mongodb+srv://andras:MYPASSWORD#cluster0.zfr0d.mongodb.net/userDB", {
useNewUrlParser: true,
useUnifiedTopology: true
});
//schema in order to have a plugin it has to be a mongoose schema//
const userSchema = new mongoose.Schema({
email: String,
password: String,
googleId: String,
facebookId: String,
secret: Array
});
//adding plugins to schema//
userSchema.plugin(passportLocalMongoose);
userSchema.plugin(findOrCreate);
const User = new mongoose.model("User", userSchema);
//configuring passport, serialize=create and deserialize=able to crack open cookie//
passport.use(User.createStrategy());
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
passport.use(new GoogleStrategy({
clientID: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
callbackURL: "https://app-secret.herokuapp.com/auth/google/secrets",
userProfileURL: "https://www.googleapis.com/oauth2/v3/userinfo"
},
function(accessToken, refreshToken, profile, cb) {
// console.log(profile);
User.findOrCreate({
googleId: profile.id
}, function(err, user) {
return cb(err, user);
});
}
));
passport.use(new FacebookStrategy({
clientID: process.env.FACEBOOK_APP_ID,
clientSecret: process.env.FACEBOOK_APP_SECRET,
callbackURL: "https://app-secret.herokuapp.com/auth/facebook"
},
function(accessToken, refreshToken, profile, cb) {
User.findOrCreate({
facebookId: profile.id
}, function(err, user) {
return cb(err, user);
});
}
));
app.get("/", function(req, res) {
res.render("home")
});
app.get("/auth/google",
passport.authenticate('google', {
scope: ["profile"]
})
);
app.get("/auth/google/secrets",
passport.authenticate('google', {
failureRedirect: "/login"
}),
function(req, res) {
// Successful authentication, redirect home.
res.redirect('/secrets');
});
app.get('/auth/facebook',
passport.authenticate('facebook'));
app.get('/auth/facebook/secrets',
passport.authenticate('facebook', {
failureRedirect: '/login'
}),
function(req, res) {
// Successful authentication, redirect home.
res.redirect('/secrets');
});
So sorry to spam stackoverflow with my rookie misery. I realised where i went wrong, i thought the facebook API is the one creating me headache and not realising that the facebook callback in the app.js missing the correct path.. instead of: "app-secret.herokuapp.com/auth/facebook" it should be: "app-secret.herokuapp.com/auth/facebook/secrets"

passport don't redirect to 'failureRedirect' upon failure with facebook

Im using passport to authenticate a user through Facebook.
The successRedirect works great [I'm redirecting into http://localhost:3000/success#_=_], but the failureRedirect doesn't, i'm getting this:
FacebookAuthorizationError: Login Error: There is an error in logging you into this application. Please try again later.
[I'm getting this in my browser-> http://localhost:3000/auth/facebook/callback?error_code=1349003&error_message=Login+Error%3A+There+is+an+error+in+logging+you+into+this+application.+Please+try+again+later.#_=_
Those are my settings:
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function (user, done) {
console.log(user);
done(null, 'this is the user');
})
passport.deserializeUser(function (id, done) {
console.log(id);
done(err, {message: 'this is the user'});
});
router.get('/auth/facebook', passport.authenticate('facebook'));
router.get(
'/auth/facebook/callback',
passport.authenticate('facebook',
{
successRedirect: '/success',
failureRedirect: '/login',
}
),
);
const FacebookStrategy = require('passport-facebook').Strategy;
const facebookStrategy = new FacebookStrategy({
clientID: staretegy.clientId,
clientSecret: staretegy.clientSecret,
callbackURL: staretegy.callbackURL,
profileFields: [
'id',
'first_name',
'middle_name',
'last_name',
],
}, (accessToken, refreshToken, profile, done) => {
done(null, {user: profile});
});
passport.use(facebookStrategy);
As i read in the docs i expected to be redirect to the /login.
/login can be accessed by the browser. (i've also tried to put this full URL path: failureRedirect: http://localhost:3000/login but it won't work, similar URL works with the successRedirect.
This seems an open issue and the main repository barely supported. But you can try to use this fork.
I had a similar issue here and have found a way to handle the error using a middleware error handler (see fbErrorHandler below):
const express = require('express'),
router = express.Router(),
passport = require('passport');
router.get(
'/facebook',
passport.authenticate('facebook')
);
function fbErrorHandler(err, req, res, next) {
// I use flash, but use whatever you want to communicate with end-users:
req.flash('error', 'Error while trying to login via Facebook: ' + err);
res.redirect('/login');
}
router.get('/facebook/callback',
passport.authenticate(
'facebook',
{
failureRedirect: '/login',
failureFlash: true
},
),
fbErrorHandler,
(req, res) => {
// Successful authentication
res.redirect('/authenticated');
}
);
module.exports = router;

social login, vue-authenticate with passport(nodejs)

I'm trying to implement facebook login with vue-authenticate and passport.
I succeeded in logging into my Facebook account. And i got the 'Callback code' successfully.
This is my callback url
http://localhost:8080/auth/callback?code=AQD0FgQ7I2oci0m3bqOHOBE1EV3Ri1TBnVcqs2PRT8pFNa38NIMX-eYiSr2EiWKQBMoNq1yOeo1QkDG1OiDjF_xUduK-HWMlMazsaBzoGNxiAK3FQH5KQopZ9NUnM2g-UYLpihtpsaFrRVssJkm8Xue1nyKbbWX76EPnPCIEVOfGM_JE4mbENLpp6_w8gwkTS9n8dtsNptDM72UO9zE7mj34J8Yls0A1VqmoZail0J2zwu4hJCzAzbP2FZ531Vo2tCERn2F_4DKsJ-zq_ppZWxRlKuRW9WFBL0UvsuNN_ODiRFs70P3SoK85-xHwzHJvx8VrVxmLlp5x7rVOzy2E2Jma#=
So I used axios to pass the 'Callback code' to the server. because my server code(passport-facebook) is this:
router.route('/auth/facebook/callback').get(passport.authenticate('facebook', {
successRedirect : '/',
failureRedirect : '/'
}));
and axois code in Vue is
this.$http.get('/api/users/auth/facebook/callback',{
params:{
code : this.param
}
})
.then((response) => {
this.movies = param;
})
but it never works.. I don't know why. just wondering, i chaneged axios code to get('api/users/'). and wrote server code like this
router.get('/',()=>{
console.log("good");
});
it works. I can see the 'good' message in console.
Let me know how you implement social sign-in!
if you want to configure Facebook login with passport So you can simply follow these Steps As mention below:
Step 1. Add passport configuration
const passport = require('passport');
app.use(passport.initialize());
app.use(passport.session());
app.get('/success', (req, res) => res.send("You have successfully logged in"));
app.get('/error', (req, res) => res.send("error logging in"));
passport.serializeUser(function(user, cb) {
cb(null, user);
});
passport.deserializeUser(function(obj, cb) {
cb(null, obj);
});
Step 2. Setup facebook configuration
const FacebookStrategy = require('passport-facebook').Strategy;
const FACEBOOK_APP_ID = 'your app id';
const FACEBOOK_APP_SECRET = 'your app secret';
passport.use(new FacebookStrategy({
clientID: FACEBOOK_APP_ID,
clientSecret: FACEBOOK_APP_SECRET,
callbackURL: "/auth/facebook/callback"
},
function(accessToken, refreshToken, profile, cb) {
return cb(null, profile);
}
));
app.get('/auth/facebook',
passport.authenticate('facebook'));
app.get('/auth/facebook/callback',
passport.authenticate('facebook', { failureRedirect: '/error' }),
function(req, res) {
res.redirect('/success');
});
This will fix your issue
Please refer this link https://www.sitepoint.com/passport-authentication-for-nodejs-applications/

Passport-facebook unable to connect

In my application, I'm trying to add loggin with facebook account. As I'm using passport for the moment with local strategy, I tried to add the facebook strategy. I registered on facebook developper site to have my token and secret. I simply copy/paste source code portions from the official passport github, adapting to my personal use.
The problem occurs when calling
passport.authenticate('facebook');
I am stuck in here and not redirected to the facebook loggin page. My application is waiting for a reponse or waits to be redirected, but nothing happens. I tried to provide on the facebook developper page my callback URL, and I tried without it (passing the callback throw the passport strategy).
What am I missing ?
My application:
app.get('/auth/facebook', user_routes.facebookLogin);
app.get('/auth/facebook/callback', user_routes.facebookCallback);
My routes:
exports.facebookLogin = function(req, res, next) {
console.log('Try to login with facebook');
passport.authenticate('facebook'); //<---------------- does not go further than here
};
exports.facebookCallback = function(req, res, next){
passport.authenticate('facebook', {
successRedirect: '/home',
failureRedirect: '/login' });
};
My strategy:
passport.use(new FacebookStrategy({
clientID: "xxxxxxxx",
clientSecret: "xxxxxxxxxxx",
callbackURL: "http://localhost:8080/auth/facebook/callback"
},
function(accessToken, refreshToken, profile, done) {
User.findOne({ username: profile.displayName, email: profile.emails[0].value }, function(err, olduser) {
if (err) { return done(err); }
if (olduser) {
return done(null, olduser);
}
else{
var newuser = new User({
username: profile.displayName,
email: profile.emails[0].value
}).save(function(err,newuser){
if(err) console.log(err);
done(null,newuser);
});
}
});
})
);
[EDIT]
Changing the routing for the callback to this solves my issue. However, I dont understand the reason why...
app.get('/auth/facebook/callback',
passport.authenticate('facebook', { failureRedirect: '/login' }),
function(req, res) {
res.redirect('/home');
});
Finally found the solution here:
Using PassportJS with Connect for NodeJS to authenticate Facebook Users
and here:
Facebook Authentication with Passport and ExpressJS - Why is verify callback not called?

Resources