I’m working on a React app with multiple Docker services and need help configuring Spotify OAuth flow
Hi everyone! I have a dockerized application that needs to handle Spotify authentication alongside my regular user auth. The project structure looks like this:
project/
api/
proxy/
prod.conf
Dockerfile-prod
frontend/
build/
config/
Dockerfile-prod
node_modules/
package.json
public/
src/
Main.jsx
modules/
SpotifyAuth.jsx
music-service/
Dockerfile-prod
node_modules
package.json
oauth/
server.js
The app requires two separate authentication steps:
- My internal user authentication (already working)
- Spotify OAuth which needs a redirect URL and returns an access token
For Spotify auth, users should visit a login page at http://localhost:9000, authorize the app, and get redirected back with tokens.
My Docker configuration:
proxy:
build:
context: ./services/proxy
dockerfile: Dockerfile-prod
restart: always
ports:
- 80:80
depends_on:
- api
- frontend
- music-service
frontend:
build:
context: ./services/frontend
dockerfile: Dockerfile-prod
volumes:
- './services/frontend:/app'
- '/app/node_modules'
ports:
- 3001:3000
environment:
- NODE_ENV=development
- REACT_APP_API_URL=${REACT_APP_API_URL}
depends_on:
- api
music-service:
build:
context: ./services/music-service
dockerfile: Dockerfile-prod
volumes:
- './services/music-service:/app'
- '/app/node_modules'
ports:
- 9000:3000
environment:
- NODE_ENV=development
depends_on:
- api
- frontend
Nginx config:
server {
listen 80;
listen 9000;
location / {
proxy_pass http://frontend:3000;
proxy_redirect default;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /api {
proxy_pass http://api:5000;
proxy_redirect default;
proxy_set_header Host $host;
}
}
React component for Spotify login:
import React, { Component } from 'react';
class SpotifyAuth extends Component {
render() {
return (
<div className='spotify-login'>
<a href='http://localhost:9000'> Connect to Spotify </a>
</div>
);
}
}
export default SpotifyAuth;
Express server for OAuth:
const express = require('express');
const request = require('request');
const querystring = require('querystring');
const CLIENT_ID = 'my_client_id';
const CLIENT_SECRET = 'my_secret';
const REDIRECT_URL = 'http://localhost:9000';
const app = express();
app.get('/authorize', function(req, res) {
const state = Math.random().toString(36);
const scope = 'user-read-private user-read-email';
res.redirect('https://accounts.spotify.com/authorize?' +
querystring.stringify({
response_type: 'code',
client_id: CLIENT_ID,
scope: scope,
redirect_uri: REDIRECT_URL,
state: state
}));
});
app.get('/callback', function(req, res) {
const code = req.query.code || null;
const authConfig = {
url: 'https://accounts.spotify.com/api/token',
form: {
code: code,
redirect_uri: REDIRECT_URL,
grant_type: 'authorization_code'
},
headers: {
'Authorization': 'Basic ' + (Buffer.from(CLIENT_ID + ':' + CLIENT_SECRET).toString('base64'))
},
json: true
};
request.post(authConfig, function(error, response, body) {
if (!error && response.statusCode === 200) {
const accessToken = body.access_token;
const refreshToken = body.refresh_token;
res.redirect('http://localhost:3001/#' +
querystring.stringify({
access_token: accessToken,
refresh_token: refreshToken
}));
}
});
});
app.listen(9000);
Right now when I click the Spotify login link, I get a connection refused error. How should I configure the nginx proxy to properly route between my main React app and the Spotify OAuth service? I need users to start at the main app, go through Spotify auth, and return back to the main app with the tokens.