Heroku App Login works for HTTP but not HTTPS

201 views Asked by At

I have passport.js set up with strategies for Google, Facebook and Github. They work fine over HTTP but not so in HTTPS.

When I'm on my site over HTTPS, and I click for example, Login with Google, I see in my URL bar the site has sent me to the relative URL '/auth/google'. This is the route I've wired in my backend to initiate the OAuth process for logging in. But in HTTPS, I simply end up at the page, there are no error messages in dev console. I have a catch all block of code that serves up index.html when the URL doesn't match any of my routes and I'm pretty sure this is what's happening i.e. the backend routes doesn't seemed to be recognised.

So to summarise, on HTTP, the app stays in a non-logged in state and there are no errors in the dev console.

What's worth noting is that I can also get it to stay in logged in state with the same behaviour as well. If I log in over HTTP and then immediately go to the HTTPS site, I'm logged in. If I try to log out, I get sent to '/auth/logout'. Again no error in console and I get served index.html as if I hadn't written a route for '/auth/logout' and I continue to be logged in.

Because there are no error messages, I don't know what part of the code to show here, I'll just show what I think could be possibly relevant.

Here are my auth routes:

const passport = require('passport')
const express = require('express')

const auth = express.Router()

auth.get(
    '/google',
    passport.authenticate('google', {
        scope: ['profile']
    })
)

auth.get('/google/callback', passport.authenticate('google'), (req, res) => {
    res.redirect('/')
})

auth.get('/facebook', passport.authenticate('facebook'))

auth.get(
    '/facebook/callback',
    passport.authenticate('facebook'),
    (req, res) => {
        res.redirect('/')
    }
)

auth.get('/github', passport.authenticate('github'))

auth.get('/github/callback', passport.authenticate('github'), (req, res) => {
    res.redirect('/')
})

auth.get('/current_user', (req, res) => {
    res.send(req.user)
})

auth.get('/logout', (req, res) => {
    req.logout()
    res.redirect('/')
})

module.exports = auth

Here is my passport strategies

const passport = require('passport')
const GoogleStrategy = require('passport-google-oauth20').Strategy
const FacebookStrategy = require('passport-facebook').Strategy
const GithubStrategy = require('passport-github').Strategy
const mongoose = require('mongoose')

const keys = require('../config/keys')

const User = mongoose.model('user')

passport.serializeUser((user, done) => {
    done(null, user.id)
})

passport.deserializeUser((id, done) => {
    User.findById(id).then(user => {
        done(null, user)
    })
})

const login = (accessToken, refreshToken, profile, done) => {
    User.findOne({ profileID: profile.id }).then(existingUser => {
        if (existingUser) {
            done(null, existingUser)
        } else {
            new User({
                profileID: profile.id
            })
                .save()
                .then(user => done(null, user))
        }
    })
}

passport.use(
    new GoogleStrategy(
        {
            clientID: keys.googleClientID,
            clientSecret: keys.googleSecretKey,
            callbackURL: '/auth/google/callback',
            proxy: true
        },
        login
    )
)

passport.use(
    new FacebookStrategy(
        {
            clientID: keys.facebookClientID,
            clientSecret: keys.facebookSecretKey,
            callbackURL: '/auth/facebook/callback',
            profileFields: ['id', 'name'],
            proxy: true
        },
        login
    )
)

passport.use(
    new GithubStrategy(
        {
            clientID: keys.githubClientID,
            clientSecret: keys.githubSecretKey,
            callbackURL: '/auth/github/callback',
            proxy: true
        },
        login
    )
)

And here is my server index.js

const express = require('express')
const mongoose = require('mongoose')
const passport = require('passport')
const session = require('express-session')
const bodyParser = require('body-parser')

const keys = require('./config/keys')

const auth = require('./routes/authRoutes')
const poll = require('./routes/pollRoutes')

require('./models/User')
require('./services/passport')

mongoose.connect(keys.mongoURI, { useMongoClient: true })
mongoose.Promise = global.Promise

const app = express()

app.use(bodyParser.json())

app.use(
    session({
        secret: keys.cookieKey,
        saveUninitialized: true,
        resave: true
    })
)

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

app.use('/auth', auth)
app.use('/poll', poll)

if (process.env.NODE_ENV === 'production') {
    app.use(express.static('client/build'))
    const path = require('path')
    app.get('*', (req, res) => {
        res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'))
    })
}

const PORT = process.env.PORT || 5000
app.listen(PORT, () => console.log(`Server started on port ${PORT}`))

I'll also provide a link to my Heroku app so you guys can see the buggy behaviour over HTTPS and a link to my Github repo

I'm pretty sure this doesn't have anything to do with how I've set up my Oauth on developer consoles of Google, Facebook and Github because all three login strategies behave exactly the same way so I would have to set up the Google+ API credentials, the Facebook Login settings and the Github Developers Settings all in a way to produce the same error which seems really unlikely. Also everything works correctly on LocalHost. Can someone please help me with this issue?

0

There are 0 answers