Announcements

Help Wizard

Step 1

NEXT STEP

GET /v1/me/top/tracks 403 Error

GET /v1/me/top/tracks 403 Error

Operating System

Windows 10

 

My Question or Issue

My app is currently in development mode. I'm using the client credentials OAuth flow. I've already set up my dashboard, registered my app, gotten my client id and client secret. I am trying to get my top track and display it on my personal website (React App), but I keep getting a 403 error when fetching /top/tracks. I am getting the proper token, and when I supply it statically to my method, I get the proper response (status code 200 with proper response), but when I try to dynamically assign the token to the function, (i.e. everytime a user visits my website, I generate a new OAuth token for them and use it), then I get the 403 error.

 

 

 

import React, { useState, useEffect } from 'react'

// omitted keys for privacy reasons
const clientId = ""
const clientSecret = ""

const getToken = async () => {
    const res = await fetch('https://accounts.spotify.com/api/token', {
        method: 'POST',
        headers: {
            'Authorization': 'Basic ' + btoa(clientId + ':' + clientSecret),
            'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: 'grant_type=client_credentials',
    });
    const data = await res.json();
    return data.access_token;
};

const getMostRecentSong = async () => {
    const token = await getToken();
    console.log(token) // this log returns a valid token
    const res = await fetch('https://api.spotify.com/v1/me/top/tracks', {
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${token}`,
        },
    });
    console.log(res); // this log returns a response with error code 403
    const data = await res.json();
    return data.items
};

const App = () => {
   const [data, setData] = useState([]);
   useEffect(() => {
        (async () => {
            try {
                const items = await getMostRecentSong();
                setData(items);
            } catch (error) {
                console.error(error);
            }
        })();
    }, []);
   
   return (
      ...
   )
}

// the response object I'm getting
Response {
   type: 'cors', 
   url: 'https://api.spotify.com/v1/me/top/tracks', 
   redirected: false, status: 403, ok: false, …}
   body: (...)
   bodyUsed: true
   headers: Headers {}
   ok: false
   redirected: false
   status: 403
   statusText: ""
   type: "cors"
   url: "https://api.spotify.com/v1/me/top/tracks"
}

 

I omitted the scope in my token fetch, because the docs mention that scope is not needed for tracks, since the playlists I want to fetch are all public anyways. Including a scope does not resolve the issue though.

Reply
1 Reply

Hi there and welcome to the forum!

 

The client credentials flow is intended for "server-to-server" integrations, and as such it does not support the end points that include user information. From the Client Credentials Flow section of the authorization guide:

The Client Credentials flow is used in server-to-server authentication. Since this flow does not include authorization, only endpoints that do not access user information can be accessed.

 

You need to use the Code Flow (with or without PKCE).

 

The Web Playback SDK guide is a good step-by-step tutorial on how you could do this using React. The example uses a node.js server component because it uses the Code Flow without PKCE. You can do this in pure React by using PKCE, but unfortunately we do not have a complete example for this yet.

Suggested posts