So I've been using Flask to create an app that uses Spotify API, and the authorization code flow works perfectly fine when running on my localhost server. However, after deploying the app to Heroku, occasionally the app will crash and give me a 'token not provided' error in the logs. Sometimes it'll work flawlessly, but when I play around with it more it'll crash. I try to redo the process on my localhost but it doesn't seem to break. I'm storing the token in sessions, could it be that Heroku is having problem with retrieving session variables?
Here's the flask app code
#Home view
@app.route('/')
@app.route('/home')
def home():
return render_template('home.html', title='Home')
#Login view
@app.route('/login', methods=['GET','POST'])
def login():
AUTH_FIRST = req_auth()
return redirect(AUTH_FIRST)
#Callback view for Spotify API
@app.route('/callback')
def callback():
if request.args.get('code'):
code = request.args.get('code')
token = req_token(code)
session['token'] = token
return redirect(url_for('generate_playlist'))
else:
return redirect(url_for('home'))
#Generate playlist view
@app.route('/generate_playlist', methods=['GET', 'POST'])
def generate_playlist():
if request.method == 'POST':
levels = int(float(request.form['level']))
token = session.get('token')
generate(token, levels)
return redirect(url_for('success'))
else:
return redirect(url_for('generate_playlist'))
This is the backend authorization code (I've commented out some parts to make it simpler, yet it still doesn't work):
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
redirect_uri = os.environ.get('REDIRECT_URI')
state = ''.join(random.choice(string.ascii_lowercase + string.digits) for n in range(8))
scope = 'user-top-read user-library-read playlist-modify-public'
def req_auth():
show_dialog = "false"
AUTH_FIRST_URL = f'https://accounts.spotify.com/authorize?client_id={client_id}&response_type=code&redirect_uri={quote("https://surprisify-playlist-generator.herokuapp.com/callback")}&show_dialog={show_dialog}&state={state}&scope={scope}'
return AUTH_FIRST_URL
def req_token(code):
#B64 encode variables
client_creds = f"{client_id}:{client_secret}"
client_creds_b64 = base64.b64encode(client_creds.encode())
#Token data
token_data = {
"grant_type": "authorization_code",
"code": code,
"redirect_uri": "https://surprisify-playlist-generator.herokuapp.com/callback"
}
#Token header
token_header = {
"Authorization": f"Basic {client_creds_b64.decode()}"
}
#Make request post for token info
token_json = requests.post('https://accounts.spotify.com/api/token', data=token_data, headers=token_header)
return token_json.json()['access_token']
#Checking if token is still valid, otherwise, refresh
# if token_json.json()['expires_in']:
# now = datetime.datetime.now()
# expires_in = token_json.json()['expires_in']
# expires = now + datetime.timedelta(seconds=expires_in)
# if now > expires:
# refresh_token_data = {
# "grant_type": "refresh_token",
# "refresh_token": token_json.json()['refresh_token']
# }
# refresh_token_json = requests.post('https://accounts.spotify.com/api/token', data=refresh_token_data, headers=token_header)
# token = refresh_token_json.json()['access_token']
# return token
# else:
# token = token_json.json()['access_token']
# return token
# else:
# token = token_json.json()['access_token']
# return token