Cannot GET /callback while using salesforce oauth in nodejs - node.js

I am trying to do salseforce aouth in nodejs using passportjs butt getting error.
Cannot GET /callback?code=aPrxaSyVmC8fBbcSNDQ8G8UtoR.YZip2hdfAGpMSc2hf0798gD_UoDle1dqqC0HnPyewycgKMw%3D%3D
Here is my code
'use strict';
var express = require('express'),
passport = require('passport'),
util = require('util'),
ForceDotComStrategy = require('passport-forcedotcom').Strategy;
//----------------------------------------------------------------------------
// REPLACE THE BELOW SETTING TO MATCH YOUR SALESFORCE CONNECTED-APP'S SETTINGS
//----------------------------------------------------------------------------
var CF_CLIENT_ID = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
var CF_CLIENT_SECRET = 'xxxxxxxxxxxxxxxxxxxxx';
var CF_CALLBACK_URL = 'http://localhost:3000/callback';
var SF_AUTHORIZE_URL = 'https://login.salesforce.com/services/oauth2/authorize';
var SF_TOKEN_URL = 'https://login.salesforce.com/services/oauth2/token';
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
var sfStrategy = new ForceDotComStrategy({
clientID: CF_CLIENT_ID,
clientSecret: CF_CLIENT_SECRET,
callbackURL: CF_CALLBACK_URL,
authorizationURL: SF_AUTHORIZE_URL,
tokenURL: SF_TOKEN_URL
}, function(accessToken, refreshToken, profile, done) {
process.nextTick(function() {
delete profile._raw;
return done(null, profile);
});
});
passport.use(sfStrategy);
var app = express();
// configure Express
app.configure(function() {
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.logger());
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.session({
secret: 'keyboard cat'
}));
// Initialize Passport! Also use passport.session() middleware, to support
// persistent login sessions (recommended).
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.get('/', function(req, res) {
console.log(req.user);
if(!req.user) {
req.session.destroy();
req.logout();
return res.redirect('/login');
}
res.render('index', {
user: req.user
});
});
app.get('/login', function(req, res) {
req.logout();
req.session.destroy();
res.render('login', {
user: req.user
});
});
app.get('/auth/forcedotcom', passport.authenticate('forcedotcom'), function(req, res) {
});
app.get('/auth/forcedotcom/callback', passport.authenticate('forcedotcom', {
successRedirect: '/',
failureRedirect: '/login'
}), function(req, res) {
res.redirect('/');
});
app.get('/logout', function(req, res) {
res.redirect('/login');
});
app.listen(3000);
console.log('localhost run in 3000');
function ensureAuthenticated(req, res, next) {
if(req.isAuthenticated()) {
return next();
}
res.redirect('/login');
}
I am trying to fix problem with already post a query in at there but that cannot resole Cannot GET /auth/twitter/callback while using twitter oauth in nodejs

looks like you've set the callback URL to http://yourdomain.com/callback in your salesforce oauth app, but have not define a handler for it correctly
either change the callback URL of your salesforce oauth app to
http://yourdomain.com/auth/forcedotcom/callback
or change the following in your code
app.get('/auth/forcedotcom/callback', passport.authenticate('...
to
app.get('/callback', passport.authenticate('forcedotcom', {
successRedirect: '/',
failureRedirect: '/login'
}), function(req, res) {
res.redirect('/');
});

Related

problem in sign in with LinkedIn in angular and node (using passportjs)

I am having problem in logging in with LinkedIn, both in angular front-end and on node side using passport js. I guess It might be due to change in policy of LinkedIn after 1st march. i have following three files
Server file
app.set('view engine', 'ejs');
// initialize passport
app.use(passport.initialize());
app.use(passport.session());
// set up routes
app.use('/auth', authRoutes);
app.use('/profile', profileRoutes);
// create home route
app.get('/', (req, res) => {
res.render('home');
});
app.listen(3000, () => {
console.log('app now listening for requests on port 3000');
});
Routes file
const router = require('express').Router();
const passport = require('passport');
// auth login
router.get('/login', (req, res) => {
res.render('login', { user: req.user });
});
// auth logout
router.get('/logout', (req, res) => {
// handle with passport
res.send('logging out');
});
router.get('/google',
passport.authenticate('linkedin'),
function(req, res){
// The request will be redirected to LinkedIn for authentication, so this
// function will not be called.
});
router.get('/linkedin/callback', passport.authenticate('linkedin'), (req,
res) => {
res.send(req.user);
// res.redirect('/profile');
});
module.exports = router;
Paasport setup file
const passport = require('passport');
const LinkedInStrategy = require('passport-linkedin-oauth2').Strategy;
passport.use(new LinkedInStrategy({
clientID: LINKEDIN_CLIENT_ID,
clientSecret: LINKEDIN_CLIENT_SECRET,
callbackURL: "http://localhost:3000/auth/linkedin/callback",
scope: ['r_emailaddress','r_liteprofile'],
}, function(accessToken, refreshToken, profile, done) {
// asynchronous verification, for effect...
process.nextTick(function () {
return done(null, profile);
});
}));

Integrate passport.js from node server file to routes file

I'm currently trying to utilize passport in my node server for twitter auth on a project. When I have all the code in one server file passport functions as expected. Below is an excerpt from the server file with all the routes in it:
passport.use(new TwitterStrategy({
consumerKey: config.twitter.consumer_key,
consumerSecret: config.twitter.consumer_secret,
callbackURL: config.twitter.callback_url.dev
}, (token, tokenSecret, profile, done) => {
console.log(token, tokenSecret, profile, done);
process.nextTick(() => {
return done(null, profile);
});
}));
app.use(session({ secret: 'SOMESECRET' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(path.join(__dirname, '../public')));
app.set('view engine', 'ejs');
// expose to routes
app.all('*', (request, response, next) => {
request.log = log;
next();
});
app.get('/', (req, res) => {
res.render('pages/index.ejs');
});
// twitter auth endpoint
app.get('/auth/twitter', passport.authenticate('twitter'));
// twitter auth callback endpoint
app.get('/auth/twitter/callback', passport.authenticate('twitter', { failureRedirect: '/' }), (req, res) => {
res.redirect('/');
});
However, when I try to expose passport from the server file to the routes file the authentication never occurs. I've searched most of the questions here and went back to the doc but all the tutorials show one server file with all the routes in it.
Server file:
passport.use(new TwitterStrategy({
consumerKey: config.twitter.consumer_key,
consumerSecret: config.twitter.consumer_secret,
callbackURL: config.twitter.callback_url.dev
}, (token, tokenSecret, profile, done) => {
console.log(token, tokenSecret, profile, done);
process.nextTick(() => {
return done(null, profile);
});
}));
app.use(session({ secret: 'SECRET' })); // session secret
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(path.join(__dirname, '../public')));
app.set('view engine', 'ejs');
// expose to routes
app.all('*', (request, response, next) => {
request.log = log;
request.passport = passport;
next();
});
// routes
app.use('/', routes);
Routes file:
import express from 'express';
const routes = express.Router();
import config from '../config.js';
// main
routes.get('/', (req, res) => {
res.render('pages/index.ejs');
});
// twitter auth endpoint
routes.get('/auth/twitter', (req, res) => {
const passport = req.passport;
passport.authenticate('twitter');
});
// twitter auth callback endpoint
routes.get('/auth/twitter/callback', (req, res) => {
const passport = req.passport;
passport.authenticate('twitter', {
failureRedirect: '/'
});
res.redirect('/');
});
module.exports = routes;
What am I missing here? I'm guessing I cannot use passport.authenticate inside the function for the route. I'm still trying to figure out how to get the version using the routes file working. Any help is appreciated!!
You can require Passport normally no need to get passport by let passport = req.passport. Here is my small demo for Google Oauth by passport
Routes.js
const router = require('express').Router();
const passport = require('passport');
router.get(
'/google',
passport.authenticate('google', {
scope: ['profile', 'email'],
session: false
})
);
router.get(
'/google/callback',
passport.authenticate('google', {
session: false
})
);
Server.js
// passort config
app.use(passport.initialize());
require('./services/passport'); // contains the passport google strategy
// routes
require('./routes')(app);

passport.js session lost after redirect

I am trying to integrate passport into my node.js app.
app.js file
const app = express();
app.set('view engine', 'pug');
app.use('/libs', express.static('node_modules'));
require('../config/auth.config')(app, data, passport);
app.use((req, res, next) => {
res.locals.user = req.user;
next();
});
app.get('/', (req, res) => {
// those objects are populated correctly after redirect from auth middleware
console.log(req.session)
console.log(req.user)
return res.render('home');
});
app.get('/login', console.log(req.user);
// req.user is undefined here
if (req.user) {
return res.redirect('/');
}
return res.render('login'););
app.post('/login', passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login',
}));
auth.config.js
const express = require('express');
const session = require('express-session');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const LocalStrategy = require('passport-local');
const MongoStore = require('connect-mongo')(session);
const config = require('./config');
const configAuth = (app, {
users
}, passport, db) => {
app.use(cookieParser('Purple Unicorn'));
app.use(bodyParser.urlencoded({
extended: true,
}));
app.use(bodyParser.json());
app.use(session({
store: new MongoStore({
url: config.connectionString
}),
secret: 'Purple Unicorn',
resave: true,
saveUninitialized: true,
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy((username, password, done) => {
return users.login(username, password)
.then((user) => {
if (user) {
return done(null, user);
}
return done(null, false);
});
}));
passport.serializeUser((user, done) => {
done(null, user._id);
});
passport.deserializeUser((id, done) => {
users.getUserById(id)
.then((user) => {
console.log(user);
if (user) {
done(null, user);
}
done(null, false);
});
});
app.use((req, res, next) => {
res.locals = {
user: req.user,
};
next();
});
};
module.exports = configAuth;
The data object is working correctly.
After the post request on /login with correct data, I am redirected to / where console.log(req.user) prints the correct user. It is also added in the req.session object.
After I follow a link to /login, it should redirect me after the check for req.user but returns undefined. Sessions in mongo are stored correctly.
It seems passport is not saving the session correctly.
The problem is in your deserializeUser method where you always run done callback twice. In if statement you should use return done(null, user); to get out from function;

How to keep a user logged on? Is it possible with ExpressJS and Passport?

I have a server in node.js using express and passport with the passport-local strategy.
I have the users in the database and through passport I'm able to authenticate them, unfortunately when a second request comes from the same client the req.isAuthenticated() method returns false.
There is also no user in the request (req.user = undefined).
I've also checked and when doing the authentication although I get back a user from passport.authenticate('local'... I do not get req.user populated then. If I try to set it up manually it just doesn't propagate for following requests.
I don't understand what I'm doing wrong, here is my code.
server.js
var express = require('express'),
compass = require('node-compass'),
routes = require('./server/routes')
http = require('http'),
path = require('path'),
passport = require('passport'),
LocalStrategy = require('passport-local').Strategy,
Database = require('./server/repositories/database'),
Configuration = require('./server/config').Config,
crypto = require('crypto');
var app = express();
app.enable("jsonp callback");
passport.use(new LocalStrategy(
function(email, password, done) {
process.nextTick(function () {
var userService = new UserService();
userService.login(email, crypto.createHash('md5').update(password).digest("hex"), function(error, user) {
if (error) done(error, user);
else if (!user) return done(null, false, { message: 'wrong credentials'});
return done(null, user);
});
});
}
));
passport.serializeUser(function(user, done) {
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
var userService = new UserService();
userService.findById(id, function(err, user) {
done(err, user);
});
});
app.configure(function(){
app.set('port', Configuration.Port);
app.set('views', __dirname + '/app/views');
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(compass({
project: path.join(__dirname, 'app'),
sass: 'styles'
}));
app.use(express.session({ secret: 'keyboard cat' }));
app.use(function(err, req, res, next){
console.error(err.stack);
res.send(500, 'Something broke!');
});
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'app')));
});
routes.configure(app);
Database.open(function() {
app.listen(Configuration.Port, function() {
console.log("Express server listening on port " + Configuration.Port);
});
});
routes.js
var Configuration = require('./config').Config;
var ApiResult = require('../model/apiResult').ApiResult;
var ApiErrorResult = require('../model/apiErrorResult').ApiErrorResult;
var ApiReturnCodes = require('../model/apiReturnCodes').ApiReturnCodes;
var passport = require('passport');
var usersController = require('./controllers/usersController');
exports.configure = function(app) {
function ensureAuthenticated(req, res, next) {
console.log(req.isAuthenticated());
if (req.isAuthenticated()) { return next(); }
else {res.send(new ApiErrorResult(ApiReturnCodes.NOT_LOGGED_IN, null));}
}
app.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err || !user) { console.log(info); res.send(new ApiErrorResult(ApiReturnCodes.ENTITY_NOT_FOUND, null)); }
// If this function gets called, authentication was successful.
// `req.user` contains the authenticated user
else res.send(new ApiResult(user));
})(req,res,next);
});
app.get('/anotherLink', ensureAuthenticated, function(req, res, next) {
res.json({Code:0});
});
}
When I hit the link /anotherLink after being authenticated I get res.isAuthenticated() as false.
Also when I see the req.session after the ensureAuthenticated is called I get:
{ cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true },
passport: {} }
What am I missing for it to save the information that that user is authenticated?
On the client side I'm using Angular only doing a simple get with the url without parameters.
If I forgot to put something here just tell me, I'll update it.
Any help will be greatly appreciated. Thanks
So I found out what was wrong with my code.
My passport.deserializeUser method used the method userService.findById
And that called the repository... like this:
userRepository.findUnique({"_id": id}, callback);
because the id was generated by MongoDB the correct call needs to be:
userRepository.findUnique({"_id": new ObjectID(id)}, callback);
I hope this saves some time to the next person with the same problem.
With this detail, this code should work nicely for everyone wanting to use the LocalStrategy on the Passport framework.

HTTP GET Request for Tweets with Passport.js and Express.js

I'm new to Express.js, Node.js, and Passport.js. I'm trying to develop an application where a user signs in with their Twitter account and then they can see their Mentions (Tweets in which other Twitter users have mentioned the logged in user's Twitter username). I came across Passport.js, and I have been able to use it successfully allow a user to sign in with their Twitter account.
However, I am not sure how to format a server-side HTTP GET request for the Twitter Mentions. I've reviewed the Twitter API numerous times at https://dev.twitter.com/docs/api/1/get/statuses/mentions, but since I'm unfamiliar with the Node/Express/Passport platform, I'm not sure how to perform this request server-side to return JSON-formatted Mentions. The application is set up to be read-only, as it only needs to be able to see relevant Tweets with the associated user.
The front-end is based on EJS. Below is what code I have that may be relevant. Thank you very much for your help.
-joshingmachine
/app.js
/**
* Module dependencies.
*/
var express = require('express')
, passport = require('passport')
, http = require('http')
, util = require('util')
, path = require('path')
, TwitterStrategy = require('passport-twitter').Strategy;
var TWITTER_CONSUMER_KEY = "theConsumerKeyForMyApp";
var TWITTER_CONSUMER_SECRET = "theConsumerSecretForMyApp";
var users = [];
// Passport session setup.
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
var user = users[id];
done(null, user);
});
// Use the TwitterStrategy within Passport.
passport.use(new TwitterStrategy({
consumerKey: TWITTER_CONSUMER_KEY,
consumerSecret: TWITTER_CONSUMER_SECRET,
callbackURL: "http://127.0.0.1:3000/auth/twitter/callback"
},
function(token, tokenSecret, profile, done) {
//console.log(token);
//console.log(tokenSecret);
//console.log(profile);
// asynchronous verification, for effect...
process.nextTick(function () {
var user = users[profile.id] || (users[profile.id] = profile);
done(null, user);
});
}
));
var app = express();
// configure Express
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.session({ secret:'secret'}));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.get('/', function(req, res){
res.render('index', { user: req.user });
});
app.get('/account', ensureAuthenticated, function(req, res){
res.render('account', { user: req.user });
});
app.get('/login', function(req, res){
res.render('login', { user: req.user });
});
// GET /auth/twitter
app.get('/auth/twitter',
passport.authenticate('twitter'),
function(req, res){
// The request will be redirected to Twitter for authentication, so this
// function will not be called.
});
// GET /auth/twitter/callback
app.get('/auth/twitter/callback',
passport.authenticate('twitter', { failureRedirect: '/login' }),
function(req, res) {
res.redirect('/');
});
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
// Create server
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
// Simple route middleware to ensure user is authenticated.
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) { return next(); }
res.redirect('/login');
}
app.use(function(req, res, next){
res.send(404, '404 Not Found');
});
/routes/index.js
/*
* GET home page.
*/
exports.index = function(req, res){
res.render('index', { title: 'Express' });
};
Install the module:
npm install oauth
Then use this code to create your GET request(replace the variables as needed).
var oauth = new OAuth.OAuth(
'https://api.twitter.com/oauth/request_token',
'https://api.twitter.com/oauth/access_token',
'your application consumer key',
'your application secret',
'1.0A',
null,
'HMAC-SHA1'
);
oauth.get(
'https://api.twitter.com/1.1/trends/place.json?id=23424977',
'your user toke for this app', //test user token
'your user secret for this app', //test user secret
function (e, data, res){
if (e) console.error(e);
console.log(require('util').inspect(data));
done();
});
And reference here if you need more info. Good luck!
https://github.com/ciaranj/node-oauth
I created something similar to what you're trying to do. Since you've signed in succesfully, I'm assuming that you're able to get the access token and secret. Once you have those, use an external library like mtwitter. I made the call like this (editing out the parts where i get the tokens from my db):
app.get('/twitter/userMentions', function (req, res) {
var twit = new mtwitter({
consumer_key: consumerKey,
consumer_secret: consumerSecret,
access_token_key: token,
access_token_secret: secret
});
twit.get("/statuses/mentions_timeline", { "include_entities": false },
function (err, data) {
if (err) {
res.write(err.toString());
}
else res.write(JSON.stringify(data));
res.end('\n');
});
}
I think you are looking for Request node module !!
https://npmjs.org/package/request

Resources