nicholastay / passport-discord

Passport strategy for authentication with Discord (discordapp.com)
ISC License
172 stars 55 forks source link

using passport discord with passport local #12

Closed ViolentCrumble closed 6 years ago

ViolentCrumble commented 6 years ago

Hi so i'm not sure if i'm doing something wrong but there seems to be an issue when trying to use local passport and also passport discord.

If i log in with passport discord it seems to search by discord username and auth that user, regardless of the actual user.

So since usernames are not unique on discord this is not good at all.

It will auth the user correctly and create the user in the database but seems to be logging in with the wrong user.

Is it possible to use this combined with local strategy?

code below

app.js

const LocalStrategy = require('passport-local').Strategy;
const DiscordStrategy = require('passport-discord').Strategy;

passport.use(new DiscordStrategy({
  clientID: process.env.DISCORD_CLIENTID,
  clientSecret: process.env.DISCORD_CLIENT_SECRET,
  callbackURL: process.env.DISCORD_REDIRECT_URL,
  scope: ['identify', 'email']
}, async function(accessToken, refreshToken, profile, cb) {

  User.findOne({ email: profile.email }, async function (err, user){
    if(err) return cb(err);
    if(!user){
      const newUser = new User();
      newUser.email = profile.email;
      newUser.discordID = profile.id;
      newUser.username = profile.username;
      newUser.descrim = profile.discriminator;    
      newUser.save(function (err, saved){
        if(err) return cb(err);
        cb(null, saved);
      });
    } else {
      //user already exists      
      user.username = profile.username;      
      user.save(function (err, saved) {
        if(err) return cb(err, user);
        cb(null, saved);
      });
    }
  });
}));

passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());

route

router.get('/discord-auth', passport.authenticate('discord'));
router.get('/discord-auth/callback', passport.authenticate('discord', {
  failureRedirect: '/account/register'
}), function(req, res) {
  res.redirect('/account/registration-success') // Successful auth
});

user model

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const passportLocalMongoose = require('passport-local-mongoose');
const slug = require('mongoose-slug-generator');

mongoose.plugin(slug);

const User = new Schema({ 
  email: {type: String, unique: true, select: false},  
  password: { type: String, select: false },  
  username: String,
  descrim: String,  
  discordID: String, 
  slug: { type: String, slug: "username", slug_padding_size: 4, unique: true },
});

User.plugin(passportLocalMongoose);

module.exports = mongoose.model('User', User);

The idea being i do not wish for usernames to be unique on the website, rather emails are what is used.

With this, I can authenticate fine with discord but once it has authenticated it will be logged in as whatever user has the same username as the auth'd user. Which if there are other users with the same username it will pick the first one.

Any advice would be appreciated. I have been dealing with this all day

ViolentCrumble commented 6 years ago

ok i think i have solved this.

Was a pain due to very littly docs on the subject on the passport.js website.

I believe the issue came down to how i was serialising and deserialising the user.

i updated my code to use email and now it seems to work.

passport.serializeUser(function(user, done) {
  done(null, user.email);
});

passport.deserializeUser(function(email, done) {
  User.findOne({email: email}, function(err, user) {
    done(err, user);
  });
});