2

Passport is being used to log in via Discord in order to access a Dashboard. Main problem is the logout though, worked before passport v.0.6.0, but now it doesn't. req.logout(); now needs a callback function (see here) to work, but when I now access /logout on the website I get Error: Login sessions require session support. Did you forget to use 'express-session' middleware?

settings.json

{
    "website": {
        "support": "https://discord.gg/xxxxxxx",
        "domain": "http://localhost:5991"
    },
    "config": {
        "port": 5991,
        "callback": "http://localhost:5991/callback",
        "clientID": "botId",
        "secret": "OAuth2 Secret"
    }
} 

index.js

const express = require('express');
const url = require('url');
const path = require('path');
const ejs = require('ejs');
const passport = require('passport');
const bodyParser = require('body-parser');
const Strategy = require('passport-discord').Strategy;
const settings = require('./settings.json');
const logger = require('silly-logger');
const favicon = require('serve-favicon');

module.exports = client => {
    // website config backend
    const app = express();
    const session = require('express-session');
    const MemoryStore = require("memorystore")(session);

    // middleware
    app.use(session({
        secret: `superdupersecret`,
        store: new MemoryStore({ checkPeriod: 86400000 }),
        resave: false,
        saveUninitialized: false,
    }));

    app.use(favicon(path.join(__dirname, 'public/assets', 'favicon.ico')));

    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({
        extended: true,
    }));
    app.use(express.json());
    app.use(express.urlencoded({
        extended: true,
    }));

    app.set("view engine", "ejs");
    app.set("views", path.join(__dirname, "./views"));

    // loading public
    app.use('/public', express.static(__dirname + '/public'));

    app.use(passport.initialize());
    app.use(passport.session());

    // initialize discord login
    passport.serializeUser((user, done) => done(null, user));
    passport.deserializeUser((obj, done) => done(null, obj));
    passport.use(new Strategy({
        clientID: settings.config.clientID,
        clientSecret: settings.config.secret,
        callbackURL: settings.config.callback,
        scope: ["identify", "guilds", "guilds.join"],
    },
    (accessToken, refreshToken, profile, done) => {
        process.nextTick(()=>done(null, profile));
    },
    ));

    app.get("/login", (req, res, next) => {
        if (req.session.backURL) {
            // eslint-disable-next-line no-self-assign
            req.session.backURL = req.session.backURL;
        } else if (req.headers.referer) {
            const parsed = url.parse(req.headers.referer);
            if (parsed.hostname == app.locals.domain) {
                req.session.backURL = parsed.path;
            }
        } else {
            req.session.backURL = "/";
        }
        next();
    }, passport.authenticate("discord", { prompt: null }));

    app.get("/callback", passport.authenticate("discord", { failureRedirect: "/" }), async (req, res) => {
        res.redirect("/dashboard");
    });

    app.get("/logout", (req, res, next) => {
        req.session.destroy(() => {
            req.logout(function(err) {
                if (err) { return next(err); }
                res.redirect("/");
            });
        });
    });

    const http = require('http').createServer(app);
    http.listen(settings.config.port, () => {
        logger.success(`Website is online on port ${settings.config.port}, ${settings.website.domain}`);
    });
};

EDIT: I found two ways that end the session:

    app.get("/logout", (req, res, next) => {
        req.logout(function(err) {
            if (err) { return next(err); }
            res.redirect("/");
        });
    });

    app.get("/logout", (req, res, next) => {
        req.session.destroy((err) => {
            if (err) { return next(err); }
            res.redirect("/");
        });
    });
EckigerLuca
  • 153
  • 10

0 Answers0