Google callback url giving back 400 when deployed in heroku - node.js

I developed an app using MEAN framework and used passportjs's google strategy to authenticate. The local run runs fine, but when I deploy the same to heroku, since Heroku runs its app on a random port. I am not sure what google callback url I need to add in my google console's "Authorized redirect URIs".
passport.use(new GoogleStrategy({
clientID: config.googleAuth.clientID,
clientSecret: config.googleAuth.clientSecret,
callbackURL: config.googleAuth.callbackURL
}, function (token, refreshToken, profile, done) {
console.log(token, refreshToken, profile, done);
var query = {
'google.id' : profile.id
};
User.findOne(query, function (err, user) {
if(user){
console.log("User found in the database");
done(null, user);
}
else{
var newUser = new User;
newUser.displayName = profile.displayName;
newUser.image = profile.photos[0].value;
newUser.google = {};
newUser.google.id = profile.id;
newUser.google.token = token;
newUser.save();
console.log("saved user to the database");
done(null, newUser);
}
});
}));
The above shown code is my google strategy. I am using passport-google-oauth lib for authentication.
module.exports = {
development: {
rootPath: rootPath,
db: 'xxx',
port: process.env.PORT || 3030,
googleAuth: {
clientID: 'xxx',
clientSecret: 'xxx',
callbackURL: 'http://localhost:3030/auth/google/callback'
}
},
production: {
rootPath: rootPath,
db: 'xxx',
port: process.env.PORT || 80,
googleAuth: {
clientID: 'xxx',
clientSecret: 'xxxx',
callbackURL: 'https://<myheroku-app>:<heroku-port-no>/auth/google/callback'
}
}
}
The above is the details of my google strategy. The localhost part works fine if I add http://localhost:3030/auth/google/callback to the Authorized redirect URI's. But when I try to do the same for the heroku app, I get a 400 server error with Error: redirect_uri_mismatch as the error.
How do I fix this thing? I am so close to deploying this app and stuck with just this thing. Let me know if you would need any more info.

You need to add heroku domain name and heroku callback url see working example below:

You could use relative paths at callbackURL (eg callbackURL: '/auth/google/callback') to make your code less depended on specific domains, and add an additional element on googleAuth, by putting a comma after callbackURL, as:
proxy: true
After this, you can use https on google's developers console for your callbacks.

Related

Passport Github strategy not working and throwing errors

The code below is getting mad at me. I don't see anything wrong with it.
function User(profile){
console.log(profile)
}
passport.use(
new GitHubStrategy({
clientID: "my_id",
clientSecret: "secret",
callbackURL: "http://localhost:3000/auth/github/callback",
},
function(accessToken, refreshToken, profile, done) {
User(profile),function (err, user) {
return done(err, user);
};
}
)
);
app.get(
"/auth/github",
passport.authenticate("github", { scope: ["user:email"] })
);
app.get(
"/auth/github/callback",
passport.authenticate("github", { failureRedirect: "/login" }),
function(req, res) {
// Successful authentication, redirect home.
res.redirect("/");
}
);
It's throwing a big error every time I try to authenticate. Please help.
Edited the question and did as #jasonandmonte said and now I get this:
The issue I am seeing is you are defining a User function that is only logging the profile. The User function in the documentation is an example of a database model that queries a database and passes data to a callback.
To resolve the issue and replicate how passport-github's example does it, you will need to use an object modeling tool like Mongoose or Sequelize. You will then have access to something similar to User.findOrCreate() or just User.find() if you want to restrict account creation to an admin role.
To get passport working until you setup a database connection though, you should be able to update the strategy callback to invoke done.
passport.use(
new GitHubStrategy({
clientID: "my_id",
clientSecret: "secret",
callbackURL: "http://localhost:3000/auth/github/callback",
},
function(accessToken, refreshToken, profile, done) {
done(null, profile.id);
}
)
);

Node React Google Login

I have been learning react and node together and have been trying to implement using google auth. I believe I have the front end side working as I can get an access token back but I can't seem to complete the authentication with the node side of it. Here is my React code.
export default class GoogleLoginComponent extends Component {
responseGoogle(response){
var id_token = response.getAuthResponse().id_token;
var googlePlus = '101603157010265563225'
console.log({accessToken: id_token});
//axios.get('oauth',id_token)
}
render(){
return(
<GoogleLogin
clientId="115435392551-qamvp0loln91e4d2uoat8pnki4f705o6.apps.googleusercontent.com"
buttonText="Login"
onSuccess={this.responseGoogle.bind(this)}
onFailure={this.responseGoogle.bind(this)}
/>
)
}
}
This will print out the id_token successfully for me. My issue I believe at least(but what do I know) is on the server side. In google I set up oauth as the callback address. Will Google make the get call to oauth or do I have to do it? When I try and do it myself I get a whole mess of errors. Here is the server side code.
var GoogleStrategy = require( 'passport-google-oauth2' ).Strategy;
passport.use(new GoogleStrategy({
clientID: "115435392551-qamvp0loln91e4d2uoat8pnki4f705o6.apps.googleusercontent.com",
clientSecret: "_9tCI3_e-oKFwz1kFkxvRKMM",
callbackURL: "http://localhost:3000/oauth",
passReqToCallback : true
},
function(accessToken, refreshToken, profile, done) {
User.findOrCreate({ googleId: profile.id }, function (err, user) {
return done(err, user);
});
}
));
app.get( '/oauth',
passport.authenticate( 'google', {
successRedirect: 'success.html',
failureRedirect: 'fail.html'
})
);
Any ideas would be greatly appreciated.

using passport module to get facebook profile events

i am trying to get future events user attended to using passport module but im clearly missing something. i followed the Facebook API and got the permission i needed like so :
router.get('/auth/facebook', passport.authenticate('facebook', { scope: [ 'public_profile', 'user_events' ] }));
router.get('/auth/facebook/callback', passport.authenticate('facebook', {
successRedirect:'/welcome',
failureRedirect:'/'
}))
but when i am trying to print an event like this:
passport.use(new FacebookStrategy({
clientID: config.fb.appID,
clientSecret: config.fb.appSecret,
callbackURL: config.fb.callbackURL,
profileFields: ['id', 'displayName', 'photos', 'birthday', 'events', 'profileUrl', 'emails', 'likes']
}, function(accessToken, refershToken, profile, done){
//Check if the user exists in our Mongo DB database
//if not, create one and return the profile
//if exists, return profile
userModel.findOne({'profileID':profile.id}, function(err, result){
if(result){
done(null,result);
} else {
// Create a new user in our mongoLab account
var newFbUSer = new userModel({
profileID: profile.id,
fullname: profile.displayName,
profilePic:profile.photos[0].value || '',
birthday:profile.birthday,
events:profile.events[0].name,
profileUrl:profile.profileUrl,
});
console.log(newFbUSer.profilePic);
newFbUSer.save(function(err){
done(null,newFbUSer);
})
}
})
i get this error:
events:profile.events[0].name,
^
TypeError: Cannot read property '0' of undefined
i tried to replace name with value, as it is working perfectly fine with the photos, and i tried many other ways but i simply can't get this one to work...any help please?

passport-oauth accessing remote url

I try to implement an OAuth solution in nodejs. I used passport-oauth for generating the acccess tokens and refresh tokens which is working.
var passport = require('passport'),
OAuth = require('oauth').OAuth,
url = require('url'),
ArenaNet = require('passport-oauth').OAuth2Strategy,
config = require('../config'),
users = require('../../app/controllers/users.server.controller');
module.exports = function() {
passport.use('arenanet', new ArenaNet({
authorizationURL: config.arenanet.authorizationURL,
tokenURL: config.arenanet.tokenURL,
clientID: config.arenanet.clientID,
clientSecret: config.arenanet.clientSecret,
callbackURL: config.arenanet.callbackURL,
response_type: "code",
scope: "offline account"
},
function(accessToken, refreshToken, code, profile, done) {
console.log(accessToken);
console.log(refreshToken);
console.log(code);
done();
}));
};
This generates the following output:
69XXXXF-776D-4CXX-AXX7-29XXXXXX4DB5
5FXXXXXX-XXX67-E1XXX1-809D-XXXXXXXXXXXXXXXX-XX69-4XX6-XXF-4C6XXXXX08EB
{ access_token: 'XX0XXXXXF-77XXX-4XXXX-XXXA7-295XXXXXXB5',
token_type: 'Bearer',
scope: 'account' }
I am new to OAuth. What confuses me now is how to access a remote url with the tokens. What i have in mind is something like this:
oauth.get(
"https://api.guildwars2.com/v2/account",
accessToken,
function(err, body, response) {
console.log(body);
}
);
What obviously don't work. I saw several examples how i can access local sites with the token, but not how to request something from a remote url.
Any suggestion how i'm able to this with passport-oauth? Or do i need to use a different module for this action?
I hope you can help me here, would be cool!
Thank you all and best regards,
michael

Using PassportJS google authentication with the nodejs google api library

I'm currently looking at implementing a google api, using the nodejs client:
https://github.com/google/google-api-nodejs-client/
I'm trying to use passport in order to authenticate, which seems to be working#
passport.use(new GoogleStrategy({
clientID: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET,
callbackURL: "http://localhost:3000/auth/google/callback"
},
function(accessToken, refreshToken, profile, done) {
process.nextTick(function () {
var user = {
id: profile.id,
email: profile.email,
firstName: profile.given_name,
lastName: profile.family_name,
accessToken: accessToken
};
return done(null, user);
});
}
));
In my google auth callback:
app.get('/auth/google/callback',
passport.authenticate('google', { failureRedirect: '/login' }),
function(req, res) {
//do something here with the google api
});
I can get hold of req.user, and this has the accessToken
However, the docs for the Google api nodejs client aren't clear on how to use an accessToken.
The example included shows the OAauth2Client retrieving a token, but I guess that part has already been covered using Passport?
I'm not familiar with google-api-nodejs-client, but this is in their documentation:
oauth2Client.credentials = {
access_token: 'ACCESS TOKEN HERE',
refresh_token: 'REFRESH TOKEN HERE'
};
client
.plus.people.get({ userId: 'me' })
.withAuthClient(oauth2Client)
.execute(callback);
I assume you can just set the credentials to those provided by Passport, and things will work fine.
Honestly, though, I find these API wrappers really contrived, and recommend just using request. That way you can access any API service from any provider using a familiar module.

Resources