0

Working with spotipy library and a React frontend. Used the Flask Spotipy example code as a basis and changed it for testing purposes to see if my idea works. Currently stuck on a bug that I can't seem to understand. I am able to authenticate the user just fine however I can only send ONE api request. After that I get an error similar to this

raise SpotifyOauthError(spotipy.oauth2.SpotifyOauthError: error: invalid_grant, error_description: Invalid authorization code

Not sure if it has to do with refresh tokens but I can never send multiple requests when I authroize a user.

Here is my python code and react code



import os
from flask import Flask, session, request, redirect, jsonify
from flask_cors import CORS, cross_origin
from flask_session import Session
import spotipy

app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(64)
app.config['SESSION_TYPE'] = 'filesystem'
app.config['SESSION_FILE_DIR'] = './.flask_session/'
CORS(app, resources={r"/*": {"origins": "*"}})
Session(app)

client_id = os.getenv("SPOTIPY_CLIENT_ID")
client_secret = os.getenv("SPOTIPY_CLIENT_SECRET")
redirect_uri = os.getenv("SPOTIPY_REDIRECT_URI")
scope = 'user-read-currently-playing playlist-modify-private user-read-recently-played'
@app.route('/')
def index():

    cache_handler = spotipy.cache_handler.FlaskSessionCacheHandler(session)
    auth_manager = spotipy.oauth2.SpotifyOAuth(scope=scope,
                                               cache_handler=cache_handler,
                                               show_dialog=True)

    if request.args.get("code"):
        # Step 2. Being redirected from Spotify auth page
        auth_manager.get_access_token(request.args.get("code"))
        session['access_token'] = auth_manager.get_access_token(request.args.get("code"))
        return redirect('http://localhost:3000/?code=' + request.args.get("code"))

    if not auth_manager.validate_token(cache_handler.get_cached_token()):
        # Step 1. Display sign in link when no token
        auth_url = auth_manager.get_authorize_url()
        # let react grab the url
        return jsonify({'url': auth_url})

    # Step 3. Signed in, display data
    spotify = spotipy.Spotify(auth_manager=auth_manager)
    return f'<small><a href="/sign_out">[sign out]<a/></small></h2>' \
           f'<a href="/playlists">my playlists</a> | ' \
           f'<a href="/currently_playing">currently playing</a> | ' \
        f'<a href="/current_user">me</a>' \



@app.route('/sign_out')
def sign_out():
    session.pop("token_info", None)
    return redirect('/')


@app.route('/recently-played')
def recently_played():
    code = request.args.get('code')
    cache_handler = spotipy.cache_handler.FlaskSessionCacheHandler(session)
    auth = spotipy.oauth2.SpotifyOAuth(cache_handler=cache_handler)
    if not auth.validate_token(cache_handler.get_cached_token()):
        token_info = auth.get_access_token(code)
    else:

        token_info = cache_handler.get_cached_token()
    spotify = spotipy.Spotify(auth=token_info['access_token'])
    return spotify.current_user_recently_played(limit=10)
   
@app.route('/currently_playing')
def currently_playing():
    cache_handler = spotipy.cache_handler.FlaskSessionCacheHandler(session)
    auth_manager = spotipy.oauth2.SpotifyOAuth(cache_handler=cache_handler)
    if not auth_manager.validate_token(cache_handler.get_cached_token()):
        return redirect('/')
    spotify = spotipy.Spotify(auth_manager=auth_manager)
    track = spotify.current_user_playing_track()
    if not track is None:
        return track
    return "No track currently playing."


@app.route('/current_user')
def current_user():
    code = request.args.get('code')
    cache_handler = spotipy.cache_handler.FlaskSessionCacheHandler(session)
    auth = spotipy.oauth2.SpotifyOAuth(cache_handler=cache_handler)
    if not auth.validate_token(cache_handler.get_cached_token()):
        token_info = auth.get_access_token(code)
    else:

        token_info = cache_handler.get_cached_token()
    spotify = spotipy.Spotify(auth=token_info['access_token'])
    return spotify.current_user()


'''
Following lines allow application to be run more conveniently with
`python app.py` (Make sure you're using python3)
(Also includes directive to leverage pythons threading capacity.)
'''
if __name__ == '__main__':
    app.run(threaded=True, port=int(os.environ.get("PORT",
                                                   os.environ.get("SPOTIPY_REDIRECT_URI", "8080").split(":")[-1])))

import React, { useState, useEffect } from "react";
import axios from "axios";

const CurrentUser = () => {
    const [currentUser, setCurrentUser] = useState(null);

  const getCurrentUser = () => {

    const urlParams = new URLSearchParams(window.location.search);
    const code = urlParams.get("code");    
    axios.get(`http://127.0.0.1:8080/current_user?code=${code}`).then((response) => {
        setCurrentUser(response.data.display_name);
    }
    );
  };


  return (
    <div>
      <button onClick={getCurrentUser} style={{"margin": "5px"}}>Get Current User</button>
      <div>
        {currentUser}
          </div>
    </div>
  );
};

export default CurrentUser;

import React, { useState, useEffect } from "react";
import axios from "axios";

const RecentPlay = () => {
  const [recentPlay, setRecentPlay] = useState(null);

  const getRecentPlay = () => {

    const urlParams = new URLSearchParams(window.location.search);
    const code = urlParams.get("code");    
    axios.get(`http://127.0.0.1:8080/recently-played?code=${code}`).then((response) => {
      setRecentPlay(response.data.items);
    }
    );
  };


  return (
    <div>
      <button onClick={getRecentPlay}>Get Recent Play</button>
      <div>
        {recentPlay &&
          recentPlay.map((item,index) => {
            return (
              <div key={index}>
                <img src={item.track.album.images[0].url} alt="album cover" />
                <p>{item.track.name}</p>
                <p>{item.track.artists[0].name}</p>
              </div>
            );
          })}
          </div>
    </div>
  );
};

export default RecentPlay;
Abraham.
  • 69
  • 6
  • When you want to refresh token, you need to send in body of POST request to /api/token endpoint code(not access_token). To receive code, you should send same request to https://accounts.spotify.com/authorize endpoint but with parameter `response_type=code`. Can this help you? https://stackoverflow.com/questions/57618366/how-to-fix-error-invalid-grant-invalid-authorization-code-when-asking-for-res – MOLLY Dec 27 '22 at 02:16

0 Answers0