this is something that has been bothering me for a while. I want to write a program so that I may automatically log into my PowerSchool portal, which will in the future potentially let me do things such as parse my schedule and grades. The first step to that is authenticating, which has become a problem for me.
import sys
import os
import requests
import lxml
import json
from bs4 import BeautifulSoup
def login(username, password):
with requests.Session() as s:
url = 'https://sisavrsb.ednet.ns.ca/guardian/home.html#sign-in-content'
r = s.get(url)
soup = BeautifulSoup(r.text, "lxml")
token = soup.select_one("[name='pstoken']")['value']
contextdata = soup.select_one("[name='contextData']")['value']
headers = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'en-US,en;q=0.5',
'Connection': 'keep-alive',
#'Content-Length': '423',
#'Content-Type': 'application/x-www-form-urlencoded',
#'Cookie': 'JSESSIONID=0B1666C446234245CECC2983F1D6CA8A; PowerSchool_Cookie_K=2069644430.1.329063952.2221457792',
'DNT': '1',
#'Host': 'sisavrsb.ednet.ns.ca',
'Referer': 'https://sisavrsb.ednet.ns.ca/public/',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:59.0) Gecko/20100101 Firefox/59.0'
}
print(contextdata)
data = json.dumps({
'account': username,
#'contextData': '30A7205567365DDB643E707E25B32D43578D70A04D9F407113CF640632082056',
'contextData' : contextdata,
'credentialType': 'User Id and Password Credential',
#'dbpw': '61a2474517a2f79ae0da0781b9bdf57d',
#'dbpw' : password,
'pcasServerUrl': '\/',
'pstoken': token,
'pw': password,
'returnUrl': '',
'serviceName': 'PS Parent Portal',
'serviceTicket': '',
'translator_ldappassword': '',
'translator_password': '',
'translator_username': '',
'translatorpw': ''
})
p = s.post(url, headers=headers, data=data, allow_redirects=True)
soup = BeautifulSoup(p.text, "lxml")
if p.status_code == 302:
print('Success!')
else:
print('Authentication error', p.status_code)
print('cookies', requests.utils.dict_from_cookiejar(s.cookies))
print(p.history)
print(p.headers)
def main():
login('xxxxx', 'xxxxx')
if __name__ == '__main__':
main()
At this point I've tried almost everything from Mechanize to (outdated) PowerSchool API. I've tried my best to replicate the headers and data, using requests.Session()
so that the cookies work properly. After hours of fiddling with it, I finally got it so that p.history() is not blank. It now contains "<Response [302]>
", which is extremely vague to me but better than nothing.
Here's my output
Authentication error 200
cookies {'JSESSIONID': 'B847F853CC373DC7EAA8800FA02EEC00', 'PowerSchool_Cookie_K': '2069644430.1.329063608.2225303936'}
[<Response [302]>]
{'Server': 'Apache-Coyote/1.1', 'Cache-control': 'no-store, no-cache, must-revalidate, post-check=0, check=0', 'Expires': 'Thu, 01 Dec 1994 16:00:00 GMT', 'Content-Type': 'text/html;charset=UTF-8', 'Content-Length': '8238', 'Date': 'Thu, 08 Feb 2018 01:01:05 GMT'}
I've left the website link so that you may test with POST requests and look at the headers and such. I'm out of ideas for how to resolve this, but I would really like to get this working. Obviously 302 is in the history which is a good sign for a POST code, but I still can't get past the login. If I did another requests.get()
and printed the output it would be the login page again.
Mechanize (throws 500 internal server error):
import mechanize
import cookielib
br = mechanize.Browser()
cj = cookielib.LWPCookieJar()
br.set_cookiejar(cj)
br.set_handle_equiv(True)
br.set_handle_gzip(True)
br.set_handle_redirect(True)
br.set_handle_referer(True)
br.set_handle_robots(False)
br.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1)
# Debugging
br.set_debug_http(True)
br.set_debug_redirects(True)
br.set_debug_responses(True)
br.set_handle_refresh(False)
# Fake User-Agent header
br.addheaders = [('User-Agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36')]
br.open('https://sisavrsb.ednet.ns.ca/public/home.html')
#
br.select_form(name='LoginForm')
br.form['account'] = 'xxxxx'
br.form['pw'] = 'xxxxxx'
br.method = 'POST'
response = br.submit()
print response.read()
EDIT: RoboBrowser gives me a 500 response too. Wondering if it's because of something I'm missing or simply a problem on their end.