0

I have a vanilla JavaScript web app that uses the Spotify API and it works fine. I'm in the process of porting it over to a React front-end and NodeJS/Express back-end but I'm receiving this issue. When the user clicks on the "login" button it shows this error in browser console (private info redacted):

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at 
https://accounts.spotify.com/authorize?response_type=code&client_id=xxx&
scope=playlist-modify-public%20playlist-modify-private
&redirect_uri=http%3A%2F%2Flocalhost%3A8888%2Fcallback%2F&state=xxxxx&show_dialog=true. 
(Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

This is the button in the home page (React):

<button
    onClick={login}
    type="button"
    className="btn btn-primary login-btn col-sm-12 col-lg-6">
    Login with Spotify
</button>

async function login() {
    console.log("Sent Login Request");
    await fetch(`/api/login`, {
      method: "GET",
      headers: { "Content-Type": "application/json" },
    });
  }

In the front-end package.json I have set up proxy:

"proxy": "http://localhost:8888"

This is the app.js (back-end) code that (I think) is relevant to this problem:

app
  .use(express.static(directoryPath))
  .use(helmet())
  .use(compression())
  .use(cors())
  .use(cookieParser());

app.use(function (req, res, next) {
  res.header("Access-Control-Allow-Origin", "localhost"); // update to match the domain you will make the request from
  res.header(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept"
  );
  next();
});

app.get("/api/login", function (req, res) {
  console.log("Started LOGIN flow");
  let state = generateRandomString(16);
  res.clearCookie(stateKey);
  res.cookie(stateKey, state);

  let scope = "playlist-modify-public playlist-modify-private";
  res.redirect(
    "https://accounts.spotify.com/authorize?" +
      querystring.stringify({
        response_type: "code",
        client_id: _client_id,
        scope: scope,
        redirect_uri: _redirect_uri,
        state: state,
        show_dialog: true, // show dialog to allow users to log out
      })
  );
});

app.get("/callback", function (req, res) {
  let code = req.query.code || null;
  let state = req.query.state || null;
  let storedState = req.cookies ? req.cookies[stateKey] : null;

  if (state === null || state !== storedState) {
    res.redirect(
      "/#" +
        querystring.stringify({
          error: "State mismatch",
        })
    );
  } else {
    res.clearCookie(stateKey);
    // request auth
    const params = {
      client_id: _client_id,
      client_secret: _client_secret,
      redirect_uri: _redirect_uri,
      code,
      grant_type: "authorization_code",
    };

    ax({
      method: "post",
      url: "https://accounts.spotify.com/api/token",
      params,
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
      },
    })
      .then((response) => {
        let token = response.data.access_token;
        res.redirect(
          "/#" +
            querystring.stringify({
              authorized: "access_granted",
              token: token,
            })
        );
      })
      .catch((error) => {
        console.log("Failed to login: " + error);
        res.redirect(
          "/#" + querystring.stringify({ authorized: "access_denied" })
        );
      });
  }
});
Ryan Russell
  • 739
  • 1
  • 8
  • 21
  • 1
    Don't redirect responses to API calls. You can't perform an OAuth flow through your server-side code. You need to direct the browser to the Spotify URL – Phil Feb 22 '21 at 01:41
  • You might wanna refer to this issue https://stackoverflow.com/questions/28389699/access-control-allow-origin-denied-spotify-api – Tauseef Ahmad Feb 22 '21 at 15:09

0 Answers0