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');
});
// auth with google+
router.get('/google',passport.authenticate('google',{
scope:['email']
}));
router.get('/google/redirected',passport.authenticate('google',{
successRedirect:"/",
failureRedirect:"/login"
}),(req,res)=>{
res.send('Redirected Successfully !')
})
module.exports = router;
GooglePlusAPIError: Legacy People API has not been used in project 297453248242 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/legacypeople.googleapis.com/overview?project=297453248242 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
at C:\Users\VAIBHAV\Desktop\GoogleAuth20\node_modules\passport-google-oauth20\lib\strategy.js:95:21
at passBackControl (C:\Users\VAIBHAV\Desktop\GoogleAuth20\node_modules\oauth\lib\oauth2.js:132:9)
at IncomingMessage. (C:\Users\VAIBHAV\Desktop\GoogleAuth20\node_modules\oauth\lib\oauth2.js:157:7)
at IncomingMessage.emit (node:events:525:35)
at endReadableNT (node:internal/streams/readable:1359:12)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
Go to google developer console for your project. Under library search for People api.
Enable it.
Related
folks. I'm working on a tiny app using OAuth (via Battle.Net) and PassportJS + Express, and I keep getting an Internal Server Error no matter what I do.
I've read their code numerous times, tried using ES6 syntax and ES5 syntax (I'm using babel-watch for transpiling), to no avail.
This is my current Express setup using the BNet Passport Strategy:
import fs from 'fs';
import path from 'path';
import express from 'express';
import cookieParser from 'cookie-parser';
import { ApolloServer } from 'apollo-server-express';
import session from 'express-session';
import passport from 'passport';
const BnetStrategy = require('passport-bnet').Strategy;
// Get our stuff from env vars
const BNET_ID = process.env.BNET_ID;
const BNET_SECRET = process.env.BNET_SECRET;
// Our GQL stuff
import resolvers from './gql/resolvers';
import typeDefs from './gql/typeDefs';
// Express Stuff
const app = express();
// Integrate Apollo middleware
const gqlServer = new ApolloServer({
typeDefs,
resolvers,
});
// Passport User serialize/deserialize
passport.serializeUser((user, done) => {
return done(null, user)
});
passport.deserializeUser((obj, done) => {
return done(null, obj)
});
// Passport middleware w/ bnet?
passport.use(new BnetStrategy({
clientID: BNET_ID,
clientSecret: BNET_SECRET,
scope: ['wow.profile'],
region: 'us',
passReqToCallback: true,
callbackURL: "http://localhost:4000/auth/bnet/callback"
},
(req, accessToken, refreshToken, profile, done) => {
console.log(req.user, accessToken, profile);
return done(null, profile)
})
);
app.get('/auth/bnet', passport.authenticate('bnet'));
app.get('/auth/bnet/callback', passport.authenticate('bnet', { failureRedirect: '/' }),
(req, res) => {
res.redirect('/');
}
)
app.get('/', function(req, res) {
if(req.isAuthenticated()) {
var output = '<h1>Express OAuth Test</h1>' + req.user.id + '<br>';
if(req.user.battletag) {
output += req.user.battletag + '<br>';
}
output += 'Logout';
res.send(output);
} else {
res.send('<h1>Express OAuth Test</h1>' +
'Login with Bnet');
}
});
// Listen!
app.listen({ port: 4000 }, () => {
console.log(`GQL server is listening at http://localhost:4000${gqlServer.graphqlPath}`);
});
When I flush the cookies from my browser and visit the server's index page, it lets me login using my BNet account, and even triggers the Mobile Authenticator on my phone (which I accepted), but then after I accept the auth on my phone, it tosses this error:
AuthorizationError: Internal server error
at Strategy.OAuth2Strategy.authenticate (/home/czbaker/Projects/wow-warmode/server/node_modules/passport-oauth2/lib/strategy.js:131:25)
at attempt (/home/czbaker/Projects/wow-warmode/server/node_modules/passport/lib/middleware/authenticate.js:361:16)
at authenticate (/home/czbaker/Projects/wow-warmode/server/node_modules/passport/lib/middleware/authenticate.js:362:7)
at Layer.handle [as handle_request] (/home/czbaker/Projects/wow-warmode/server/node_modules/express/lib/router/layer.js:95:5)
at next (/home/czbaker/Projects/wow-warmode/server/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/home/czbaker/Projects/wow-warmode/server/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/home/czbaker/Projects/wow-warmode/server/node_modules/express/lib/router/layer.js:95:5)
at /home/czbaker/Projects/wow-warmode/server/node_modules/express/lib/router/index.js:281:22
at Function.process_params (/home/czbaker/Projects/wow-warmode/server/node_modules/express/lib/router/index.js:335:12)
at next (/home/czbaker/Projects/wow-warmode/server/node_modules/express/lib/router/index.js:275:10)
I've checked callbacks for all of the functions to see that they're formatted correctly (returning done(null, <value>) seems to be a big thing people miss, after looking around at similar issues, but it's fine here.
I have no idea what I'm doing wrong, so any assistance would be super appreciated. Thanks!
It turns out that my problem was that the callback URL needed to use HTTPS, as is a requirement from the OAuth2 API on Blizzard's end, and I failed to realize that.
Upon setting up SSL/HTTPS on my Express server, everything worked fine, so I guess the JS error itself wasn't super helpful.
I just started to learn OAuth. I am using passport-google-oauth20 with node.js. Below is the code from the passport-setup.js file of my project.
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20');
const keys = require('./keys')
passport.use(
new GoogleStrategy({
//options for google strategy
callbackURL:'https://localhost:3000/auth/google/redirect',
clientID:keys.google.clientID,
clientSecret:keys.google.clientSecret
}, function(){
//passport callback function
})
);
Code from the auth-route.js file of my project
const router = require('express').Router();
const passport = require('passport');
//auth login
router.get('/login', function(req,res){
res.render('login');
});
//auth logout
router.get('/logout', function(req,res){
//have to handle with passport
res.send('Logging out');
});
//auth with google
router.get('/google', passport.authenticate('google',{
scope:['profile']
}));
//callback route for google
router.get('/google/redirect', passport.authenticate('google'),
function(req,res){
res.send('You logged in');
});
module.exports = router;
Can refer to full code # https://github.com/Ayush-Porwal/OAuth-learning.git
I am trouble with redirect URL. When callbackURL holds the value of "https://localhost:3000/auth/google/redirect", then browser directs me to OAuth consent screen. However, after when I try logging in, the browser(chrome) gives me an error/message as shown in the screenshot.
while on Firefox, the message is as shown(adding only because of error messages are different )
And when callbackURL hold the value of "/auth/google/redirect"(I think both values should give same results). The browser gives the error as
Here is the screenshot for the URI's that I entered in my app on google developer's website.
I tried several things like changing the code a little etc but I'm not able to realize where the problem is arising. Please help.
The process is incomplete. I have now completed my project and I have written an answer regarding the same. Please follow up from here to my answer on Google Oauth giving code redeemed error
I have been able to use node.js and passport.js to connect to Facebook using the GitHub project available at: https://github.com/jaredhanson/passport-facebook/tree/master/examples/login.
Here is the what the app.js code is doing:
var express = require('express')
, passport = require('passport')
, util = require('util')
, FacebookStrategy = require('passport-facebook').Strategy
, logger = require('morgan')
, session = require('express-session')
, bodyParser = require("body-parser")
, cookieParser = require("cookie-parser")
, methodOverride = require('method-override');
var FACEBOOK_APP_ID = "--insert-facebook-app-id-here--"
var FACEBOOK_APP_SECRET = "--insert-facebook-app-secret-here--";
// 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 Facebook profile is serialized
// and deserialized.
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
// Use the FacebookStrategy within Passport.
// Strategies in Passport require a `verify` function, which accept
// credentials (in this case, an accessToken, refreshToken, and Facebook
// profile), and invoke a callback with a user object.
passport.use(new FacebookStrategy({
clientID: FACEBOOK_APP_ID,
clientSecret: FACEBOOK_APP_SECRET,
callbackURL: "http://localhost:3000/auth/facebook/callback"
},
function(accessToken, refreshToken, profile, done) {
// asynchronous verification, for effect...
process.nextTick(function () {
// To keep the example simple, the user's Facebook profile is returned to
// represent the logged-in user. In a typical application, you would want
// to associate the Facebook account with a user record in your database,
// and return that user instead.
return done(null, profile);
});
}
));
var app = express();
// configure Express
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(logger());
app.use(cookieParser());
app.use(bodyParser());
app.use(methodOverride());
app.use(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(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/facebook
// Use passport.authenticate() as route middleware to authenticate the
// request. The first step in Facebook authentication will involve
// redirecting the user to facebook.com. After authorization, Facebook will
// redirect the user back to this application at /auth/facebook/callback
app.get('/auth/facebook',
passport.authenticate('facebook'),
function(req, res){
// The request will be redirected to Facebook for authentication, so this
// function will not be called.
});
// GET /auth/facebook/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('/auth/facebook/callback',
passport.authenticate('facebook', { 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')
}
The code works great if I am just using the internet with no proxy server but if I am behind a corporate firewall then I get the following error:
InternalOAuthError: Failed to obtain access token
at Strategy.OAuth2Strategy._createOAuthError (C:\FacebookExample\passport-facebook\examples\login\node_modules\passport-facebook\node_modules\passport-oauth2\lib\strategy.js:348:17)
at C:\FacebookExample\passport-facebook\examples\login\node_modules\passport-facebook\node_modules\passport-oauth2\lib\strategy.js:171:43
at C:\FacebookExample\passport-facebook\examples\login\node_modules\passport-facebook\node_modules\passport-oauth2\node_modules\oauth\lib\oauth2.js:177:18
at ClientRequest.<anonymous> (C:\FacebookExample\passport-facebook\examples\login\node_modules\passport-facebook\node_modules\passport-oauth2\node_modules\oauth\lib\oauth2.js:148:5)
at emitOne (events.js:77:13)
at ClientRequest.emit (events.js:169:7)
at TLSSocket.socketErrorListener (_http_client.js:259:9)
at emitOne (events.js:77:13)
at TLSSocket.emit (events.js:169:7)
at emitErrorNT (net.js:1253:8)
Does anyone know how to setup the code above to go through a corporate proxy server for connectivity? I have tried setting the npm configuration properties of proxy, http-proxy and https-proxy but it does not appear to make a difference when I run this application. Any help you can offer would be greatly appreciated. Thank you.
Adding this code in /node_moduels/oauth/lib/oauth.js would fix the issue temporarily.
var HttpsProxyAgent = require('https-proxy-agent');
if (process.env['https_proxy']) {
httpsProxyAgent = new HttpsProxyAgent(process.env['https_proxy']);
}
Finally, set the httpsProxyAgent to the request options right before _executeRequest gets called like this:
options.agent = httpsProxyAgent
oauth2.js does not take in consideration the proxy environment variables when it performed the requests. Blocking the web app to get authenticated (receive the access token and the github user info)
So I tried with this workarround that let know to the oauth2.js that uses the proxy to communicate.
You usually will find the oauth2.js code that needs to adapt at: your_project/node_modules/oauth/lib/oauth2.js
var querystring= require('querystring'),
crypto= require('crypto'),
https= require('https'),
http= require('http'),
URL= require('url'),
OAuthUtils= require('./_utils');
// line codes to add
var HttpsProxyAgent = require('https-proxy-agent');
let httpsProxyAgent = null
if (process.env['https_proxy']) {
httpsProxyAgent = new HttpsProxyAgent("http://127.0.0.1:1087");
// fill in your proxy agent ip and port
}
....
// line codes to add
options.agent = httpsProxyAgent;
this._executeRequest( http_library, options, post_body, callback );
}
exports.OAuth2.prototype._request= function(method, url, headers, post_body, access_token, callback) {
...
Adding
options.agent = httpsProxyAgent
worked for me. But I added it in $workdir\node_modules\oauth\lib\oauth2.js as method _executeRequest exists only there.
If you have trouble finding _executeRequest I recommend do full search in node_modules\oauth as I found that method in oauth2.js
Also, don't forget that if you use third party API that you should consider them as well. I use vkAPI SDK, which is basically a wrapper over http_library with handy methods.
In that case I would suggest to wrap http_library calls and decorate them for your need.
Good way to start here Anyway to set proxy setting in passportjs?
I have passport working with Google, and Facebook. I have attempted to add Github to add these credentials so I can do validated Github API calls. So I simply added the same pattern I used to login using either Google or Facebook credentials.
BUT I see InternalOAuthError in the middle of my code after the auth callback has taken place from Github. This happens when the nearly last line: 'return done(null, user.userData);' is called. Attempting to debug interferes with the callbacks. SO I am hoping that someone with greater clarity about passport can explain what I am doing wrong.
What is really strange is that I have already received the user profile from github and stored in in my database with 'user.update(db)', in the same way I do with google. Then the crash happens when I attempt to return by calling done(...).
Do I need to add something to my profile on github? or something else?
Or is this because I already have used passport much earlier to login using Google credentials. Note that for Google, or Facebook, I have specified session: false. I have attempted this with both 'passport-github' and 'passport-github2'.
The code for clarity is:
index.js
var express = require('express');
var passport = require('passport');
var auth = require('../auth.service');
var router = express.Router();
router
.get('/:user', passport.authenticate('github', {
failureRedirect: '/signup',
session: false
}))
.get('/callback', passport.authenticate('github', {
failureRedirect: '/signup',
session: true
}), auth.setTokenCookie);
module.exports = router;
and the corresponding passport.js
var passport = require('passport');
var GitHubStrategy = require('passport-github2').Strategy;
var monk_db = rekuire('server/monk_db');
var loggingAndErrors = rekuire('./loggingAndErrors');
var auth = require('../auth.service');
var config = require('../../config/environment');
var jwt = require('jsonwebtoken');
var expressJwt = require('express-jwt');
var validateJwt = expressJwt({ secret: config.secrets.session });
var jwtDecode = require('jwt-decode');
var ObjectID = require("bson-objectid");
exports.setup = function (User, config) {
passport.use(new GitHubStrategy({
clientID: config.github.clientID,
clientSecret: config.github.clientSecret,
callbackURL: config.github.callbackURL,
passReqToCallback: true
},
function(req, accessToken, refreshToken, profile, done) {
//loggingAndErrors.logger.log(accessToken);
var token = req.cookies.token;
var decoded = jwtDecode(token);
var user_id = decoded._id;
var db = monk_db.getDb();
var users = User.getUsers(db);
users.findById(ObjectID(user_id), function(err, user) {
if (err) {
loggingAndErrors.loggerError.log(err);
return done(err);
}
//loggingAndErrors.logger.log(profile);
user.github=profile._json
user = User.newUser(user);
user.update(db).onResolve(function(err, result) {
if (err) {
loggingAndErrors.loggerError.log(err);
return done(err);
}
//loggingAndErrors.logger.log(user);
loggingAndErrors.logger.log("calling done(err, user) for user_id:", user.userData._id);
return done(null, user.userData);
});
});
}
));
};
The crash is:
{ statusCode: 404,
data: '{"message":"Not\
Found","documentation_url":"https://developer.github.com/v3"}' }
GET /auth/github/callback?code=7c0c6dff81cdd9417301 500 945.444 ms - 674
InternalOAuthError: Failed to fetch user profile
at /home/joel/workspace/Tracker2/node_modules/passport-github2/lib/strategy.js:118:21
at passBackControl (/home/joel/workspace/Tracker2/node_modules/passport-github2/node_modules/passport-oauth2/node_modules/oauth/lib/oauth2.js:123:9)
at IncomingMessage.<anonymous> (/home/joel/workspace/Tracker2/node_modules/passport-github2/node_modules/passport-oauth2/node_modules/oauth/lib/oauth2.js:142:7)
at IncomingMessage.emit (events.js:129:20)
at _stream_readable.js:908:16
at process._tickDomainCallback (node.js:381:11)
I just ran into the same problem, so here is what works for me.
Use passport-github2 and request access to the user's email address when authenticating:
passport.authenticate('github', { scope: [ 'user:email' ] }));
There are other permissions that you may want to access at the same listed in the GitHub OAuth documentation.
I'm working with passport-linkedin and I'm getting this error.
InternalOAuthError: failed to obtain request token
at /Users/davey/code/node/appify-frontend/node_modules/passport-linkedin/node_modules/passport-oauth/lib/passport-oauth/strategies/oauth.js:196:36
at /Users/davey/code/node/appify-frontend/node_modules/passport-linkedin/lib/passport-linkedin/strategy.js:80:19
at passBackControl (/Users/davey/code/node/appify-frontend/node_modules/passport-linkedin/node_modules/passport-oauth/node_modules/oauth/lib/oauth.js:397:13)
at IncomingMessage.<anonymous> (/Users/davey/code/node/appify-frontend/node_modules/passport-linkedin/node_modules/passport-oauth/node_modules/oauth/lib/oauth.js:409:9)
at IncomingMessage.emit (events.js:129:20)
at _stream_readable.js:908:16
at process._tickCallback (node.js:355:11)
GET /oauth/linkedin 500 1074ms - 786b
Here's what my setup looks like
exports.setup = function (config) {
var passport = require('passport');
var LinkedinStrategy = require('passport-linkedin').Strategy;
passport.use(new LinkedinStrategy({
consumerKey: config.linkedin.clientID,
consumerSecret: config.linkedin.clientSecret,
callbackURL: config.linkedin.callbackURL
},
function(token, tokenSecret, profile, done) {
console.log(token, tokenSecret, profile);
return done(null, true);
}
));
};
and my routing setup is as follows
router
.get('/',
function(req, res, next) {
console.log("[OAuth2:redirect:query]:", JSON.stringify(req.query));
console.log("[OAuth2:redirect:body]:", JSON.stringify(req.body));
next();
},
passport.authenticate('linkedin', {
failureRedirect: '/settings/connected-accounts',
session: false
}))
.get('/callback', passport.authenticate('linkedin', {
failureRedirect: '/settings/connected-accounts',
session: false
}), function (req, res){
res.redirect('/settings/connected-accounts');
});
In the same app, I've setup twitter and facebook oauth, both of which work very well. I have no idea what's causing this error and have tried everything.
In my linkedin developer account, I've configured everything as should be.
Authorized Redirect URLs:
http://testdomain.ngrok.io/oauth/linkedin/callback
Default "Accept" Redirect URL:
http://testdomain.ngrok.io/settings/connected-accounts
I first used a localhost url running on port 9000, but when that failed, I exposed my app running locally to a live url, but I still had the same error.
Any help is appreciated. Thanks
The InternalOAuthError is related to passport-oauth1 ( https://github.com/jaredhanson/passport-linkedin/blob/master/lib/strategy.js ) , but you use OAuth2 according to your routing setup. So try switching to passport-linkedin-oauth2