spotify / spotify-web-api-ts-sdk

A Typescript SDK for the Spotify Web API with types for returned data.
Other
356 stars 69 forks source link

Unable to Access Current User Top Items after Using Client Credentials Auth #70

Closed oogunjob closed 1 year ago

oogunjob commented 1 year ago

It's my first time using the SDK, and I am having issues with seeing user details in my app. I am using typescript and attempting to create a server side app using the helper methods offered by the SDK. Documentation shared that I should be using the Client Credentials flow if I am creating a server side app. Here is my code (Please note that I removed the client_id and client_secret values after running the app out of auth safety. I have a verified Spotify developer account with valid credentials.)

import { SpotifyApi } from '@spotify/web-api-ts-sdk';

const scope = ['user-read-private', 'user-read-email', 'playlist-modify-public', 'playlist-modify-private, user-read-playback-state, user-modify-playback-state']
const client_id = ''
const client_secret = ''

const sdk = SpotifyApi.withClientCredentials(client_id, client_secret, scope);
const auth = await sdk.authenticate()
// console.log(auth.accessToken.access_token)

const topItems = sdk.currentUser.topItems("artists", "long_term", 10, 0)

Here is a screenshot of the error: image

I'm not entirely sure what the issue is. I've commented out the access token value, but I when looking at it, the user was authenticated and token had not yet been expired. Would be great to receive some help on what I'm doing wrong. Thanks in advance.

davidwhitney commented 1 year ago

There are two errors in the above.

  1. It's using (or indeed, trying to) the ClientCredentials strategy (which is the API keys of YOUR app and YOUR secret) to retrieve a users information. This won't work, because you need the users authorisation to do this (AuthorizationCodeWithPKCEStrategy)

  2. You're missing the scope 'user-top-read'

Here's a working example for what you're looking for:


const scope = [
    'user-read-private',
    'user-read-email',
    'playlist-modify-public',
    'playlist-modify-private',
    'user-read-playback-state',
    'user-modify-playback-state',
    'user-top-read'
];

const strategy = new AuthorizationCodeWithPKCEStrategy(
    import.meta.env.VITE_SPOTIFY_CLIENT_ID,
    import.meta.env.VITE_REDIRECT_TARGET,
    scope
);

const spotify = new SpotifyApi(strategy);
// or 
// const spotify = SpotifyApi.withUserAuthorization(import.meta.env.VITE_SPOTIFY_CLIENT_ID, import.meta.env.VITE_REDIRECT_TARGET, scope);

const topItems = await spotify.currentUser.topItems("artists", "long_term", 10, 0)
console.log("tops", topItems);

Also note that while you're in dev mode, you need to make sure that users you're trying to do this for are registered here: https://developer.spotify.com/dashboard/YOUR-APP-ID/users

Once your app is accepted, it will work for anyone that authenticates.

oogunjob commented 1 year ago

@davidwhitney Apologies for delayed response, but even when copying the same exact code that you've written, I'm still getting an error with auth. Here you can see that I've created the strategy using the client Id and redirect url image

I've already tried rotating my app secret, and I've already added myself in User Management for the app as someone who can use it.

The error is:

@spotify/web-api-ts-sdk/src/auth/AuthorizationCodeWithPKCEStrategy.ts:51
        const hashParams = new URLSearchParams(window.location.search);
                                               ^
ReferenceError: window is not defined
    at AuthorizationCodeWithPKCEStrategy.redirectOrVerifyToken (file:///C:/Users/togun/OneDrive/Desktop/spotify/node_modules/@spotify/web-api-ts-sdk/src/auth/AuthorizationCodeWithPKCEStrategy.ts:51:48)
davidwhitney commented 1 year ago

Ok, so I think the error you're providing there (window is not defined), is because you're trying to do something that requires a front-end user flow (redirecting for user elevation), in node on the server side?

Got a git repro that I can clone and take a look?

This stuff is quite confusing because there are categories of things that can work with only a client key and secret (getting your own profile seems to work, for one), but that exact same auth fails for other operations (I couldn't get my own top tracks without going through client side auth when I tried either).

This might just be a case of "you're trying to do something on the server side that only works with a user scoped access token".

oogunjob commented 1 year ago

Yes! It's now working for me, thanks! @davidwhitney