def _get_authorization_token(self, cache_token=True) -> str: """ Step 2 """ logger.info('Get authorization token') code_verifier, code_challenge = self._generate_consts() data = { 'client_id': self.client_id, 'grant_type': 'authorization_code', 'code': self._get_authorization_code(code_challenge), 'redirect_uri': self.redirect_uri, 'code_verifier': code_verifier } resp = self._session.post(url=self.AUTH_TOKEN_URL, data=data) if resp.status_code != 200: result = resp.json() logger.error('Getting responce token error') raise AuthFlowRequestError(error=result['error'], error_descr=result['error_description'], code=resp.status_code) self.token_info = resp.json() self.token_info['expires_at'] = int( time.time()) + self.token_info["expires_in"] if cache_token: self._cache_token()
def _refresh_authorization_token(self, cache_token=True) -> None: """ Requesting a refreshed access token; Spotify returns a new access token to your app """ logger.info('Refresh expired token') headers = self._make_authorization_headers(self._client_id, self._client_secret) data = { 'grant_type': 'refresh_token', 'refresh_token': self.token_info['refresh_token'], 'redirect_uri': self.redirect_uri } resp = self._session.post(url=self.AUTH_TOKEN_URL, headers=headers, data=data) if resp.status_code != 200: result = resp.json() logger.error('Getting responce token error') raise AuthFlowRequestError(error=result['error'], error_descr=result['error_description'], code=resp.status_code) logger.debug(resp.text) self.token_info = resp.json() self.token_info['expires_at'] = int( time.time()) + self.token_info["expires_in"] if cache_token: self._cache_token()
def _get_cached_token(self) -> None: token_info = None try: with open(self.cache_token_path, 'r') as f: token_info = json.load(f) logger.info('Got cached token') except (IOError, json.decoder.JSONDecodeError) as e: logger.warning( f'Can not get token from {self.cache_token_path}: {e}') # self.token_info = token_info return token_info
def _get_authorization_token(self, cache_token=True) -> None: """ Step 2. Exchange code with an access token POST https://accounts.spotify.com/api/token The body must contain the following parameters encoded in application/x-www-form-urlencoded as defined in the OAuth 2.0 specification: POST data: grant_type=authorization_code, code, redirect_uri Headers: Base 64 encoded string that contains the client ID and client secret key. The field must have the format: "Authorization: Basic *<base64 encoded client_id:client_secret>*" Return: - access_token - token_type=“Bearer” - scope -- space-separated list of scopes which have been granted for this access_token - expires_in -- The time period (in seconds) for which the access token is valid - refresh_token -- a token that can be sent to the Spotify Accounts service in place of an authorization code. When the access code expires, send a POST request to the Accounts service /api/token endpoint, but use this code in place of an authorization code. A new access token will be returned. A new refresh token might be returned too.) """ logger.info('Get authorization token') headers = self._make_authorization_headers(self._client_id, self._client_secret) data = { 'grant_type': 'authorization_code', 'code': self._get_authorization_code(), 'redirect_uri': self.redirect_uri } resp = self._session.post(url=self.AUTH_TOKEN_URL, headers=headers, data=data) if resp.status_code != 200: result = resp.json() logger.error('Getting responce token error') raise AuthFlowRequestError(error=result['error'], error_descr=result['error_description'], code=resp.status_code) self.token_info = resp.json( ) # {'access_token': 'BQ...', 'token_type': 'Bearer', 'expires_in': 3600, 'refresh_token': 'AQ...', 'scope': '...'} self.token_info['expires_at'] = int( time.time()) + self.token_info["expires_in"] if cache_token: self._cache_token()
def get_token(self) -> str: logger.info('Authorizing with Authorization Code Flow') self.token_info = self._get_cached_token() if self.token_info: logger.debug(f'Cached token: {str(self.token_info)[:25]}...') if Scope(self.token_info['scope']) == self.scope: if self._is_token_expired(): logger.debug( f'Token expired at {time.ctime(int(self.token_info["expires_at"]))}. Refreshing token...' ) try: self._refresh_authorization_token() except AuthFlowRequestError as err: if err.code == 400: logger.debug(err) logger.debug( 'Cleaning cache, trying to get another token') self._clean_cache() self._get_authorization_token() else: logger.info('Scopes are not compatible. Getting new token...') self._get_authorization_token() else: self._get_authorization_token() logger.info( f'Authorization complite. Token "{self.token_info["access_token"][:7]}..." will be expire at {time.ctime(int(self.token_info["expires_at"]))}' ) return self.token_info['access_token']