After setting up the Drupal as this guide says: Drupal-passport I created a simple simple node app to test how it works.
It doesn't, I get the InternalOAuthError: Failed to obtain request token error.
Going through the strategy.js, I saw that my callbackURL is logging out undefined not exactly sure why. The callbackURL is set in my Drupal app
Also preforming a curl -i -XPOST http://extranet.local/rest/system/connect/ gives me exactly what I need
Here is my node.js code (keep in mind this is just supposed to test the drupal set up).
var express = require('express');
var passport = require('passport');
var dStrategy = require('passport-drupal').DrupalStrategy;
var passportDrupal = require('passport-drupal');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser')
var session = require('express-session');
var http = require('http');
var app = express();
var server = http.createServer(app);
app.use(cookieParser());
app.use(bodyParser());
app.use(session({ secret: 'SECRET' }));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new dStrategy({
consumerKey: "emDVp7P2LZFLPcN3cNCjLmrjrhQLnNv6",
consumerSecret: "mkbc3UYEuUQLNQRwLWo3B8zEk4ZrErKa",
providerURL: "http://extranet.local",
resourceEndpoint: "rest/system/connect", // <---- optional. Defaults to `rest/system/connect`
callbackURL: 'http://33.33.33.40:8888/auth/drupal/callback'
},
function(token, tokenSecret, profile, done) {
profile.oauth = { token: token, token_secret: tokenSecret };
done(null, profile);
}
));
app.get('/', function(req, res) {
res.writeHead(200);
res.end("This is root");
});
app.get('/auth/drupal',
passport.authenticate('drupal'),
function(req, res) {
// The request will be redirected to the Drupal website for
// authentication, so this function will not be called.
});
app.get('/auth/drupal/callback',
passport.authenticate('drupal', { failureRedirect: '/error' }),
function(req, res) {
// Successful authentication, redirect home.
res.redirect('/signedin');
});
app.get('/error', function(req, res) {
res.writeHead(200);
res.end("Could not sign in");
});
app.get('/signedin', function(req, res) {
res.writeHead(200);
res.end("signed in");
});
server.listen(8888, '33.33.33.40');
Any clues as to why or ideas are greatly appreciated
If you look into the strategy.js code of the library passport-drupal, you will see that the DrupalStrategy constructor does not expect a callbackURL property in the options parameter object and it also does not pass it further into the OAuthStrategy.
This is the code snippet that creates the parameter for the oauth strategy:
// Determine all necessary OAuth options
var oauthOptions = {
requestTokenURL: this._providerURL + '/oauth/request_token',
accessTokenURL: this._providerURL + '/oauth/access_token',
userAuthorizationURL: this._providerURL + '/oauth/authorize',
consumerKey: options.consumerKey,
consumerSecret: options.consumerSecret
};
OAuthStrategy.call(this, oauthOptions, verify);
It should be modified to pass the callbackURL, for example like this:
// Determine all necessary OAuth options
var oauthOptions = {
requestTokenURL: this._providerURL + '/oauth/request_token',
accessTokenURL: this._providerURL + '/oauth/access_token',
userAuthorizationURL: this._providerURL + '/oauth/authorize',
consumerKey: options.consumerKey,
consumerSecret: options.consumerSecret,
callbackURL: options.callbackURL// <==== THIS LINE WAS ADDED
};
OAuthStrategy.call(this, oauthOptions, verify);
I'm not sure that will solve your issue though. But I made a pull request
Related
So I'm using this post as an example to test POST/GET. I've tested actions that I wanted to do which are Follow and Retweet. But now the problem is this code works on Express and my project is in ReactJS so how do I convert these code to let this work in React?
Here's my code:
var Twit = require('twit');
var express = require('express');
var path = require('path');
var passport = require('passport');
var cookieParser = require('cookie-parser');
var Strategy = require('passport-twitter').Strategy;
var session = require('express-session');
passport.use(new Strategy({
consumerKey: '...',
consumerSecret: '...',
callbackURL: 'http://localhost:3000/twitter/return'
}, function(token, tokenSecret, profile, callback) {
const configs = createConfigs(token, tokenSecret);
// Post to twitter
var Twit = require('twit')
var T = new Twit({
consumer_key: '...', //get this from developer.twitter.com where your app info is
consumer_secret: '...', //get this from developer.twitter.com where your app info is
access_token: token,
access_token_secret: tokenSecret,
timeout_ms: 60*1000, // optional HTTP request timeout to apply to all requests.
strictSSL: true, // optional - requires SSL certificates to be valid.
})
// tweet hello world
T.post('statuses/update', { status: 'hello world!' }, function(err,
data, response) {
console.log(data)
})
return callback(null, profile);
}));
passport.serializeUser(function(user, callback) {
callback(null, user);
})
passport.deserializeUser(function(obj, callback) {
callback(null, obj);
})
const app = express();
const port_no = 5555
//view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// Server Setup
app.listen(port_no, () => {
console.log('port running atport number : 5555')
})
app.use(cookieParser());
app.use(session({secret: 'whatever', resave: true, saveUninitialized: true}))
app.use(passport.initialize())
app.use(passport.session())
app.get('/' , (req,res) => {
res.render('testpage')
})
app.get('/twitter/login', passport.authenticate('twitter'))
app.get('/twitter/return', passport.authenticate('twitter', {
failureRedirect: '/'
}), function(req, res) {
res.redirect('/')
})
module.exports = app;
So the code above is mainly to login into user's twitter then make POST action according to the API. So I would need some help so that I can make this thing works in my React project.
I'm trying to set up Googe Authentication to a website running off node.js, passport.js, express & mongodb, largely based off this example. I have managed to get local authentication working but when trying to get Google Authentication working, I'm getting a TypeError: OAuth2Strategy requires a verify callback error when trying to initialise the server.
The authentication strategy for Google is held in /config/passport.js, shown below:
var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy();
var User = require('../models/user');
var configAuth = require('./auth');
module.exports = function(passport) {
// serialize the user session
passport.serializeUser(function(user, done) {
done(null, user.id);
});
// deserialize the user session
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
// =================GOOGLE=======================
var strategyOptions = {
clientID : configAuth.googleAuth.clientID,
clientSecret : configAuth.googleAuth.clientSecret,
callbackURL : configAuth.googleAuth.callbackURL,
};
var verifyCallback = function(token, refreshToken, profile, done) {
process.nextTick(function() {
User.findOne({ 'google.id' : profile.id }, function(err, user) {
if (err)
return done(err);
if (user) {
return done(null, user);
} else {
var newUser = new User();
newUser.google.id = profile.id;
newUser.google.token = token;
newUser.google.name = profile.displayName;
newUser.google.email = profile.emails[0].value;
newUser.save(function(err) {
if (err)
throw err;
return done(null, newUser);
});
}
});
});
};
passport.use(new GoogleStrategy(strategyOptions, verifyCallback));
};
My app.js looks as follows (with the invocation of passport.js bolded):
// set up ================================================================
var express = require('express');
var app = express()
var path = require('path');
var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');
var morgan = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var configDB = require('./config/database.js');
// config ================================================================
mongoose.connect(configDB.url);
require('./config/passport')(passport);
//set up express application
app.use(morgan('dev'));
app.use(cookieParser());
app.use(bodyParser());
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(session({ secret: 'what a long string' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use(express.static(path.join(__dirname, 'public')));
// routes ================================================================
require('./routes/index.js')(app, passport);
// launch ================================================================
//app.listen(port);
module.exports = app;
I can't tell what is going wrong here, because as far as I can see verifyCallback is being supplied in the passport.use() function. I've spent the last day Googling around and searching through StackOverflow but haven't found a fix that works yet.
Apologies if this is a really obvious error, I'm new to the whole node ecosystem and web design in general. Happy to provide more information if that is helpful.
You have done it well.The issue is with getting google strategy.
Change this line
var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy();
To below mentioned one
var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
You can see the working example here for any other issue.
For Reference: https://github.com/Khushbu-2112/OAuth-google-example
I am very new to both JS and NodeJs/Express. I am writing a proof of concept MVP node/express app that uses passport for authentication (via social logins).
I have written the server and installed all required packages and so far everything (apart from the authentication bit works).
Note: I have already set up my credentials at the various social media company's ends, so this is not the problem.
Here is a snippet of my code:
app.js
const express = require('express');
const expressLayouts = require('express-ejs-layouts');
compression = require('compression'),
shouldCompress = (req, res) => {
if (req.headers['x-no-compression']) {
// don't compress responses if this request header is present
return false;
}
// fallback to standard compression
return compression.filter(req, res);
};
const app = express();
// EJS
app.use(expressLayouts);
app.set('view engine', 'ejs');
// Parsing related
app.use(express.urlencoded( { extended: false })); //Parse URL-encoded bodies
app.use(express.json()); //Used to parse JSON bodies
app.use(compression({
filter:shouldCompress,
threshold: 3
}));
app.use(express.static('public'));
app.disable('x-powered-by');
// Initialize Passport and restore authentication state, if any, from the session.
var passport = require('passport');
app.use(require('express-session')({ secret: 'keyboard cat', resave: false, saveUninitialized: false }));
app.use(passport.initialize());
app.use(passport.session())
// Routes
app.use('/', require('./routes/index'));
app.use('/member', require('./routes/users'));
const PORT = process.env.PORT || 5000;
app.listen(PORT, console.log(`Server started on port: ${PORT}`));
routes/users.js
const express = require('express');
const router = express.Router();
/* GET authentication funcs */
let authentication = require('../controllers/auth.js');
router.get('/subscribe', (req, res) => { res.render('subscribe'); });
router.post('/subscribe', authentication.subscribe);
module.exports = router;
controllers/auth.js
require('dotenv').config();
const model = require("../models");
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const FacebookStrategy = require('passport-facebook').Strategy;
passport.serializeUser(function(user, done) {
done(null, user)
});
passport.deserializeUser(function(email, done) {
done(null, email)
})
function validateLead(req, done) {
mail = req.body.lead_email;
console.log('validateLead() called!');
models.Lead.findOne({
where: {
email: email
}
}).then(/* some logic */).catch();
} else {
// email already taken ..
return done(null, false, {
message: 'This email address is already subscribed'
});
}
}).catch((err) => {
console.log('An error occurred!', err);
});
}
exports.subscribe = function(req, res, next) {
switch (req.body.source) {
case 'facebook':
passport.use(new FacebookStrategy({
clientID: process.env.FACEBOOK_APP_ID,
clientSecret: process.env.FACEBOOK_APP_SECRET,
callbackURL: process.env.FACEBOOK_CALLBACK_URL
},
function(accessToken, refreshToken, fbProfile, done) {
console.log('FB callback!');
profile = {
'email': fbProfile.email,
'firstName': '',
'LastName': '',
'leadSource': '',
'tags': [],
};
return validateLead(req, done, profile);
}
));
break;
default:
console.log('Unknown');
}
}
views/test.eps
<a href='#'><i id='facebook' class='foobar'></i></a>
(simplified) views/layout.eps
$(document).ready(function(){
$('i.foobar').click(function(e){
$.ajax({
method: "POST",
url: "/member/subscribe",
data: {
"source": $(this).attr('id')
},
dataType: "json",
timeout: 5000 // 5000ms
}).done(function(data) {
// is called if request is successful
console.log(data.fridge);
}).fail(function(jqXHR, status) {
// is called if request fails or timeout is reached
alert('Request could not complete: ' + status);
});
});
});
I have put console.log() messages in controllers/auth.js and I can see that the FB code branch is being reached. However, when log messages in validateLead() and the FB callback function are not being reached.
What is the cause of this, and how do I fix it?
A couple things I can see :
As far as I could see you didn't configure passportjs. You need to have a configuration file, which for you would be the controllers/auth.js. To configure passport you need to run require('./controllers/auth')(passport); in app.js.
For passport to be able to ingest that config you need to export them as a function that takes passport e.g. module.exports = passport => {passport.use('facebook')}
Your config file (in exports.subscribe) is not a format that passport will understand. Follow the Documentation on how to create that config file.
Passport provides you with authentication middleware, I am pretty sure that you cannot create "wrappers" for them like in controllers/auth.js. To access passport's auth functions you use passport.authenticate('facebook', callback())(req, res, next) in routes/users.js.
Passport only provides middleware to serialize and deserialize users.
Your deserialization is not yet set up. You need a call to the db to fetch the user from session store.
i am new in node.js. i still couldn't figure out the meaning of configuration on session.
below is example of basic use of session
app.js
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
var session = require('express-session');
var cookieParser = require('cookie-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser('cookie'));
app.use(session({
cookie: {
domain: 'localhost',
signed: false,
maxAge:100000,
},
resave: false,
saveUninitialized:false,
secret:'cookie',
rolling:false,
unset:'keep'
}));
app.get('/', function (req, res) {
res.send('this is a router base page!');
});
app.get('/index1.html', function (req, res, next) {
res.sendFile(__dirname + '/index1.html');
next();
});
app.get('/index1.html', function (req, res) {
console.log(req.session.id);
});
app.post('/index1.html', function (req, res) {
if(!req.session.user) req.session.user = req.body;
res.setHeader('Content-Type','text/html');
res.write('session:' + JSON.stringify(req.session));
res.write('expires:'+ JSON.stringify(req.session.cookie.maxAge/1000));
res.end();
});
app.listen(1338);
when i refresh localhost:1338/index.htmlmany times, the req.session.id changes accordingly such as
CboUX1OOMa1veStAmf_9fsEd-ZwNYlW
kWkgsLXsDJcbtEIt9gfSWbg4_ScbG44p
jXLUt0fcCa-wH_jYsU64GznGj1ZNR44G
FjmjRHahDlaC79ngg7k2n1yWni6OHqpt
eLauXn3_SFNxmcWbHMZKAL4d0OVTwzqC
i don't get it why it changes every time even i haven't use post method.
if it changes according to every refreshing web page, what is the difference from req.session.regenerate
req.session.regenerate(function(err){
console.log(req.session.id);
});
but after i wrote username and password in front end form,and submit, then refresh web page again, it won't print session.id any more.
I think i may have some misunderstanding on concept of session.
can anyone help out?
It should give you same token if you introduce time duration setting in session configuration. Something like this
activeDuration: 5 * 60 * 1000
If you are interested for more detail please visit this link https://stormpath.com/blog/everything-you-ever-wanted-to-know-about-node-dot-js-sessions
I have been staring at the same SO questions/answers for too long.
I am trying to set my user ID in a req.session variable
here is my app.js stack
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, cors = require('cors')
, mongoose = require('mongoose')
, User = require('./user-model')
, path = require('path')
, mysql = require('mysql');
app = express()
/**
* Middleware.
*/
app.use(cors());
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: 'supercalafragalistic' }));
app.locals.pretty = true;
app.use(express.static(path.join(__dirname, 'public')));
app.set('view engine', 'jade');
...
app.get('/someRoute', routes.someRoute)
I have moved the app.router from top to bottom. Currently it is implied (I just deleted it as I stripped my code looking for error). I have exported app, included app in routes (also erased) . I added middleware. I am lost.....
here is my route stack
//routes/index.js
//requires
var User = require('../user-model')
,qs = require('querystring')
,http = require('http')
,mysql = require('mysql')
,connection = mysql.createConnection({
edited
});
/**
* Set up application.
*/
connection.connect(function(err){
if(err) console.log('failed to connect to mysql because'+ err);
else console.log('connected to mysql');
})
I save the id in the login route:
//login processing route
exports.logIn = function(req, res, next){
console.log('log in request from '+req.body.name);
User.findOne({name:req.body.name}, function(err, user, next){
if(err) return next(err);
if(!user) return res.end();
//check password
user.comparePassword(req.body.password, function(err, isMatch){
if(err) res.send('failed to find user');
console.log(""+isMatch);
if(isMatch){
console.log(user._id.toString()+' user loggd in');
//set session cookie
req.session.loggedIn = user._id.toString();
console.log('req.session.loggedIn set to :'+req.session.loggedIn );
res.send(user);
}else {
res.send('User not found try again');
}
});
});
However, in all other routes the variable is undefined:
// clock status
exports.clockStatus = function(req, res, next){
var user = req.session.loggedIn;
console.log('Status route, userID: '+user);
if(user){
I found the answer in "Cannot access req.session variables in Express/NodeJS" but the last part trails off:
In your case, you have assigned req.session.user = user; only in
/login request. It will not be available for further requests(/auth).
You have to get user information in /auth request too by session id.
(Or) Better you can use passport for authentication.
HOW? How do you "get user information in /auth request too by session id"?
Please ask for anything else you need to straighten me out.
I'm stumped. I have tried some dumb stuff already!
The variable is undefined in other routes if you don't log in first in the browser. Here is my test code:
var express = require('express');
var cors = require('cors');
app = express();
app.use(cors());
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: 'this is a test' }));
app.use(express.static(require('path').join(__dirname, 'public')));
app.get('/login', function(req, res) {
req.session.uid = 'user001';
res.send(req.session);
});
app.get('*', function(req, res) {
res.send(req.session);
});
app.listen(8080);
First visit http://localhost/login in the browser. Then visit other URLs(e.g., http://localhost/test) in this browser, the user id in the session is returned. So maybe there is something wrong in other parts of your code.
Test settings:
Ubuntu Desktop 13.10, 64 bit
Node 0.10.26
NPM 1.4.4
Express 3.4.8
cors 2.2.0