I'm trying to set up Express routes bound with multiple controllers, of course they're supposed to receive functions, this is what I'm trying:
authRouter.get('/login/redirect/:provider', controllers.handleOAuth2Redirect, controllers.jwt);
This has sometimes worked, sometimes not, the only changes when works or not are minimal code changes, could be a require line, an expression, etc.
This is the error being thrown:
Error: Route.get() requires callback functions but got a [object Object]
So following code is the complete working controllers file:
'use strict';
var passport = require('passport');
var FacebookStrategy = require('passport-facebook').Strategy;
var TwitterStrategy = require('passport-twitter').Strategy;
var InstagramStrategy = require('passport-instagram').Strategy;
var OAuth2Strategy = require('passport-oauth2').Strategy;
var facebook_scope = ['email', 'user_about_me','user_friends','publish_actions'];
var passportFacebookOptions = {scope: facebook_scope};
passport.use(new FacebookStrategy({
clientID: process.env.FACEBOOK_FINALCUT_APP_ID,
clientSecret: process.env.FACEBOOK_FINALCUT_APP_SECRET,
callbackURL: 'http://localhost:9248/auth/login/redirect/fb'
},
function (accessToken, refreshToken, params, profile, done) {
return done(null, profile, params);
}));
passport.use(new InstagramStrategy({
clientID: process.env.INSTAGRAM_FINALCUT_CLIENT_ID,
clientSecret: process.env.INSTAGRAM_FINALCUT_CLIENT_SECRET,
callbackURL: 'http://localhost:9248/auth/login/redirect/ig'
},
function (accessToken,refreshToken,profile,done) {
return done(null, profile, {tokens: {accessToken: accessToken, refreshToken: refreshToken}});
}));
function oauth2ProviderLogin (request,response,next) {
var provider = request.query.provider;
switch (provider) {
case 'fb':
passport.authenticate('facebook')(request,response,next);
break;
case 'ig':
passport.authenticate('instagram')(request,response,next);
break;
}
}
function handleOAuth2Redirect (request,response,next) {
var provider = request.params.provider;
switch (provider) {
case 'fb':
passport.authenticate('facebook', {session:false})(request,response,next);
break;
case 'ig':
passport.authenticate('instagram', {session:false})(request,response,next);
break;
}
}
function jwt (request,response,next) {
var jwt = require('jsonwebtoken');
var token = jwt.sign({auth: request.authInfo}, '623145ca-7749-11e5-8bcf-feff819cdc9f');
return response.send({user: request.user, auth: token});
}
module.exports = (function() {
var authController = {
oauth2ProviderLogin: oauth2ProviderLogin,
handleOAuth2Redirect: handleOAuth2Redirect,
jwt: jwt
};
return authController;
})();
I've literally made it work by changing some lines of the controller functions. But the exports block has always remained the same. Naturally I nede to keep coding but then it stops working.
An example of something making it to stop working:
'use strict';
var passport = require('passport');
var jwt = require('jsonwebtoken'); // This makes it fail
var FacebookStrategy = require('passport-facebook').Strategy;
var TwitterStrategy = require('passport-twitter').Strategy;
var InstagramStrategy = require('passport-instagram').Strategy;
var OAuth2Strategy = require('passport-oauth2').Strategy;
That's it: adding a var jwt = require('jsonwebtoken') will make it fail.
Is there something I'm missing?
My error is actually silly:
Adding var jwt = require('jsonwebtoken') because I have a function with same name below:
function jwt (request,response,next) {
var token = jwt.sign({auth: request.authInfo}, '623145ca-7749-11e5-8bcf-feff819cdc9f');
return response.send({user: request.user, auth: token});
}
Just changing the name of any of those will fix the issue.
Related
I'm trying to get the user data from google after authentication using passport js, the req.user() function isn't working .I obviously did something wrong, in the redirect URL the
req.user method works but then it doesn't work in any other route. so even when I use axios to fetch the data from the other endpoint, I usually just get an empty object.
const router = require("express").Router();
const passport = require("passport");
// const loginPage = "http://localhost:3000/login"
// const homePage = "http://localhost:3000/"
const userController = require("../Controllers/user-controller")
//auth login
router.get("/login/success",userController.getuserdata )
//auth failure
router.get("/login/failed", userController.getfailuremsg)
//auth logout
router.get("/logout", userController.logout)
//auth sign in with google
router.get("/google", passport.authenticate("google",{
scope: [ 'profile' ],
}))
//callback url for google to redirect to
router.get("/google/callback",passport.authenticate("google",
{
failureRedirect:"/login/failed",
successRedirect: "/auth/login/success"
}), (req,res) => {
console.log(req.user.name);
res.redirect("/profile/")
} )
module.exports = router
Here's what the DB side looks like
const passport = require("passport");
const GoogleStrategy = require('passport-google-oauth2').Strategy;
require("dotenv").config();
const googleId = process.env.GOOGLE_CLIENT_ID;
const clientSecret = process.env.GOOGLE_CLIENT_SECRET;
// const {createUser,findOne,findById} = require("../Services/user")
const User = require("../Models/Users")
passport.serializeUser((user,done)=> {
done(null,user._id)
})
passport.deserializeUser((id,done)=> {
const user = User.findById(id)
done(null,user)
})
passport.use(
new GoogleStrategy({
clientID: googleId,
clientSecret: clientSecret,
callbackURL: 'http://localhost:5000/auth/google/callback',
// passReqToCallback: true
}, (accessToken, refreshToken, profile, done)=> {
User.findOne({googleid:profile.id}).then((currentUser)=>{
if(currentUser){
// console.log(`current User: ${currentUser}`)
done(null,currentUser)
}else{
new User ({
name:profile.displayName,
googleid:profile.id
}).save().then((user) => {console.log(`newly created user: ${user}`); done(null, user)})
}
})
})
)
I've been trying to test the protected routes by using passport and passport-jwt.
I've got it to the point where the token is being generated when a user tries to log in and tested it in Postman.
I've created a route and passed in as an argument passport.authenticate with the jwt strategy and am getting errors all over the place.
In my main server.js, I require passport:
passport = require('passport');
app.use(passport.initialize());
// passport config
require('./config/passport')(passport);
My folder structure is this:
in my passport config file, i have this:
const jwtStrategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
const mongoose = require('mongoose');
const User = mongoose.model('users')
const keys = require('../config/keys');
const opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = keys.secretOrKey;
module.export = passport => {
passport.use(
new jwtStrategy(opts, (jwt_payload, done) => {
console.log(jwt_payload);
}));
};
And my route is this:
// #route get to /users/current
// #desc: return the current user (who the jwt token belongs to)
// #access: should be public
router.get('/current',
passport.authenticate('jwt', { session: false }),
(req, res) => {
res.json({msg: "Success"})
}
);
The first error I can't seem to get passed is this in the console:
require('./config/passport')(passport);
^
TypeError: require(...) is not a function
In postman, when I try to go to /users/current and pass in a confirmed bearer token, I get this:
Error: Unknown authentication strategy "jwt" at attempt
in passport config file
you have typo module.export actualy its module.exports
thats why after require it does not recongnizing it as function
change the module.export to
module.exports = passport => {
passport.use(
new jwtStrategy(opts, (jwt_payload, done) => {
console.log(jwt_payload);
}));
};
its module.exports and not module.export.
The module.exports property can be assigned a new value (such as a function or object).
module.exports = class Square {
constructor(width) {
this.width = width;
}
area() {
return this.width ** 2;
}
};
nodejs modules documentation reference
When I am trying to secure the users API; I am getting always 401 unauthorized. I have tried different variations to define strategy; but no luck. I have been using JWTStrategy and using jwtwebtoken while signing the token with the Secret and RS256 Algorithm
Passport.js
// import * as module from 'module';
const
User = require('../models/user'),
JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt,
config = require('./appconfig');
// Setting JWT strategy options
const jwtOptions = {
// Telling Passport to check authorization headers for JWT
jwtFromRequest: ExtractJwt.fromAuthHeaderWithScheme('Bearer'),
// Telling Passport where to find the secret
secretOrKey: config.jwtSecret,
algorithms:['RS256']
// TO-DO: Add issuer and audience checks
};
console.log(config.jwtSecret);
module.exports = function(passport) {
passport.use(new JwtStrategy(jwtOptions, function(jwt_payload, done) {
console.log(jwt_payload);
User.findOne({id: jwt_payload.sub}, function(err, user) {
if (err) {
return done(err, false);
}
if (user) {
return done(null, user);
} else {
return done(null, false);
// or you could create a new account
}
});
}));
};
Index.Route.js
const express = require('express');
const userRoutes = require('./user.route');
const authRoutes = require('./auth.route');
// const postRoutes = require('./post.route');
const passport = require('passport');
passport.initialize();
var jwt = require('../config/passport')(passport);
const router = express.Router(); // eslint-disable-line new-cap
/** GET /health-check - Check service health */
router.get('/health-check', (req, res) =>
res.send('OK')
);
// mount user routes at /users
router.use('/users', passport.authenticate('jwt', { session: false }), userRoutes);
// mount auth routes at /auth
router.use('/auth', authRoutes);
// router.use('/posts', postRoutes);
module.exports = router;
Using Postman:
Header:
Authentication: JWT Token
localhost:4040/api/users
Did you configure postman in header section? Can you show JwtStrategy code.
I am new to Javascript and even newer to Node. I am trying to read an express server code and can't figure out following line in my app.js file:
module.require('./auth')(passport);
I know I have a variable that holds passport module in app.js:
var passport = require('passport');
and I also have auth.js in the same directory which exports the following function:
module.exports = function(passport) {
passport.use('local-login', new LocalStrategy({
usernameField: 'email'
}, function(idpEmail, password, done) {
// do email mapping
findEmailFromDummyDb(idpEmail, password,function(err,user){
if(err) {
done(null, false, {
messages: err.toString()
});
} else {
done(null, {
sysEmail: user.sysEmail
});
}
});
}));
However, what does following function actually do?
module.require('./auth')(passport);
module.require('./auth') imports a function, then it get's called with passport as a parameter. It's the same as
const auth = require('./auth');
const passport = require('passport');
auth = auth(passport);
The below returns a javascript function.
module.require('./auth');
You are then immediately calling the function with the passport object as a function argument.
(passport)
I'm making a Facebook login with Express, mongoose and passport / passport-facebook modules for nodejs.
I want to handle with a controller who i created for authenticate. When i activate the server, trigger that message on terminal:
if (!verify) { throw new TypeError('OAuth2Strategy requires a verify callback
^
TypeError: OAuth2Strategy requires a verify callback
This is my code:
userController
var mongoose = require('mongoose');
var passport = require('passport');
var FacebookStrategy = require('passport-facebook').Strategy;
var Account = require('../models/accounts');
var Project = require('../models/projects');
var Message = require('../models/messages');
var Follow = require('../models/follows');
var apiKeys = require('../apiKeys');
{more code}
fbAuth : function(access_token, refresh_token, profile, done){
console.log("*************");
console.log("entra en fbAuth");
console.log("*************");
Account.findOne({'providerId' : profile.id}, function(err, user){
if(err){
return done(err);
}
if(user){
return done(null, user);
}
else{
var newUser = new Account({
emailAccount : profile.emails[0].value,
provider : profile.provider,
providerId : profile.id,
username : profile.name.givenName,
});
newUser.save();
}
});
passport.authenticate('facebook',{
successRedirect : '/user',
failureRedirect : '/'
});
},
fbAuthSuccess : function (req, res){
passport.authenticate('facebook', {
successRedirect : '/user',
failureRedirect : '/'
});
},
route
router.get('/facebook', controller.fbAuth);//passport.authenticate('facebook', { scope : 'email' }));
router.get('/facebook/callback', passport.authenticate('facebook', {
successRedirect : '/user',
failureRedirect : '/'
});
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var morgan = require('morgan');
var mongoose = require('mongoose');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var FacebookStrategy = require('passport-facebook').Strategy;
var session = require('express-session');
var socket = require('socket.io');
var apiKeys = require('./apiKeys');
var app = express();
{more code}
passport.use(new LocalStrategy(Account.authenticate()));
passport.serializeUser(Account.serializeUser());
passport.deserializeUser(Account.deserializeUser());
//social facebook
passport.use(new FacebookStrategy({
clientID: apiKeys.facebook.appID,
clientSecret: apiKeys.facebook.appSecret,
callbackURL: apiKeys.facebook.callbackUrl,
'profileFields': ['id', 'displayName', 'email', 'name'],
}));
You need to add a verify callback, your controller.fbAuth as a second argument to passport.use. The router.get('/facebook should have passport.authenticate('facebook') as its second argument. You can follow the example on passports docs.