INTRODUCTION
As you will see below, I already tried 3 methods, mainly from what I could find here on stackoverflow. But I am in a dead end.
I am trying to built a Python 3 script that would make requests to the Spotify API. But first, I need to authenticate via OAuth, and more particularly using the 'Authorization Code' flow, to get an "endless" access. See here. Basically the process consist in those main steps:
GETrequest tohttps://accounts.spotify.com/authorizeendpoint with several parameters including:- the
client_idof my registered app (found on my Spotify Dev Dashbord) - the
redirect_uri
- the
- (user's login if not already logged in)
- (user's authorization for my app if not already authorized)
- redirected to
redirect_uri:https://example.com/callback?code=XYZ - get the
XYZAuthorization Code and pass it back to the main script for next step - [
POSTrequest tohttps://accounts.spotify.com/api/tokenendpoint to get anaccess_token] -> we won't be covering that point in this post, neither the following steps.
Because of the need for the user's credentials and most of all the need for user's authorization, I have to open a browser window. The thing is that I can't get to manage that window how I would like to from my Python 3 script.
ATTEMPT #1
First of all, I have been very inspired from examples given here and more particularly by this one in JavaScript.
INTRODUCTION step 1. is dealt with a webbrowser.open_new_tab(url). Once my app is authorized, Chrome (my default browser) is redirected to localhost. Indeed, my Python 3 script runs a "one-time-only" SimpleHTTPRequestHandler server which waits for the request. When received, it gets the Authorization Code from the window.path, then sends back some HTML code to browser with a window.close(). This last bit of code works when the app is already authorized, but not when the Spotify login page or the Authorization page appears in between. The window won't close in this case. I came to understand that only a window opened via window.open() can be programmatically closed via window.close(). I have attempted many other variations at this point like window.open('','_self').close();. All failed to close the window if the app is not already authorized and user is not already logged in.
QUESTION 1: Why won't it work? And why does it even work when already logged in + authorized?
QUESTION 2: I am thinking that the login window somehow changes the window... But How can I verify that? Chrome console won't help, I don't even get an error for the window.close.
QUESTION 3: Is there a way to keep a handle to the opened window and pass it back to the callback javascript?
ATTEMPT #2
Combining selenium and chromedriver I could successfully open and close that window:
browserdriver.execute_script("window.open('%s', '_self');" % url)window.close()
But the thing is that selenium seems to be more intended for unit testing. So, I could not get it to open a Chrome window using Chrome default profile when already in use in another open Chrome session/instance. It works correctly only when I make a temp user data folder, but by doing so, the login credentials cannot be retrieved from default profile (nor saved), which does not suit me.
QUESTION 4: I have seen a workaround that consists in copying the whole user data folder somewhere and use it to open Chrome, so it has write access to the default profile. This does not suits me... Do you see another solution?
ATTEMPT #3
Back to using webbrowser. The main script now opens a browser that does not directly make the GET request of INTRODUCTION step 1. (previously mentioned url in ATTEMPT #2 step 1. ). It makes a request to localhost that delivers some HTML code to browser with a window.open(url, '_self'). But later, in the callback javascript, 'window.close()` won't work again. Even if user's already logged in and the app authorized! (it worked in ATTEMPT #1 in this particular case)
QUESTION 5: Why is that? the window.open() is even explicit in this case, whereas it was not in ATTEMPT #1 because hidden in the webbrowser class.
If I use window.open(url), I can close the new window with window.close() later on. But the first window remains open, and here again, a new problem: the new window is a blocked popup because it is opened by script and therefore cannot be tracked down to a user action (unlike the example given in INTRODUCTION which uses a "Login" button).
QUESTION 6: How could I open a single browser window, not a blocked popup, and close it, while managing to retrieve the Authorization Code?
Any more ideas?
Note: I am not interested in a solution with a simple copy of the URI the browser redirected to, and then paste in Python interpreter to retrieve the Authorization Code provided by the Spotify Accounts service (as does Spotipy for example).