0

Any other requests through my react app seems to be working fine, until I try to res.redirect to somewhere else. I somewhat understand why it does not work, but I cant figure out how to properly implement something similar to that. Code for references:

React app.js:

  function loginToSpotify() {
    axios.get('http://localhost:4000/login')
    .then(res => {
      console.log(res)
    })
    .catch(err => {
      console.log("error!")
    })
  }

express server.js:

var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var cors = require('cors');


var app = express();

app.use(cors())
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/users', usersRouter);

module.exports = app;

express index.js login call:

const { default: axios } = require('axios');
var express = require('express');
var router = express.Router();
var querystring = require('querystring')
var  SpotifyWebApi = require('spotify-web-api-node');
/* GET home page. */

let spotifyApi = new SpotifyWebApi({
    clientId:'c2b60e83cbdb4b5ba923140f0c32ac8f',
    clientSecret:'d45b554801ab4333b89a36bdbf04fad7'
})

let clientId = 'c2b60e83cbdb4b5ba923140f0c32ac8f'
let clientSecret = 'd45b554801ab4333b89a36bdbf04fad7'
let scopes = 'user-read-playback-state user-read-currently-playing'
let redirectUri = 'http://localhost:4000/token'


router.get('/login', (req, res) => {
  res.redirect('https://accounts.spotify.com/authorize' + '?response_type=code&client_id=' + clientId + '&scope=' + encodeURIComponent(scopes) + '&redirect_uri=' + encodeURIComponent(redirectUri))
})

It never even gets redirected back, It just throws this error every time:

Access to XMLHttpRequest at 'https://accounts.spotify.com/authorize?response_type=code&client_id=<removed by me just in case>&scope=user-read-playback-state%20user-read-currently-playing&redirect_uri=http%3A%2F%2Flocalhost%3A3000' (redirected from 'http://localhost:4000/login') from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

I thought that if I make a call from my react app to my server, and then my server redirects to spotify's api it would be fine, but it still gives me this error.

also note that if I access the login page of my server from the browser, it will work but it does not like the "two jumps" I guess

I have seen this thread and am still a bit confused: Access-Control-Allow-Origin denied spotify api If i make the call from my client to my server, then the server makes the call to the token, shouldn't it work?

How can I implement the login properly?

SkyNess
  • 55
  • 8

1 Answers1

0

Step one to avoid CORS issues is to make sure your website on Spotify is 'localhost:4000'.

The redirect is most likely causing the concern. You don't want to use a redirect. You want Spotify to authenticate the user and then redirect them back to your website with a token.

I would suggest using passportJS, this is a much more secure way if you are new to handling tokens and such.

Create a strategy as such

const passport = require('passport');
const SpotifyStrategy = require('passport-spotify').Strategy;
passport.serializeUser(function(user, done) {
  done(null, user);
});
passport.deserializeUser(function(user, done) {
  done(null, user);
});
passport.use(new SpotifyStrategy({
  clientID: "c2b60e83cbdb4b5ba923140f0c32ac8f",
  clientSecret: "d45b554801ab4333b89a36bdbf04fad7",
  callbackURL: "http://localhost:4000/auth/spotify/callback"
},
function(accessToken, refreshToken, profile, done) {
  return done(null, profile);
}
));

PassportJS Spotify Docs

const passport = require('passport');
require('./passport')

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

app.get('/auth/spotify',passport.authenticate('spotify'));
app.get('/auth/spotify/callback',passport.authenticate('spotify', { failureRedirect: '/auth/error' }),
function(req, res) {
  res.redirect('/');
});
app.get('/logout', (req, res) => {
  req.session = null;
  req.logout(); 
  res.redirect('/');
})
Dallas Baker
  • 368
  • 1
  • 10
  • Hey @Dallas Baker, Thanks for the input! I'll take a look at PassportJS, and it does look alot more cleaner. Do you have an explanation on why my current code does not work though? I'd like to also understand my mistakes. – SkyNess Mar 20 '21 at 21:12
  • @SkyNess Yes so you are trying to redirect the user from the server. You need to redirect them from the client side. Once they verify on their side they will get redirected to your site with a code. On the server side you want to take that code and pass it to Spotify. They will in return give you an access token. Scroll past the boilerplate code they initially show. Go to auth flow and start with Part 1. _Have your application request authorization; the user logs in and authorizes access_ [DOCS](https://developer.spotify.com/documentation/general/guides/authorization-guide/) – Dallas Baker Mar 20 '21 at 21:29
  • Oh, so I would rather send the /login request from client side and redirect it back to the client side, then get the code and send a post request to my server with the code to retrieve the token? – SkyNess Mar 20 '21 at 22:03
  • Correct, that would be the recommended approach. – Dallas Baker Mar 20 '21 at 22:10