Skip to content

Instantly share code, notes, and snippets.

@markmur
Last active August 17, 2018 16:05
Show Gist options
  • Save markmur/552cc1446f0428d4d1ce48353b26d5df to your computer and use it in GitHub Desktop.
Save markmur/552cc1446f0428d4d1ce48353b26d5df to your computer and use it in GitHub Desktop.
Express server
// Tell "now" to look for a now-secrets.json file
// (where we'll store our local secrets - NOT production secrets)
require('now-env')
const path = require('path')
const express = require('express')
const session = require('express-session')
const bodyParser = require('body-parser')
const morgan = require('morgan') // optional
const passport = require('passport')
const SpotifyStrategy = require('passport-spotify').Strategy
// For the sake of keeping our server file concise,
// we'll move our API to a separate file
const api = require('./api')
const PORT = process.env.PORT || 8080
// Get required environment variables
const {
CLIENT_ID,
CLIENT_SECRET,
REDIRECT_URI,
NODE_ENV,
SESSION_SECRET
} = process.env
passport.serializeUser((user, done) => done(null, user))
passport.deserializeUser((obj, done) => done(null, obj))
const isProduction = NODE_ENV === 'production'
// Tell passport to use the Spotify strategy
passport.use(
new SpotifyStrategy(
{
clientID: CLIENT_ID,
clientSecret: CLIENT_SECRET,
callbackURL: REDIRECT_URI
},
(accessToken, refreshToken, expires, profile, done) => {
return done(null, {
profile,
token: {
accessToken,
refreshToken
}
})
}
)
)
// Middleware function to check if a user is authenticated.
// If the user is not authenticated we throw a 401 error response
// and prevent moving firing the real request.
const isAuthenticated = (req, res, next) => {
if (req.isAuthenticated()) {
return next()
}
res.status(401).send()
}
// Create the express server
const server = express()
server.use(bodyParser.json())
server.use(session({ secret: SESSION_SECRET }))
// Morgan is used for logging.
// You can omit this dependency if you don't want it, but it's convenient.
server.use(morgan('tiny'))
// In production, the react app is a static, pre-built bundle, so we
// need to tell express that when we hit '/' it returns the index.html in
// the build folder.
// In development, the react app will be running on port 3000 and we'll
// proxy our requests to this server (8080).
// More on that later..
if (isProduction) {
// Serve any static files
server.use(express.static(path.join(__dirname, '..', 'build')))
// Handle React routing, return all requests to React app
server.get('/', (req, res) => {
res.sendFile(path.join(__dirname, '..', 'build', 'index.html'))
})
}
server.use(passport.initialize())
server.use(passport.session())
server.get('/auth/spotify',
passport.authenticate('spotify', {
scope: [
'user-read-email',
'user-read-private',
'playlist-read-private',
'playlist-modify-private',
'playlist-modify-public'
],
showDialog: true
})
)
server.get('/auth/callback',
passport.authenticate('spotify', {
failureRedirect: '/login'
}),
(req, res) => res.redirect(isProduction ? '/' : 'http://localhost:3000')
)
// Route all /api requests to our API
server.use('/api', isAuthenticated, api)
// Start up the server
server.listen(PORT, err => {
if (err) throw err
console.log(`Listening on port ${PORT}`)
})
{
"@app_client_id": "YOUR CLIENT ID",
"@app_client_secret": "YOUR CLIENT SECRET",
"@app_redirect_uri": "http://localhost:8080/auth/callback",
"@app_session_secret": "SESSION_SECRET"
}
{
"name": "your-app-name",
"alias": "your-app-name.now.sh",
"env": {
"CLIENT_ID": "@app_client_id",
"CLIENT_SECRET": "@app_client_secret",
"REDIRECT_URI": "@app_redirect_uri",
"SESSION_SECRET": "@app_session_secret"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment