integrate auth0 in a web app express / node js - node.js

I'm trying to add auth0 to my web app, I've followed their tutorials and other tutorials on the web, including creating account/client and everything else, but I keep getting the usual white page loading screen and after several minutes I receive this error:
ERR_EMPTY_RESPONSE
These are parts of my code:
app.js
...
var cookieParser = require('cookie-parser');
var session = require('express-session');
var passport = require('passport');
var Auth0Strategy = require('passport-auth0');
...
// Configure Passport to use Auth0
var strategy = new Auth0Strategy(
{
domain: process.env.AUTH0_DOMAIN,
clientID: process.env.AUTH0_CLIENT_ID,
clientSecret: process.env.AUTH0_CLIENT_SECRET,
callbackURL: process.env.AUTH0_CALLBACK_URL
},
(accessToken, refreshToken, extraParams, profile, done) => {
return done(null, profile);
}
);
passport.use(strategy);
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
...
app.use(cookieParser());
app.use(
session(
{
secret: uuid(),
resave: false,
saveUninitialized: false
}
)
);
app.use(passport.initialize());
app.use(passport.session());
...
app.get('/', routes.index);
app.get('/home', routes.home);
...
http.createServer(app).listen(app.get('port'), function(){
console.log('Server listening on port: ' + app.get('port'));
});
module.exports = app;
index.js
exports.home = function(req, res){
res.render('home', { title: ' homepage ' });
};
exports.index = function(req, res){
var express = require('express');
var passport = require('passport');
var router = express.Router();
var env = {
AUTH0_CLIENT_ID: process.env.AUTH0_CLIENT_ID,
AUTH0_DOMAIN: process.env.AUTH0_DOMAIN,
AUTH0_CALLBACK_URL: process.env.AUTH0_CALLBACK_URL
};
// GET home page.
router.get('/', function(req, res, next) {
res.render('home', { title: ' homepage ' });
});
// Perform the login
router.get(
'/login',
passport.authenticate('auth0', {
clientID: env.AUTH0_CLIENT_ID,
domain: env.AUTH0_DOMAIN,
redirectUri: env.AUTH0_CALLBACK_URL,
audience: 'https://' + env.AUTH0_DOMAIN + '/userinfo',
responseType: 'code',
scope: 'openid'
}),
function(req, res) {
res.redirect('/');
}
);
// Perform session logout and redirect to homepage
router.get('/logout', (req, res) => {
req.logout();
res.redirect('/');
});
// Perform the final stage of authentication and redirect to '/home'
router.get(
'/callback',
passport.authenticate('auth0', {
failureRedirect: '/'
}),
function(req, res) {
res.redirect(req.session.returnTo || '/home');
}
);
}
There are some parts that are not clear to me or on which I would like to have a confirmation:
1) the callback URL must be my homepage (180.180.180.180/home) or the real first page (180.180.180.180)? Which one should be included in the auth0 dashboard?
2) In the router, should I also specify the / login and / logout fields or should these be managed directly by the auth0 API?
Sorry for my ignorance but it's days I have this problem, I do not understand if it's an authorization error with the auth0 account or something else.
I have the credentials in a .env file, but they should not be the problem, as I can access other data in them to connect to my MySQL database.

As per the documentation of auth0 The callback URL is not necessarily the same URL to which you want users redirected after authentication.
redirect_uri field is used as a callback URL. Auth0 invokes callback URLs after the authentication process and are where your application gets routed.
You can redirect the user to a non callback URL after authenticating the user and storing the same url in web storage.
On app.get(/login)...>authenticated>>landing page>>stores the access tokens
So post authentication it should login to your landing page (home).
On app.get(/logout), you can clear the access tokens or make it available for desired time and let it get expired after certain time.

Related

Getting "You need to provide a redirectUri" error with WP OAuth Server & NodeJS

I am creating a NodeJS application and I am trying to use Wordpress for authentication, via OAuth2, but I am running into a few issues. I am leveraging the 'passport-wpoauth' module.
I am getting the error "You need to provide a redirectUri" when trying to authorize. I did try specifying "redirectUri" in the parameters passed to WPOAuthStrategy, but that did not help. The issue is happening in the call to passport.authenticate(), from what I can see.
Code looks as follows and was wondering if you had any suggestions?
const bodyParser = require("body-parser");
const express = require('express');
const expressSession = require('express-session');
const url = require('url');
const passport = require('passport');
const OAuth2Strategy = require('passport-oauth2');
const WPOAuthStrategy = require('passport-wpoauth');
function initPassport(app) {
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
var oauthConfig = {
"clientID": "Wq3lkiaPfMn83Cd5YWNoRAHpJtN55a",
"clientSecret": "82AbnUuyJJk7RoK4uJ0h7SSPhBi5Ho",
"authorizationURL": "https://localhost/oauth/authorize",
"tokenURL": "https://localhost/oauth/token/",
"callbackURL": "http://localhost:7070/api/auth/callback",
"userProfileURL": "http://localhost/myprofile"
};
passport.use(new WPOAuthStrategy(oauthConfig,
function(accessToken, refreshToken, profile, callback) {
console.log('profile', profile);
callback(undefined, {
id: '56757dsfe22',
email: 'dummy#example.com'
});
}
));
app.get('/auth/callback',
passport.authenticate('wpoauth', { failureRedirect: '/api/login' }),
function(req, res) {
console.log('success');
// Successful authentication, redirect home.
res.redirect('/');
});
}
function handleAuthenticate(req, res, next) {
console.log('xxxx', 'handleAuthenticate');
passport.authenticate('wpoauth')(req, res, next);
}
function initRoutes(app) {
app.get(/.*/, handleAuthenticate) ;
app.get('/auth/callback',
passport.authenticate('wpoauth', { failureRedirect: '/api/login' }),
function(req, res) {
console.log('success');
// Successful authentication, redirect home.
res.redirect('/');
});
}
var app = express();
var router = express.Router();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
initPassport(app);
app.use('/api/', router);
initRoutes(router);
Note I have also tried with the passport-oauth2 module directly, getting as far as the login screen, but once logged in and sent back to the http://localhost:7070/api/auth/callback URL I get the error:
TokenError: Authorization code doesn't exist or is invalid for the client
Both the clientID and the clientSecret match what is specified in the WordPress admin UI for 'WP OAuth Server'.
Using WP OAuth Server 3.2.0001, with Nginx and WP 4.6.1
Looking through the source code of the 'passport-wpoauth' package indicates that the 'redirectUri' is being expected as part of the request body, rather from settings passed in as options, as I was expecting.
I changed my code to be:
app.get('/auth/wordpress', function(req, res, next) {
req.body.redirectUri = 'http://redirectUrl/'
passport.authenticate('oauth2', {})(req, res, next);
});
The issue was larger due to other incompatibilities. I have submitted a pull-request to the project.

Google-oauth2 passport not working

I am trying to implement sign-in with google and passport but I am running into a bit of a problem. I successfully authenticate with google, but my data isn't being passed to the front end. I Haven't changed anything from the original code except for the URI and necessary client id and secret. Can anyone tell me what I am missing?
var express = require( 'express' )
, app = express()
, server = require( 'http' ).createServer( app )
, passport = require( 'passport' )
, util = require( 'util' )
, bodyParser = require( 'body-parser' )
, cookieParser = require( 'cookie-parser' )
, session = require( 'express-session' )
, RedisStore = require( 'connect-redis' )( session )
, GoogleStrategy = require( 'passport-google-oauth2' ).Strategy;
// API Access link for creating client ID and secret:
// https://code.google.com/apis/console/
var GOOGLE_CLIENT_ID = "307841191614-1shiak514mrjugtbon3dm2if8hbhnvdv.apps.googleusercontent.com"
, GOOGLE_CLIENT_SECRET = "fgViegEgHWuoc1X-p63iPmpF";
// Passport session setup.
// To support persistent login sessions, Passport needs to be able to
// serialize users into and deserialize users out of the session. Typically,
// this will be as simple as storing the user ID when serializing, and finding
// the user by ID when deserializing. However, since this example does not
// have a database of user records, the complete Google profile is
// serialized and deserialized.
passport.serializeUser(function(user, done) {
done(null, user);
console.log("User: "+ user.displayName); // If there is a persistent session, the console logs out the displayName
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
// Use the GoogleStrategy within Passport.
// Strategies in Passport require a `verify` function, which accept
// credentials (in this case, an accessToken, refreshToken, and Google
// profile), and invoke a callback with a user object.
passport.use(new GoogleStrategy({
clientID: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET,
//NOTE :
//Carefull ! and avoid usage of Private IP, otherwise you will get the device_id device_name issue for Private IP during authentication
//The workaround is to set up thru the google cloud console a fully qualified domain name such as http://mydomain:3000/
//then edit your /etc/hosts local file to point on your private IP.
//Also both sign-in button + callbackURL has to be share the same url, otherwise two cookies will be created and lead to lost your session
//if you use it.
callbackURL: "http://127.0.0.1:3000/oauth2callback",
passReqToCallback : true
},
function(request, accessToken, refreshToken, profile, done) {
// asynchronous verification, for effect...
process.nextTick(function () {
// To keep the example simple, the user's Google profile is returned to
// represent the logged-in user. In a typical application, you would want
// to associate the Google account with a user record in your database,
// and return that user instead.
console.log(profile); //logs google profile successfully
return done(null, profile);
});
}
));
// configure Express
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use( express.static(__dirname + '/public'));
app.use( cookieParser());
app.use( bodyParser.json());
app.use( bodyParser.urlencoded({
extended: true
}));
app.use( session({
secret: 'cookie_secret',
name: 'kaas',
store: new RedisStore({
host: '127.0.0.1',
port: 6379
}),
proxy: true,
resave: true,
saveUninitialized: true
}));
app.use( passport.initialize());
app.use( passport.session());
/*
===
===
===
Here is where the data is not being read.
*/
app.get('/', function(req, res){
res.render('index', { user: req.user });
console.log(req.user); //Output: undefined
});
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/google
// Use passport.authenticate() as route middleware to authenticate the
// request. The first step in Google authentication will involve
// redirecting the user to google.com. After authorization, Google
// will redirect the user back to this application at /auth/google/callback
app.get('/auth/google', passport.authenticate('google', { scope: [
'https://www.googleapis.com/auth/plus.login',
'https://www.googleapis.com/auth/plus.profile.emails.read']
}));
// GET /auth/google/callback
// Use passport.authenticate() as route middleware to authenticate the
// request. If authentication fails, the user will be redirected back to the
// login page. Otherwise, the primary route function function will be called,
// which, in this example, will redirect the user to the home page.
app.get( '/oauth2callback',
passport.authenticate( 'google', {
successRedirect: '/',
failureRedirect: '/login'
}));
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
server.listen( 3000 );
// Simple route middleware to ensure user is authenticated.
// Use this route middleware on any resource that needs to be protected. If
// the request is authenticated (typically via a persistent login session),
// the request will proceed. Otherwise, the user will be redirected to the
// login page.
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) { return next(); }
res.redirect('/login');
}
`
Here is the simple layout that doesn't seem to be receiving any data.
<% if (!user) { %>
<h2>Welcome! Please log in.</h2>
<% } else { %>
<h2>Hello, <%= user.displayName %>.</h2>
<% } %>
Your code works, I just used same example on my app.
I had the same problem and I realized that I'm not using a valid account in my tests.
This API retrieves data from Google+ profile. Are you using a valid Google account with linked Google+ profile to authenticate?

passport-google-oauth2 for fetching gmail.users.messages.list in node js

First of all I am bit new to node js + oauth2 with passport so if you have any confusion please comment.
I have tried below for authentication with google from oauth2 with node.js, here is the code
var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
var google = require('googleapis');
var GOOGLE_CLIENT_ID = "---MY-CLIENT-ID";
var GOOGLE_CLIENT_SECRET = "---MY-CLIENT-SECRET";
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
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 });
});
// user back to this application at /auth/google/return
app.get('/auth/google',
passport.authenticate('google', { failureRedirect: '/login' }),
function(req, res) {
res.redirect('/');
});
// GET /auth/google/return
// Use passport.authenticate() as route middleware to authenticate the
// request. If authentication fails, the user will be redirected back to the
// login page. Otherwise, the primary route function function will be called,
// which, in this example, will redirect the user to the home page.
app.get('/auth/google/return',
passport.authenticate('google', { failureRedirect: '/login' }),
function(req, res) {
res.redirect('/');
});
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
app.listen(3000);
// Simple route middleware to ensure user is authenticated.
// Use this route middleware on any resource that needs to be protected. If
// the request is authenticated (typically via a persistent login session),
// the request will proceed. Otherwise, the user will be redirected to the
// login page.
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) { return next(); }
res.redirect('/login')
}
Above all is working fine but now I want to use this in with the help of passport for fetching the gmail's emails list.
var gmail = google.gmail('v1');
var profileData = gmail.users.messages.list({ userId: 'me', auth: "**AUTHORISATION OBJECT WITH ACCESSTOKEN**" }, function(err, response) {
//console.log(response.messages);
});
How can I use this within the passport's generated access token.
You need a OAuth2-client:
var gmail = google.gmail('v1');
var OAuth2 = google.auth.OAuth2;
var oauth2Client = new OAuth2('<CLIENT_ID>', '<CLIENT_SECRET>', '<REDIRECT_URL>');
oauth2Client.setCredentials({ access_token: '<ACCESS_TOKEN_HERE>' });
app.get('/', function(req, res, next) {
gmail.users.messages.list({ userId: 'me', auth: oauth2Client },
function(err, response) {
res.send(response);
});
}
This will work fine for testing with your own credentials, but with more users you have to change access token to the current user's token.

Facebook Authentication with Passport and ExpressJS - Why is verify callback not called?

I am Passport to authenticate users in an ExpressJS application. I am attempting to place all Facebook routes in their own module because I intend to support other OAuth providers. In my start script I have defined the required FB endpoints:
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var facebook = require('./routes/facebook');
var login = require('./routes/login');
var http = require('http');
var path = require('path');
var app = express();
/* Configuration stuff here*/
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/login', login.index);
app.get('/auth/facebook', facebook.fb_auth);
app.get('/auth/facebook/callback', facebook.fb_callback);
As you can see I am requiring my 'facebook' module which contains the actual routes and Facebook verify callback. It looks like this:
var passport = require('passport')
, FacebookStrategy = require('passport-facebook').Strategy
, User = require('../services/user');
passport.use(new FacebookStrategy({
clientID: 'myclientid',
clientSecret: 'mysecretkey',
callbackURL: "http://localhost:3000/auth/facebook/callback" //localhost:3000 domain is registered domain in fb
},
function(accessToken, refreshToken, profile, done) {
console.log('verify')
User.findOrCreate(profile, function(err, user){
if(err) return done(err);
done(null, user);
});
}
));
// Redirect the user to Facebook for authentication. When complete,
// Facebook will redirect the user back to the application at
// /auth/facebook/callback
exports.fb_auth = function(req, res){
passport.authenticate('facebook')
};
// Facebook will redirect the user to this URL after approval. Finish the
// authentication process by attempting to obtain an access token. If
// access was granted, the user will be logged in. Otherwise,
// authentication has failed.
exports.fb_callback = function(req, res){
console.log('callback')
passport.authenticate('facebook', { successRedirect: '/',
failureRedirect: '/login' });
};
I can see (logging to stdout) that fb_auth is called but the verify callback function defined above never is. Am I overlooking something? Is there an error occurring somewhere I can capture?
Thanks!
I found the answer here: Using PassportJS with Connect for NodeJS to authenticate Facebook Users
You need to explicitly call the 'authenticate' function and provide it with req, res, and next.
exports.fb_auth = function(req, res, next){
passport.authenticate('facebook')(req, res, next);
return;
};
exports.fb_callback = function(req, res, next){
passport.authenticate('facebook', { successRedirect: '/',
failureRedirect: '/login' })(req, res, next);
};

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