3

EDIT: for some reason my Vue frontend isn't setting the session cookie

Goal:

Implement Login with Twitch and have synced authenticated session between frontend and backend

Description:

I have a problem with making Passport.js authentication work when in development environment with my architecture described below. I'm trying to implement Login with Twitch (social website) using passport-twitch

Frontend: Vue.js, webpack

Backend: Node, Express, Passport

My Development Environment:

I run npm run dev and have a hot-reload server running my Vue.js client on localhost:8080. Note that this hot-reload server for reloading the frontend is only run when I'm developing.

I also have my Node backend serving some APIs while running on localhost:3000 and my local frontend will make HTTP requests to the local backend.

Production Environment

When preparing for production, I will run npm run build on my Vue.js frontend and it will be minified and placed in a dist folder as plain static HTML, CSS, and JS files.

My Node/Express backend server will serve these static files as well as supporting the backend APIs.

Code

This is my auth.js module that I import in my app.js file that npm start will start server with:

const passport = require('passport')
const TwitchStrategy = require('passport-twitch').Strategy

// Retrieve our encrypted secrets depending on the environment
const config = require('config')

// Postgresql connection
var knex = require('knex')({
  client: 'pg',
  connection: config.get('postgres')
});

passport.use(new TwitchStrategy({
  clientID: config.get('twitch.clientID'),
  clientSecret: config.get('twitch.clientSecret'),
  callbackURL: config.get('twitch.authCallbackURL'),
  scope: 'user_read'
}, (accessToken, refreshToken, profile, done) => {
  // Upsert into users table
  knex.raw(`
    INSERT INTO users
      (twitch_id)
    VALUES
      (${profile.id})
    ON CONFLICT (twitch_id) DO UPDATE SET
      updated_at = now() at time zone 'utc'
    WHERE users.twitch_id = '${profile.id}'
    RETURNING *`)
  .then((rows, err) => {
    return done(err, profile)
  })
}))

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

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

module.exports = passport

I have these endpoints on localhost:3000 backend running to support passport-twitch

app.get('/auth/twitch', passport.authenticate('twitch'))

app.get('/auth/twitch/callback', passport.authenticate('twitch', { failureRedirect: '/'}), (req, res) => {
  // Successful authentication, redirect home.
  return res.redirect('/')
})

Problem when in Development Environment Workflow

I have 2 servers running in development environment.

When writing and testing frontend code in dev, I'm running hot-reloaded frontend at localhost:8080, and call the backend.

But I need to call localhost:3000/auth/twitch to redirect user to Login with Twitch page. However, when user finishes logging in, it will redirect me to localhost:3000/auth/callback, which redirects to localhost:3000/.

The authenticated sessions are disconnected at this point and frontend has no idea how to auth?

How do I sync the authenticated session in development mode between Vue.js client/frontend and the Node backend?

// This helps me get the current authenticated user in the session (returns empty hash in this case)
// Works fine in production mode since the Node backend gets to serve the minified frontend files
app.get('/self', (req, res) => {
  res.json(req.user || {})
})

1 Answer 1

1

Basically I just had to initialize Axios with withCredentials: true

import axios from 'axios'

export default() => {
  return axios.create({
    baseURL: `http://localhost:8081`,
    withCredentials: true
  })
}

Also, when redirecting from my OAuth callback, I had to change it to redirect to my localhost:8080 (hot-reloading Vue frontend) instead of the static files served by my Node backend at localhost:3000

app.get('/auth/twitch/callback', passport.authenticate('twitch', { failureRedirect: '/'}), (req, res) => {
  // Successful authentication, redirect home.
  if(process.env.NODE_ENV === 'production') return res.redirect('/')
  res.redirect('http://localhost:8080')
})
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.