Node jS express Authenticate facebook API - javascript

hello i new in backend and want to make a Authenticate facebook api with node js using express and i use passport but its not work and give me a page of html code as a response to sign in with facebook account this can handle when use web page the api may use with mobile application
my passport file that i use
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcryptjs');
const passport = require('passport')
const FacebookStrategy = require('passport-facebook').Strategy;
// Load User model
const User = require('../Schema/user');
// ---------------- Local Auth -------------- //
passport.use(
new LocalStrategy({ usernameField: 'email' },
(email, password, done) => {
// Search For Match user
User.findOne({ email: email }).then(user => {
if (!user) {
console.log("That email is not registered")
return done(null, false, { message: 'That email is not registered' });
}
// Compare the Two Password password
bcrypt.compare(password, user.password, (err, isMatch) => {
// if (err) throw err;
if (err) {
console.log(err)
return done(err);
}
if (isMatch) {
console.log("matching email");
return done(null, user);
} else {
console.log("Password incorrect");
return done(null, false, { message: 'Password incorrect' });
}
});
});
})
);
//------------------ Facebook Auth ---------------//
passport.use(new FacebookStrategy({
clientID: process.env.FACEBOOK_APP_ID,
clientSecret: process.env.FACEBOOK_APP_SECRET,
ccallbackURL: "/auth/facebook/callback",
profileFields: ['id', 'emails', 'name'],
},
async (accessToken, refreshToken, profile, done) => {
try {
const userData = {
firstName: profile._json.first_name.toLowerCase(),
lastName: profile._json.last_name.toLowerCase(),
email: profile._json.email,
isConfirmed: true,
};
// const user = await userService.registerWithThirdParty(userData);
done(null, user);
} catch (error) {
console.error(error.message);
done(null, false);
}
}
));
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
module.exports = passport;
my index.js file
router.get("/auth/facebook", passport.authenticate("facebook"));
router.get("/auth/facebook/callback",
function (req, res, next) {
passport.authenticate('facebook', function (err, user, info) {
if (err) { return next(err); }
if (!user) { return res.json({ message: info.message }) }
req.logIn(user, function (err) {
if (err) { return next(err); }
return res.json({ msg: "succes Login", user: user });
});
})(req, res, next);
}
);
when i use local signup or login it work but when i use facebook login dont work and give me a full html to sign in and i cant handled it in my api.
hint : i use passport-facebook

you can use this script to make authentication to facebook + passport js:
user.controller.js
import passport from "passport";
import dotenv from "dotenv";
import strategy from "passport-facebook";
import userModel from "../user/user.model";
const FacebookStrategy = strategy.Strategy;
dotenv.config();
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
passport.use(
new FacebookStrategy(
{
clientID: process.env.FACEBOOK_CLIENT_ID,
clientSecret: process.env.FACEBOOK_CLIENT_SECRET,
callbackURL: process.env.FACEBOOK_CALLBACK_URL,
profileFields: ["email", "name"]
},
function(accessToken, refreshToken, profile, done) {
const { email, first_name, last_name } = profile._json;
const userData = {
email,
firstName: first_name,
lastName: last_name
};
new userModel(userData).save();
done(null, profile);
}
)
);
user.router.js
import express from "express";
import passport from "passport";
import userController from "./user.controller";
const userRouter = express.Router();
userRouter.get("/auth/facebook", passport.authenticate("facebook"));
userRouter.get(
"/auth/facebook/callback",
passport.authenticate("facebook", {
successRedirect: "/", // to add check you can use this value successRedirect also the next value failureRedirect
failureRedirect: "/fail"
})
);
userRouter.get("/fail", (req, res) => {
res.send("Failed attempt");
});
userRouter.get("/", (req, res) => {
res.send("Success");
});
export default userRouter;
index.js
import express from "express";
import { json } from "body-parser";
import passport from "passport";
import { connect } from "./utils/db";
import userRouter from "./user/user.routes";
const app = express();
const port = 3000;
app.use(passport.initialize());
app.use(json());
app.use("/", userRouter);
app.listen(port, async () => {
await connect();
console.log(`Server listening on ${port}`);
});

Related

Passport only redirect "failureRedirect: '/login?fail=true'"

I'm using Passport js local strategy but I can't redirect from my admin page. it always fails even if the login and password are correct, below is the auth.js and login.js code
login.js
router.get('/', (req, res, next) =>{
if (req.query.fail){
res.render('admin/login', {layout: 'admin.hbs', message: "Usuario e/ou Senha invalidos"});
}else{
res.render('admin/login', {layout: 'admin.hbs', message: null});
}
})
router.post('/',
passport.authenticate('local', { failureRedirect: '/login?fail=true' }),
function(req, res) {
res.redirect('/admin');
});
auth.js
const users = [{
_id: 123,
username: "adm",
password: hashedPassword
}];
console.log(users);
module.exports = function(passport){
function findUser(username){
return users.find(item => item.username === username);
}
function findUserById(id){
return users.find(item => item._id === id);
}
passport.serializeUser((user, done) => {
done(null, user._id);
});
passport.deserializeUser((id, done) => {
try {
const user = findUserById(id);
done(null, user);
} catch (err) {
console.log(err);
return done(err, null)
}
});
passport.use(new localStrategy({
usernameField: 'username',
passwordField: 'password',
},
(username, password, done) => {
try{
const user = findUser(username).then(user);
if(!user) return done(null, false);
const isValid = bcrypt.compare(password, user.password);
if(!isValid) return done(null, false);
return done(null, user);
}
catch(err){
console.log(err);
return done(err, false)
}}));
}
I don't know why it's not working, I wanted help getting into the admin page

Error: Unknown authentication strategy "spotify"

I get an error when i try out my code 'Error: Unknown authentication strategy "spotify"'. I even tried googling this issue but can't didn't find an answer
Update: I updated my code to give answers to a person that is helping me
Code
const passport = require('passport')
const SpotifyStrategy = require('passport-spotify').Strategy
const userWebData = require('../model/userWebSchema')
passport.serializeUser((user, done) => {
const u = user
done(null, u)
})
passport.deserializeUser(async(spotifyID, done)=> {
try{
const data = await userWebData.findOne({ spotifyID: spotifyID})
const user = data
return user ? done( null, user) : done(null, null)
}catch(e){
console.log(e)
done(e, null)
}
})
passport.use(
new SpotifyStrategy({
clientID: 'Clients_ID_That_I_Wont_Show',
clientSecret: 'Clients_Secret_That_I_Wont_Show',
callbackURL: 'http://localhost:3001/',
scope: ["user-modify-playback-state", "user-read-private","user-library-read"]
}, async(accessToken, refreshToken, expires_in, profile, done)=>{
const userData = await userWebData.findOne({ spotifyID: profile.id})
if(userData){
console.log(`User ${profile.displayName} found`)
return done(err, userData);
}else{
let profiles = await userWebData.create(
{
spotifyID: profile.id,
spotifyName: profile.displayName,
spotifyFollowers: profile.followers,
}
)
profile.save()
console.log(`New User ${profile.displayName} Created`)
return done(err, userData);
}
}
)
)
You also have to import the passport-spotify package before authenticating with it. First, install the package (npm i passport-spotify) and then require it in your file:
const SpotifyStrategy = require('passport-spotify').Strategy;
Then, you have to call the passport.use() function before you can authenticate with passport:
passport.use(
new SpotifyStrategy(
{
clientID: client_id,
clientSecret: client_secret,
callbackURL: 'http://localhost:8888/auth/spotify/callback'
},
function(accessToken, refreshToken, expires_in, profile, done) {
User.findOrCreate({ spotifyId: profile.id }, function(err, user) {
return done(err, user);
});
}
)
);
Finally, you can use it as an Express middleware. Your modified code would look something like:
const express = require('express')
const app = express()
const passport = require('passport')
const SpotifyStrategy = require('passport-spotify').Strategy;
passport.use(
new SpotifyStrategy(
{
clientID: client_id,
clientSecret: client_secret,
callbackURL: 'http://localhost:8888/auth/spotify/callback'
},
function(accessToken, refreshToken, expires_in, profile, done) {
User.findOrCreate({ spotifyId: profile.id }, function(err, user) {
return done(err, user);
});
}
)
);
app.get('/', passport.authenticate('spotify'), (req, res)=>{
res.redirect('http://localhost:3001/user')
})
app.get('/user', (req, res) => {
if(req.user == undefined){res.status(401).redirect('http://localhost:3001/')}else{res.send(req.user)}
})
module.exports = app
Refer to http://www.passportjs.org/packages/passport-spotify/

Getting req.user undefined in passportjs?

I have configured passportJS with node express app but when I make login/register request then in that case req.user is undefined any idea what is wrong am I missing something in configuring passport js? I have used express-session and mongoDB store for storing sessions
passport-config.js:
const passport = require("passport");
const LocalStrategy = require("passport-local").Strategy;
const User = require("./Models/userSchema");
passport.use(
new LocalStrategy(
{
usernameField: "email",
passwordField: "password",
},
async (email, password, done) => {
try {
const user = await User.findOne({ email });
// Username/email does NOT exist
console.log("user in config", user);
if (!user) {
return done(null, false, {
message: "Username/email not registered",
});
}
// Email exist and now we need to verify the password
const isMatch = await user.isValidPassword(password);
return isMatch
? done(null, user)
: done(null, false, { message: "Incorrect password bro" });
} catch (error) {
done(error);
}
}
)
);
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(async function (id, done) {
const user = await User.findById(id);
done(null, user);
});
server.js file: https://pastebin.com/NfpvXSFf (see line 39)
I would try:
async (req, res) => {
{email, password, done} = req.body;
(you need a body-parser for that)

how to send error message to client?

I am using passport with local strategy .but I want to send message and status when credential is not match or (user is not exit is DB)
here is code
router.js
const passport = require('passport');
const passportConfig = require('../passport')
const passportSignIn = passport.authenticate('local', { session: false });
router.route('/login',)
.post(passportSignIn,controller.login)
on controller file
login: async (req, res, next) => {
console.log(req.body);
res.json({status:200})
}
passport.js
passport.use(new LocalStrategy({
usernameField: 'email'
}, async (email, password, done) => {
const user = await db.User.findOne({where: {email: email}});
if (!user) {
return done(null, false,{message:"No user exit"});
}
const isMatch = await bcrypt.compare(password, user.dataValues.password);
console.log(isMatch, 'isMatch');
if (!isMatch) {
return done(null, false);
}
// Otherwise, return the user
done(null, user);
}))
Client code
when user click on login button it goes to /login path first it goes to passportSignIn function or below function.
`new LocalStrategy({
usernameField: 'email'
}, async (email, password, done) => {`
now if user not found I want to send this message on the client as the response ("No user exit")
return done(null, false,{message:"No user exit"});
You have to update your login controller, like so:
login: (req, res, next) => {
console.log(req.body);
passport.authenticate('yourStrategy', function(err, user, info) {
if (err) {
return res.status(500).json("Internal Server Error");
}
if (!user) {
// This 'info' variable below would be - { message: "No user exit" }
// as you passed in the done() callback as the third param
return res.status(404).json(info.message);
}
}
}

Basic passport.js signup function fails, thinks username has already been taken

I'm using passport.js to get a basic signup function established for a Node + Express + Sequelize app. Right now I have an empty database, and am using just the passport-local strategy to get the user's email and password from a form, check this against the database to ensure the email is not associated with another account, and then once this has been established, create the user.
Here are the relevant sections of my code:
./config/passport.js
const db = require('./sequelize');
const passport = require('passport'),
LocalStrategy = require('passport-local').Strategy;
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(user, done) {
db.User.findById(id, function(err, user) {
done(err, user);
});
});
passport.use('local', new LocalStrategy({
emailField : 'email',
passwordField : 'password',
passReqToCallback : true
},
function(email, password, done){
process.nextTick(function() {
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
db.User.findOne({ email : email }, function(err, user) {
// if there are any errors, return the error
if (err)
return done(null, false, {message: err});
// check to see if there's already a user with that email
else if (user) {
return done(null, false, {message: 'User already exists'});
}
else {
return done(null, true, {message: 'User created'});
}
});
});
}
));
module.exports = passport;
app.js
app.post('/signup', function(req, res, next){
const user = req.body;
passport.authenticate('local', function(err, user, info){
if (err){
res.send({success: false, message: 'authentication failed'});
}
if (!user) {
console.log(user);
res.send({message: "user already found"});
}
else{
db.User.create({
email: req.body.username,
password: req.body.password
});
console.log(info);
res.json({message: "user successfully signed up"});
}
})(req, res, next)
});
./config/sequelize
const path = require('path');
const Sequelize = require('sequelize');
const _ = require('lodash');
const config = require('./config');
const db = {};
// create your instance of sequelize
const sequelize = new Sequelize(config.db.name, config.db.username, config.db.password, {
host: config.db.host,
port: config.db.port,
dialect: 'mysql',
storage: config.db.storage
});
//Instantiate the database
sequelize
.authenticate()
.then(function(err) {
console.log('Connection has been established successfully.');
}, function (err) {
console.log('Unable to connect to the database:', err);
});
/* this is where all of the MODELS will be defined for the time being */
const User = sequelize.define('User', {
username: Sequelize.STRING,
email: Sequelize.STRING,
password: Sequelize.STRING
});
sequelize.sync();
db.User = User;
db.Sequelize = Sequelize;
db.sequelize = sequelize;
module.exports = db;
However, when I run the app with the clean database, !user in the app.js file evaluates to false, and I am unable to sign up new users because it would seem to be that the strategy thinks there is already an existing user with that email in the database. What do I need to do to remedy situation?
db.User.findOne({ where: { email : email }})
.then(
function(user) {
if (user) {
return done(null, false, {message: 'User already exists'});
} else {
return done(null, true, {message: 'User created'});
);
Try to change your code
using redirects here (app.js):
app.post('/signup', passport.authenticate('local', {
successRedirect : '/profile',
failureRedirect : '/signup',
failureFlash : true
}));
using promises for sequelize queries (./config/passport.js):
passport.deserializeUser(function(id, done) {
db.User.findById(id).then(function(user) {
done(err, user.dataValues);
})
.catch(function(err){
done(err, null);
});
});
passport.use('local', new LocalStrategy({
emailField : 'email',
passwordField : 'password',
passReqToCallback : true
},
function(req, email, password, done){
process.nextTick(function() {
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
db.User.findOne({ where: {email : email }})
.then(function(user) {
if (user !== null) {
done(null, false, {message: 'User already exists'});
}
else {
db.User.create({
email: email,
password: password
})
.then(function(user){
done(null, user);
})
.catch(function(err){
console.log(err);
done(null, false);
});
}
})
.catch(function(err){
// if there are any errors, return the error
return done(null, false, {message: err});
});
});
}
));

Categories