Browse Source
			
			
			Implement User Authorization
			
				
		Implement User Authorization
	
		
	
			
				Completed step 1 of the Authorization Code Flow documented by the Spotify API.master
				 5 changed files with 189 additions and 2 deletions
			
			
		- 
					1musicvis/settings.py
 - 
					5requirements.txt
 - 
					132spotifyvis/templates/spotifyvis/index.html
 - 
					3spotifyvis/urls.py
 - 
					50spotifyvis/views.py
 
@ -1,10 +1,15 @@ | 
			
		|||||
astroid==1.6.3 | 
				astroid==1.6.3 | 
			
		||||
 | 
				certifi==2018.4.16 | 
			
		||||
 | 
				chardet==3.0.4 | 
			
		||||
Django==2.0.5 | 
				Django==2.0.5 | 
			
		||||
djangorestframework==3.8.2 | 
				djangorestframework==3.8.2 | 
			
		||||
 | 
				idna==2.6 | 
			
		||||
isort==4.3.4 | 
				isort==4.3.4 | 
			
		||||
lazy-object-proxy==1.3.1 | 
				lazy-object-proxy==1.3.1 | 
			
		||||
mccabe==0.6.1 | 
				mccabe==0.6.1 | 
			
		||||
pylint==1.8.4 | 
				pylint==1.8.4 | 
			
		||||
pytz==2018.4 | 
				pytz==2018.4 | 
			
		||||
 | 
				requests==2.18.4 | 
			
		||||
six==1.11.0 | 
				six==1.11.0 | 
			
		||||
 | 
				urllib3==1.22 | 
			
		||||
wrapt==1.10.11 | 
				wrapt==1.10.11 | 
			
		||||
@ -0,0 +1,132 @@ | 
			
		|||||
 | 
				<!doctype html> | 
			
		||||
 | 
				<html> | 
			
		||||
 | 
				  <head> | 
			
		||||
 | 
				    <title>Example of the Authorization Code flow with Spotify</title> | 
			
		||||
 | 
				    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css"> | 
			
		||||
 | 
				    <style type="text/css"> | 
			
		||||
 | 
				      #login, #loggedin { | 
			
		||||
 | 
				        display: none; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      .text-overflow { | 
			
		||||
 | 
				        overflow: hidden; | 
			
		||||
 | 
				        text-overflow: ellipsis; | 
			
		||||
 | 
				        white-space: nowrap; | 
			
		||||
 | 
				        width: 500px; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    </style> | 
			
		||||
 | 
				  </head> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  <body> | 
			
		||||
 | 
				    <div class="container"> | 
			
		||||
 | 
				      <div id="login"> | 
			
		||||
 | 
				        <h1>This is an example of the Authorization Code flow</h1> | 
			
		||||
 | 
				        <a href="/login" class="btn btn-primary">Log in with Spotify</a> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				      <div id="loggedin"> | 
			
		||||
 | 
				        <div id="user-profile"> | 
			
		||||
 | 
				        </div> | 
			
		||||
 | 
				        <div id="oauth"> | 
			
		||||
 | 
				        </div> | 
			
		||||
 | 
				        <button class="btn btn-default" id="obtain-new-token">Obtain new token using the refresh token</button> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    <script id="user-profile-template" type="text/x-handlebars-template"> | 
			
		||||
 | 
				      <h1>Logged in as {{display_name}}</h1> | 
			
		||||
 | 
				      <div class="media"> | 
			
		||||
 | 
				        <div class="pull-left"> | 
			
		||||
 | 
				          <img class="media-object" width="150" src="{{images.0.url}}" /> | 
			
		||||
 | 
				        </div> | 
			
		||||
 | 
				        <div class="media-body"> | 
			
		||||
 | 
				          <dl class="dl-horizontal"> | 
			
		||||
 | 
				            <dt>Display name</dt><dd class="clearfix">{{display_name}}</dd> | 
			
		||||
 | 
				            <dt>Id</dt><dd>{{id}}</dd> | 
			
		||||
 | 
				            <dt>Email</dt><dd>{{email}}</dd> | 
			
		||||
 | 
				            <dt>Spotify URI</dt><dd><a href="{{external_urls.spotify}}">{{external_urls.spotify}}</a></dd> | 
			
		||||
 | 
				            <dt>Link</dt><dd><a href="{{href}}">{{href}}</a></dd> | 
			
		||||
 | 
				            <dt>Profile Image</dt><dd class="clearfix"><a href="{{images.0.url}}">{{images.0.url}}</a></dd> | 
			
		||||
 | 
				            <dt>Country</dt><dd>{{country}}</dd> | 
			
		||||
 | 
				          </dl> | 
			
		||||
 | 
				        </div> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				    </script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    <script id="oauth-template" type="text/x-handlebars-template"> | 
			
		||||
 | 
				      <h2>oAuth info</h2> | 
			
		||||
 | 
				      <dl class="dl-horizontal"> | 
			
		||||
 | 
				        <dt>Access token</dt><dd class="text-overflow">{{access_token}}</dd> | 
			
		||||
 | 
				        <dt>Refresh token</dt><dd class="text-overflow">{{refresh_token}}</dd> | 
			
		||||
 | 
				      </dl> | 
			
		||||
 | 
				    </script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    <script src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/2.0.0-alpha.1/handlebars.min.js"></script> | 
			
		||||
 | 
				    <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> | 
			
		||||
 | 
				    <script> | 
			
		||||
 | 
				      (function() { | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * Obtains parameters from the hash of the URL | 
			
		||||
 | 
				         * @return Object | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        function getHashParams() { | 
			
		||||
 | 
				          var hashParams = {}; | 
			
		||||
 | 
				          var e, r = /([^&;=]+)=?([^&;]*)/g, | 
			
		||||
 | 
				              q = window.location.hash.substring(1); | 
			
		||||
 | 
				          while ( e = r.exec(q)) { | 
			
		||||
 | 
				             hashParams[e[1]] = decodeURIComponent(e[2]); | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				          return hashParams; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        var userProfileSource = document.getElementById('user-profile-template').innerHTML, | 
			
		||||
 | 
				            userProfileTemplate = Handlebars.compile(userProfileSource), | 
			
		||||
 | 
				            userProfilePlaceholder = document.getElementById('user-profile'); | 
			
		||||
 | 
				        var oauthSource = document.getElementById('oauth-template').innerHTML, | 
			
		||||
 | 
				            oauthTemplate = Handlebars.compile(oauthSource), | 
			
		||||
 | 
				            oauthPlaceholder = document.getElementById('oauth'); | 
			
		||||
 | 
				        var params = getHashParams(); | 
			
		||||
 | 
				        var access_token = params.access_token, | 
			
		||||
 | 
				            refresh_token = params.refresh_token, | 
			
		||||
 | 
				            error = params.error; | 
			
		||||
 | 
				        if (error) { | 
			
		||||
 | 
				          alert('There was an error during the authentication'); | 
			
		||||
 | 
				        } else { | 
			
		||||
 | 
				          if (access_token) { | 
			
		||||
 | 
				            // render oauth info | 
			
		||||
 | 
				            oauthPlaceholder.innerHTML = oauthTemplate({ | 
			
		||||
 | 
				              access_token: access_token, | 
			
		||||
 | 
				              refresh_token: refresh_token | 
			
		||||
 | 
				            }); | 
			
		||||
 | 
				            $.ajax({ | 
			
		||||
 | 
				                url: 'https://api.spotify.com/v1/me', | 
			
		||||
 | 
				                headers: { | 
			
		||||
 | 
				                  'Authorization': 'Bearer ' + access_token | 
			
		||||
 | 
				                }, | 
			
		||||
 | 
				                success: function(response) { | 
			
		||||
 | 
				                  userProfilePlaceholder.innerHTML = userProfileTemplate(response); | 
			
		||||
 | 
				                  $('#login').hide(); | 
			
		||||
 | 
				                  $('#loggedin').show(); | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				            }); | 
			
		||||
 | 
				          } else { | 
			
		||||
 | 
				              // render initial screen | 
			
		||||
 | 
				              $('#login').show(); | 
			
		||||
 | 
				              $('#loggedin').hide(); | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				          document.getElementById('obtain-new-token').addEventListener('click', function() { | 
			
		||||
 | 
				            $.ajax({ | 
			
		||||
 | 
				              url: '/refresh_token', | 
			
		||||
 | 
				              data: { | 
			
		||||
 | 
				                'refresh_token': refresh_token | 
			
		||||
 | 
				              } | 
			
		||||
 | 
				            }).done(function(data) { | 
			
		||||
 | 
				              access_token = data.access_token; | 
			
		||||
 | 
				              oauthPlaceholder.innerHTML = oauthTemplate({ | 
			
		||||
 | 
				                access_token: access_token, | 
			
		||||
 | 
				                refresh_token: refresh_token | 
			
		||||
 | 
				              }); | 
			
		||||
 | 
				            }); | 
			
		||||
 | 
				          }, false); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				      })(); | 
			
		||||
 | 
				    </script> | 
			
		||||
 | 
				  </body> | 
			
		||||
 | 
				</html> | 
			
		||||
@ -1,6 +1,52 @@ | 
			
		|||||
from django.shortcuts import render | 
				 | 
			
		||||
 | 
				from django.shortcuts import render, redirect | 
			
		||||
from django.http import HttpResponse | 
				from django.http import HttpResponse | 
			
		||||
 | 
				import math | 
			
		||||
 | 
				import random | 
			
		||||
 | 
				import requests | 
			
		||||
 | 
				import os | 
			
		||||
 | 
				import urllib | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				def generate_random_string(length): | 
			
		||||
 | 
				    """Generates a random string of a certain length | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    Args: | 
			
		||||
 | 
				        length: the desired length of the randomized string | 
			
		||||
 | 
				     | 
			
		||||
 | 
				    Returns: | 
			
		||||
 | 
				        A random string | 
			
		||||
 | 
				    """ | 
			
		||||
 | 
				    rand_str = "" | 
			
		||||
 | 
				    possible_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    for _ in range(length): | 
			
		||||
 | 
				        rand_str += possible_chars[random.randint(0, len(possible_chars) - 1)] | 
			
		||||
 | 
				     | 
			
		||||
 | 
				    return rand_str | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				
 | 
			
		||||
# Create your views here. | 
				# Create your views here. | 
			
		||||
def index(request): | 
				def index(request): | 
			
		||||
    return HttpResponse("You're at the index") | 
				 | 
			
		||||
 | 
				    return render(request, 'spotifyvis/index.html') | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				def login(request): | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    state_str = generate_random_string(16) | 
			
		||||
 | 
				    # use a randomly generated state string to prevent cross-site request forgery attacks | 
			
		||||
 | 
				    request.session['state_string'] = state_str  | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    payload = { | 
			
		||||
 | 
				        'client_id': os.environ['SPOTIFY_CLIENT_ID'], | 
			
		||||
 | 
				        'response_type': 'code', | 
			
		||||
 | 
				        'redirect_uri': 'http://localhost:8000/callback', | 
			
		||||
 | 
				        'state': state_str, | 
			
		||||
 | 
				        'scope': 'user-library-read', | 
			
		||||
 | 
				        'show_dialog': False | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    params = urllib.parse.urlencode(payload) # turn the payload dict into a query string | 
			
		||||
 | 
				    authorize_url = "https://accounts.spotify.com/authorize/?{}".format(params) | 
			
		||||
 | 
				    return redirect(authorize_url) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				def callback(request): | 
			
		||||
 | 
				    return HttpResponse("At callback") | 
			
		||||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue