Example #1
0
    def auth_via_browser(self):
        """
        Handles authentication and authorization.

        Raises
        ------
        AuthorizationError
            If the authentication or authorization could not be completed
        """
        self._start_auth_server()
        self._open_browser(self.callback_url)
        logger.debug("Waiting for authorization code...")
        tokens = self.auth_server._wait_for_tokens()
        self._stop_auth_server()

        try:
            refresh_token = tokens["refresh_token"]
            refresh_expiry = tokens["refresh_token_expires_in"]
            access_token = tokens["access_token"]
            access_expiry = tokens["expires_in"]
            access_time = tokens["access_time"]
        except KeyError:
            logger.error("Authorization could not be completed.")
            raise AuthorizationError("Authorization could not be completed.")
        r = RefreshToken(token=refresh_token,
                         access_time=access_time,
                         expires_in=refresh_expiry)
        a = AccessToken(token=access_token,
                        access_time=access_time,
                        expires_in=access_expiry)
        logger.debug("Refresh and Access tokens received.")
        return (
            r,
            a,
        )
Example #2
0
def refresh_auth():
    global __api__
    if __api__ is None:
        raise AuthorizationError("Default API not found.")
    else:
        __api__.refresh_auth()
        return
Example #3
0
 def _wait_for_tokens(self):
     count = 0
     while count <= self.retry_count and self.tokens is None:
         self.handle_request()
     if self.tokens:
         return self.tokens
     else:
         raise AuthorizationError("The authorization could not be "
                                  "completed.")
Example #4
0
 def _authenticate_wrapper(self, *args, **kwargs):
     if self.api.auth_valid is True:
         return func(self, *args, **kwargs)
     else:
         if self.api.refresh_valid is False:
             logger.warning("Need new refresh token.")
             choice = yn_require("Would you like to authorize a new "
                                 "refresh token?")
             if choice is True:
                 self.api.refresh_auth()
             else:
                 raise AuthorizationError("Refresh token "
                                          "needed for access.")
         else:
             self.api.auth.refresh_access_token()
     if self.api.auth_valid is True:
         return func(self, *args, **kwargs)
     else:
         raise AuthorizationError("Authorization could not be "
                                  "completed.")
Example #5
0
    def refresh_access_token(self):
        """
        Attempts to refresh access token if current is not valid.

        Updates the cache if new token is received.

        Raises
        ------
        AuthorizationError
            If the access token is not successfully refreshed
        """
        if self.cache.refresh_token.valid is False:
            raise AuthorizationError("Refresh token is not valid.")
        logger.debug("Attempting to refresh access token...")
        headers = {'Content-Type': 'application/x-www-form-urlencoded'}
        data = {
            'grant_type': 'refresh_token',
            'refresh_token': self.cache.refresh_token.token,
            'client_id': self.consumer_key
        }
        try:
            authReply = requests.post(
                'https://api.tdameritrade.com/v1/oauth2/'
                'token',
                headers=headers,
                data=data)
            now = to_timestamp(datetime.datetime.now())
            if authReply.status_code == 400:
                raise AuthorizationError("Could not refresh access token.")
            authReply.raise_for_status()
            json_data = authReply.json()
            token = json_data["access_token"]
            expires_in = json_data["expires_in"]
        except (KeyError, ValueError):
            logger.error("Error retrieving access token.")
            raise AuthorizationError("Error retrieving access token.")
        access_token = AccessToken(token=token,
                                   access_time=now,
                                   expires_in=expires_in)
        logger.debug("Successfully refreshed access token.")
        self.cache.access_token = access_token
Example #6
0
 def _check_status_codes(self, response):
     status = response.status_code
     logger.debug("RESPONSE TEXT (1st 200 chars): %s" % response.text[:200])
     if status in [301, 302, 303, 307]:
         message = "There was an unexpected redirect during your request."
         raise Redirection(response, message=message)
     elif status == 400:
         message = "There was a validation problem with your request."
         raise ValidationError(response, message=message)
     elif status == 401:
         message = "Auth Token invalid."
         raise AuthorizationError(message)
     elif status == 403:
         message = "You are forbidden from accessing this resource."
         raise ForbiddenAccess(response, message=message)
     elif status == 404:
         message = "The requested resource was not found."
         raise ResourceNotFound(response=response, message=message)
     elif 401 <= status <= 499:
         message = "There was a client-side error with your request."
         raise ClientError(response, message=message)
     elif 500 <= status <= 599:
         t = response.text
         t = re.sub(r"[\n\t\s]*", "", t)
         t = re.sub(r"\\", "", t)
         try:
             import json
             json_data = json.loads(t)
             if json_data["error"] == "InvalidApiKey":
                 raise AuthorizationError("Invalid OAuth ID.")
         except ValueError:
             pass
         message = "There was a server-side error with your request."
         raise ServerError(response, message=message)
     else:
         raise TDQueryError(response=response,
                            message="Unknown response code.")
Example #7
0
    def do_GET(self):
        if self.path.endswith(".css"):
            f = open("pyTD/auth/_static/style.css", 'r')
            self.send_response(200)
            self.send_header('Content-type', 'text/css')
            self.end_headers()
            self.wfile.write(f.read().encode())
            f.close()
            return

        self._set_headers()
        path, _, query_string = self.path.partition('?')
        try:
            code = parse_qs(query_string)['code'][0]
        except KeyError:
            f = codecs.open("pyTD/auth/_static/auth.html", "r", "utf-8")
            auth = f.read()
            link = auth.format(self.auth_link)
            self.wfile.write(link.encode('utf-8'))
            f.close()
        else:
            self.server.auth_code = code
            headers = {'Content-Type': 'application/x-www-form-urlencoded'}
            data = {'refresh_token': '', 'grant_type': 'authorization_code',
                    'access_type': 'offline', 'code': self.server.auth_code,
                    'client_id': self.server.consumer_key,
                    'redirect_uri': self.server.callback_url}
            now = to_timestamp(datetime.datetime.now())
            authReply = requests.post('https://api.tdameritrade.com/v1/oauth2/'
                                      'token', headers=headers, data=data)
            try:
                json_data = authReply.json()
                json_data["access_time"] = now
                self.server._store_tokens(json_data)
            except ValueError:
                msg = json.dumps(json_data)
                logger.Error("Tokens could not be obtained")
                logger.Error("RESPONSE: %s" % msg)
                raise AuthorizationError("Authorization could not be "
                                         "completed")
            success = codecs.open("pyTD/auth/_static/success.html", "r",
                                  "utf-8")

            self.wfile.write(success.read().encode())
            success.close()