@@ -60,23 +60,42 @@ def user_login(self, email=None, password=None):
6060 :type password: str
6161 :param password: The password used for authentication
6262 """
63+
64+ # Need to get the CSRF token first
65+ response = self .session .get ('https://piazza.com/main/csrf_token' )
66+
67+ # Make sure a CSRF token was retrieved, otherwise bail
68+ if response .text .upper ().find ('CSRF_TOKEN' ) == - 1 :
69+ raise AuthenticationError ("Could not get CSRF token" )
70+
71+ # Remove double quotes and semicolon (ASCI 34 & 59) from response string.
72+ # Then split the string on "=" to parse out the actual CSRF token
73+ csrf_token = response .text .translate ({34 : None , 59 : None }).split ("=" )[1 ]
74+
6375 email = six .moves .input ("Email: " ) if email is None else email
6476 password = getpass .getpass () if password is None else password
6577
66- login_data = {
67- "method" : "user.login" ,
68- "params" : {"email" : email ,
69- "pass" : password }
70- }
71- # If the user/password match, the server respond will contain a
72- # session cookie that you can use to authenticate future requests.
73- r = self .session .post (
74- self .base_api_urls ["logic" ],
75- data = json .dumps (login_data ),
78+ # Log in using credentials and CSRF token and store cookie in session
79+ response = self .session .post (
80+ 'https://piazza.com/class' ,
81+ data = f'from=%2Fsignup&email={ email } &password={ password } &remember=on&csrf_token={ csrf_token } '
7682 )
77- if r .json ()["result" ] not in ["OK" ]:
78- raise AuthenticationError ("Could not authenticate.\n {}"
79- .format (r .json ()))
83+
84+ # If non-successful http response, bail
85+ if response .status_code != 200 :
86+ raise AuthenticationError (f"Could not authenticate.\n { response .text } " )
87+
88+ # Piazza might give a successful http response even if there is some other
89+ # kind of authentication problem. Need to parse the response html for error message
90+ pos = response .text .upper ().find ('VAR ERROR_MSG' )
91+ errorMsg = None
92+ if pos != - 1 :
93+ end = response .text [pos :].find (';' )
94+ errorMsg = response .text [pos :pos + end ].translate ({34 : None }).split ('=' )[1 ].strip ()
95+
96+ if errorMsg is not None :
97+ raise AuthenticationError (f"Could not authenticate.\n { errorMsg } " )
98+
8099
81100 def demo_login (self , auth = None , url = None ):
82101 """Authenticate with a "Share Your Class" URL using a demo user.
0 commit comments