Search code examples
pythonhttppython-requestsresponse

How to get post request auth_token from zyBook's response?


I am trying to log into zyBooks using the Requests library in Python. I saw in the Network tab of google chrome that I need an auth_token to be able to add to the URL to actually create and do the login request. Firstly, here is the Network tab snapshot after I log into the website:

Network snapshot

So first, I need to do the 1st POST request that is named 'signin' (the 2nd one, 1st OPTIONS request doesn't seem to do anything or respond with anything). The signin POST request is supposed to respond with an auth_token, which then I can use to login using the 3rd name in the list, which is the first GET request.

The response of the first POST request is the auth_token:

auth_token response

And here is the detail about the first POST request. You can see the request URL and the payload required: payload and request URL

As proof, here is what request URL would look like. As you can see, it needs the auth_token. enter image description here

I am however, unable to get the first POST request's auth_token in anyway that I have tried so far. Both request URL for the first 2 'signin' are what is in the code. Here is the code:

import requests
url = 'https://learn.zybooks.com/signin'
payload = {"email":"myemail","password":"mypassword"}

 headers = {
        'Host': 'zyserver.zybooks.com',
        'Connection': 'keep-alive',
        'Content-Length': '52',
        'Pragma': 'no-cache',
        'Cache-Control': 'no-cache',
        'sec-ch-ua': "Chromium;v=88, Google Chrome;v=88, ;Not A Brand;v=99",
        'Accept': 'application/json, text/javascript, */*; q=0.01',
        'DNT': '1',
        'sec-ch-ua-mobile': '?0',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like 
         Gecko) Chrome/88.0.4324.150 Safari/537.36',
        'Content-Type': 'application/json',
        'Origin': 'https://learn.zybooks.com',
        'Sec-Fetch-Site': 'same-site',
        'Sec-Fetch-Mode': 'cors',
        'Sec-Fetch-Dest': 'empty',
        'Referer': 'https://learn.zybooks.com/',
        'Accept-Encoding': 'gzip, deflate, br',
        'Accept-Language': 'en-US,en;q=0.9',
        }

session = requests.Session()
req1 = session.post(url)
req2 = session.post(url, data=payload)

print(req2.json())

I just get the JSONDecoreError:

    353             obj, end = self.scan_once(s, idx)
    354         except StopIteration as err:
   --> 355             raise JSONDecodeError("Expecting value", s, err.value) from None
    356         return obj, end

    JSONDecodeError: Expecting value: line 1 column 1 (char 0)

From what I have researched in many posts online, this error happens because the response doesn't contain any JSON. But that doesn't make any sense as I need that JSON response with the auth_token to be able to create the GET request to login to the site.


Solution

  • Got it. It's because zyBooks runs on Ember.js. There is no html (barely), it's a javascript website. The javascript needs to be loaded first, then the form can be filled and submitted.

    I did not go through with implementing it myself, but for future people coming here, there are posts on this subject, such as:

    using requests to login to a website that has javascript login form