jessecooper / pyetrade

Python E-Trade API Wrapper
GNU General Public License v3.0
209 stars 97 forks source link

HTTPError: 401 Client Error: Unauthorized for url #72

Closed nathanramoscfa closed 1 year ago

nathanramoscfa commented 1 year ago

I was able to write an automatic login script as was suggested in question #71. However this time, I am having trouble using pyetrade with the session object. pyetrade is giving me HTTPError: 401 Client Error: Unauthorized for url: https://api.etrade.com/v1/accounts/list but my direct code to E-Trade API does work and gives me the accounts list as requested. From what I see, it appears to successfully log in to my E-Trade account with no problems. The generated request_token and request_token_secret appear to be correct, and change each time I run the script as I believe it should. However, when I test the session object by trying to get an account list with pyetrade:

# pyetrade
accounts = pyetrade.ETradeAccounts(
    consumer_key,
    consumer_secret,
    request_token, 
    request_token_secret,
    dev
)

# lists all the accounts for
print(accounts.list_accounts(resp_format='xml'))  <------BREAKS RIGHT HERE

I am getting HTTPError: 401 Client Error: Unauthorized for url: https://api.etrade.com/v1/accounts/list. But when I run a script directly (without using pyetrade) to E-Trade API, it works:

# E-Trade API
url = 'https://api.etrade.com/v1/accounts/list'
response = session.get(url, params={'format': 'json'})
if response is not None and response.status_code == 200:
    print('Status Code: {}'.format(session.get(url, params={'format': 'json'}).status_code))
    accounts_list = xmltodict.parse(response.text)

Here is my automated login script which appears to work, otherwise, how could I query the E-Trade API like in the code above (status code: 200 successful connection to server). I suspect then that the problem may be with how I am using pyetrade.

"""Allows user authorization for the sample application with OAuth 1"""
etrade = OAuth1Service(
    name="etrade",
    consumer_key=config["DEFAULT"]["CONSUMER_KEY"],
    consumer_secret=config["DEFAULT"]["CONSUMER_SECRET"],
    request_token_url="https://api.etrade.com/oauth/request_token",
    access_token_url="https://api.etrade.com/oauth/access_token",
    authorize_url="https://us.etrade.com/e/t/etws/authorize?key={}&token={}",
    base_url="https://api.etrade.com"
)

 # Step 1: Get OAuth 1 request token and secret
request_token, request_token_secret = etrade.get_request_token(
    params={"oauth_callback": "oob", "format": "json"})

# Step 2: Go through the authentication flow. Login to E-TRADE.
# After you login, the page will provide a text code to enter.
authorize_url = etrade.authorize_url.format(etrade.consumer_key, request_token)

#############################################
# Automate the login process
service = Service(executable_path="msedgedriver.exe")
driver = webdriver.Edge(service = service)
driver.get(authorize_url)

swhcookie = {cookie given to me from E-Trade API Help Desk}
driver.add_cookie(swhcookie)

user_id = driver.find_element(By.NAME, 'USER')
user_id.send_keys(web_username)

password = driver.find_element(By.NAME, 'PASSWORD')
password.send_keys(web_password)

logon = driver.find_element(By.ID, 'logon_button')
logon.click()

driver.implicitly_wait(5)

accept = driver.find_element(By.NAME, "submit")
accept.click()

code = driver.find_element(By.XPATH, "//div[@style='text-align:center']/input[1]")
code = code.get_attribute('value')

driver.close()

text_code = code

# Step 3: Exchange the authorized request token for an authenticated OAuth 1 session
session = etrade.get_auth_session(
    request_token, 
    request_token_secret, 
    params={"oauth_verifier": text_code}
)
nathanramoscfa commented 1 year ago

The problem was incorrect consumer key and secret. Correcting this fixed the issue.