Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What do I do with a spotify api authentication redirect uri in Django?

I've built an app in Django that uses Spotipy, a Spotify API Python Library, and uses the spotipy.util.prompt_for_user_token() command as such to generate a token and access my private library as such:

import spotipy
import spotipy.util as util
import os, ast

#Spotify API keys
scope = "playlist-read-private"
uir = "http://localhost:8000"
username = "<MY_USERNAME>"

spotify_uid = os.environ["SPOTIFY_UID"]
spotify_usec = os.environ["SPOTIFY_USEC"]
print "retrieved keys from OS"

#set up access
def get_access():
  try:
    token = util.prompt_for_user_token(username, scope, spotify_uid, spotify_usec, uir)
    print "SUCCESS"
    return spotipy.Spotify(auth=token)
  except:
    print "FAILED TO LOAD"

I'd like the app to have a ui login instead of a hardcoded login, but I can't figure out how.

At the moment I have a 'login' button which attempts to trigger the login page redirect through Javascript, by calling the above code with a username parameter, but that opens a new page and the following is in the console:

User authentication requires interaction with your
        web browser. Once you enter your credentials and
        give authorization, you will be redirected to
        a url.  Paste that url you were directed to to
        complete the authorization.


Opening https://accounts.spotify.com/authorize?scope=playlist-read-     private&redirect_uri=http%3A%2F%2Flocalhost%3A8000&response_type=code&client_id=<CLIENT_ID> in your browser


Enter the URL you were redirected to: [30/Jun/2016 15:53:54] "GET /?code=<TOKEN>HTTP/1.1" 200 2881 

note: the text in carat brackets were replaced since they were private keys.

I'd like it to have similar functionality to how this website handles logins: http://static.echonest.com/SortYourMusic/

like image 353
Ryan Finley Avatar asked Nov 09 '22 12:11

Ryan Finley


1 Answers

To implement this I ended up abandoning the spotipy module all together and just using javascript. I see your using the user authorization api flow which is fine because your server can send your secret key securely. When moving this to the frontend of your application you can't do this and instead must use the Implicit Grant flow:

#In your main page's <script>:
var loginSpotify = function(){
        var SPOTIPY_CLIENT_ID = "Your Client ID Here"
        var SPOTIPY_REDIRECT_URI = "Your Django Callback View Here (www.example.com/callback/)"
        var spotifyScope = "playlist-read-private"
        var spotifyAuthEndpoint = "https://accounts.spotify.com/authorize?"+"client_id="+SPOTIPY_CLIENT_ID+"&redirect_uri="+SPOTIPY_REDIRECT_URI+"&scope="+spotifyScope+"&response_type=token&state=123";
        window.open(spotifyAuthEndpoint,'callBackWindow','height=500,width=400');
        //This event listener will trigger once your callback page adds the token to localStorage
        window.addEventListener("storage",function(event){
            if (event.key == "accessToken"){
                var spAccessToken = event.newValue;
                //do things with spotify API using your access token here!!
            }
        });
    }

Calling the above method will open a new popup window that will take the user through spotify's login. Once authorized, the window will redirect to the Django view you specify. Have that view load a callback page whose only purpose will be to collect the access token from its URI:

#in your views.py:
def callback(request):
    return render(request, 'YourApp/spotifyLoginFinish.html',{})

When that page loads, in the popup window, it's URI will contain the grant you seek, ex: http://www.example.com/callback/#access_token=BQDoPzyrkeWu7xJegj3v1JDgQXWzxQk2lgXrQYonXkXIrhmjeJVS38PFthMtffwlkeWJlwejkwewlHaIaOmth_2UJ2xJrz2x-Voq0k0T0T4SuCUdIGY3w3cj5CpULkFla9zwKKjvdauM2KoUIQa1vULz-w8Da83x1&token_type=Bearer&expires_in=3600&state=123

Idk if youre using jquery or not but theres a bunch of ways to call a JS function on page load. So now all you need to do is parse the URI once the callback page loads and you can get your access token. Then you're done with this popup callback window, so you can pass the access token back to your main page by adding it to localStorage. Remember how on your main page we created an event listener to watch the localStorage so you'll know when its there. Here's an example of the code you'd want on your callback page (it uses some jquery but there are regular JS ways of doing stuff on page load):

#In spotifyLoginFinish.html's <script>:
$('document').ready(function(){
        //i leave 'parseHash()' as an exercise for the reader, all it does is take the uri string(see above ex of what this looks like) and get the access_token from it
        var spotifyAccessToken = parseHash(String(window.location.hash));
        //you must clear localStorage for main page listener to trigger on all(including duplicate) entries
        localStorage.clear();
        localStorage.setItem('accessToken', spotifyAccessToken);
        window.close();
});

Now your popup has closed itself and youre back in your main window, in the localStorage event listener function from the first piece of code in this post. It'll get the token from localStorage and youre all set! Hope this helps, please comment if it doesn't work.

like image 91
stackPusher Avatar answered Nov 14 '22 21:11

stackPusher