Flask Test Post is not sending correct data - python

I'm in the process of writing a test for the login portion of an app I'm creating in Flask. However, when I pass data using the test_client.post() method my test data isn't being passed correctly.
What's more, the manual login test POSTs and redirects fine.
The test case code is:
# Ensure Login behaves correctly given the correct credentials
def test_correct_login(self):
tester = app.test_client(self)
response = tester.post('/login',data= dict(username = 'bigtest', password = 'testing2'), follow_redirects = True, content_type='application/x-www-form-urlencoded')
self.assertIn(b'Section title', response.data)
The response given shows that the username is passed correct, but the password does not have a value.
This is the response returned in console:
<div class="form-group required">
<label class="control-label" for="username">username</label>
<input class="form-control" id="username" name="username" required type="text" value="bigtest">
</div>
<div class="form-group required">
<label class="control-label" for="password">password</label>
<input class="form-control" id="password" name="password" required type="password" value="">
I'm not sure what the issue is here. Has this happened to anyone else before?

Related

Upload file in flask with other form elements fails with 400 error

Getting a 400, when trying to upload a file ad send other form elements to flask from html. Tried to use ajax, but that throws me an error as well.
Python:
#app.route('/prod_diff_result', methods=['POST', 'GET'])
def prod_diff_result():
try:
host = request.form['host-prod-iterator']
print(host)
if request.files['file']:
f = request.files['file']
f.save(secure_filename(f.filename))
HTML:
<div class="main-div">
<form action="/prod_diff_result" method="POST" enctype="multipart/form-data">
<div class="grid-container">
<div class="grid-item">
<span class="label label-default ">PROD</span><br>
<p>Iterator Host : <input type="text" class="form-control" id="host-prod-iterator" value="10.47.7.57"
required></p>
<input type="radio" name="data_fetch_type" value="file" onclick="showfile()">Upload File
<input type="file" name="file" />
<input type="radio" name="data_fetch_type" value="db"> Get from DB
<input type="submit" />
</div>
</form>
</div>
I want to be able send hostname and file back to flask error in one request and using one form.
It gives an error because you try to access a form field that it cannot find, and assumes that somehow the request was bad, because it didn't include a required form field. You are trying to access:
host = request.form['host-prod-iterator']
However you have simply not given it a name in your HTML. If you give it a name, it should work:
<p>Iterator Host :
<input type="text" class="form-control" name="host-prod-iterator" id="host-prod-iterator" value="10.47.7.57" required>
</p>

How to transmit form-data without POST with python requests?

I'm writing a little piece of python code to login on several "Investing"-Websites of mine and get out the current amount of money invested. I'm using pythons requests library and analyze the html-source to identify the form and the fields to fill in.
So, a form may look like this:
<form class="onboarding-form" id="loginForm" action="https://estateguru.co/portal/login/authenticate" method="post" data-redirect="https://estateguru.co/portal/home">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<input type="text" class="form-control main-input" name="username">
<label class="bmd-label-floating main-label">E-Mail</label>
<em id="username-error" class="error bmd-help help-block" style="display:none;">This field is required.</em>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<input type="password" class="form-control main-input login-pass" name="password">
<label class="bmd-label-floating main-label long-label">Passwort (Mindestens 8 Zeichen)</label>
<em id="password-error" class="error bmd-help help-block" style="display:none;">This field is required.</em>
<i class="zmdi zmdi-eye"></i>
</div>
</div>
</div>
In this case, my code looks like this:
import requests
_username = 'xxx'
_password = 'yyy'
loginUrl = 'https://estateguru.co/portal/login/authenticate'
readUrl = 'https://estateguru.co/portal/portfolio/overview'
with requests.session() as s:
payload = {"username": _username, "password": _password}
final = s.post(loginUrl, data = payload)
result = s.get(readUrl)
print(result)
This works like a charm for many websites! But now i got an website without the "method=post" in the form, so i don't know hot to transmit the form-data.
The html-part (from http://www.reinvest24.com/en/login) looks like this:
<form>
<div class="form-group">
<input type="text" id="email" placeholder="Email" value="" name="email" maxLength="100" class="form-control"/>
</div>
<div class="form-group">
<input type="password" id="password" placeholder="Password" value="" name="password" maxLength="100" class="form-control"/>
</div>
<p class="forgot text-right">
<span>Forgot password?</span>
</p>
<input type="submit" class="btn btn-success" value="Login"/>
<p class="reg text-center">
<span>Don't have an account?</span>
<a href="/en/registration">
<span>Sign up</span></a>
</p>
</form>
So without the method clarified, I tried
final = s.get(loginUrl, data = payload)
but without success. The result in both cases is a html-output saying something about "Loading authorization details...".
So my question is: Am i missing the right method (POST/GET) to transmit data or am i missing some other parameter? Some websites require a session-token, which I retrieve from the login-site itself (like it's the case in https://www.mintos.com/de/login), but in my opinion, this is not the problem here.
By default, the body (form data) of a HTTP request is ignored when the method is set to GET. Therefore you shouldn't try to submit the request via GET (not only is it not safe to transmit sensitive info over GET, the server would just ignore the username/password of your request).
The issue here is that the page is doing some JavaScript magic to submit your request over a different URL. Open up your web inspector and watch the "network" tab whenever you try to login on that website. You should see that the request is being POSTed to https://api-frontend.reinvest24.com/graphql.
When we inspect this POST request, we can see that the data is being transmitted as a JSON body, not a form body. So your request should look something along the lines of this:
login_url = 'https://api-frontend.reinvest24.com/graphql'
payload = {
"operationName": "login",
"variables": {
"email": EMAIL,
"password": PASSWORD
},
"query": "mutation login($email: String!, $password: String!) {\n login(email: $email, password: $password)\n}\n"
}
r = s.post(url=login_url, json=payload)
# note that we used the 'json' parameter here not 'data'
Chrome web inspector is your friend here to observe how data is transmitted when logging in.
Good luck!

Python - Login to Website

I know that there are several posts on this subject and I believe I have read a significant amount of them, however I still can't login to this website.
Below is my inspection of the login page:
<form id="login" name="login" method="POST" action="/signin">
<div id="login_username">
<label>Email</label>
<input class="textfield" id="email" name="email" type="text" autocomplete="off" value="">
</div>
<div id="login_password">
<label>Password</label>
<input class="textfield" id="password" name="password"
type="password" autocomplete="off" value="">
</div>
<input type="hidden" id="hash" name="hash" value="">
<div id="login_submit">
<a id="forgot_password_link">Forgot Password?</a>
<input class="submitbutton" type="submit" value="Sign In">
</div>
</form>
Below is my code:
username = 'XXXXX#gmail.com'
password = 'XXXX'
hash = ''
data = {'password':password, 'email':username,'hash':hash}
login_url = "https://carmel.orangetheoryfitness.com/login"
s = requests.session()
result = s.post(login_url, data=data, headers = dict(referer=login_url))
scrape_url = 'https://carmel.orangetheoryfitness.com/apps/otf/classes/view?id=16297&loc=0'
result = s.get(url=scrape_url)
From here I go on to search the html document but I'm not finding what I want as I am sent back to the login page when getting the scrape_url. I have verified this by inspecting the resulting html document.
Things I have considered:
-Almost all blog posts or SO responses indicate that usually a CSRF token is required. I have searched the login page and can't find a CSRF token.
The form has an action="/signin" attribute so you need to post to https://carmel.orangetheoryfitness.com/signin instead.
result = s.post('https://carmel.orangetheoryfitness.com/signin', data=data, headers = dict(referer=login_url))

python requests module with redirect

I am trying to perform a get request in python using the requests module. However, before I can do a get the website redirects me to a login page. I need to login first which will then land to me to the page I am requesting.
Following is the content I receive after doing the get. How should I perform the login in order to access the page I am looking for? Any help would be appreciated!
<form action="/idp/profile/SAML2/Redirect/SSO?execution=e1s1" method="post">
<div class="form-element-wrapper">
<label for="username">Username</label>
<input class="form-element form-field" id="username" name="j_username" type="text" value="">
</div>
<div class="form-element-wrapper">
<label for="password">Password</label>
<input class="form-element form-field" id="password" name="j_password" type="password" value="******">
</div>
<div class="form-element-wrapper">
<input type="checkbox" name="donotcache" value="1">Don't Remember Login </div>
<div class="form-element-wrapper">
<input id="_shib_idp_revokeConsent" type="checkbox" name="_shib_idp_revokeConsent" value="true">
Clear prior granting of permission for release of your information to this service.
</div>
<div class="form-element-wrapper">
<button class="form-element form-button" type="submit" name="_eventId_proceed"
onClick="this.childNodes[0].nodeValue='Logging in, please wait...'">Login</button>
</div>
</form>
Following is the code I have written until now:
values = {'j_username':'****'}
with requests.Session() as s:
p = s.get(url,verify=False)
logger.info(p.text)
values = {'j_username':'****'}
with requests.Session() as session:
login_response = session.post(login_url, data=data, verify=False)
# the session will now have the session cookie, so subsequent requests will be authenticated. its worth inspecting the response to make sure it is the correct status code.
other_response = session.get(url) # expect this not to redirect to login page

How can I pass my login details to a web page?

<div class="group group-form group-form-requiredinformation">
<h2 class="sr">Required Information</h2>
<ol class="list-input">
<li class="field required text" id="field-email">
<label for="email">E-mail</label>
<input class="" id="email" type="email" name="email" value="" placeholder="example: username#domain.com" required aria-required="true" aria-described-by="email-tip" />
<span class="tip tip-input" id="email-tip">This is the e-mail address you used to register with edX</span>
</li>
<li class="field required password" id="field-password">
<label for="password">Password</label>
<input id="password" type="password" name="password" value="" required aria-required="true" />
<span class="tip tip-input">
I am trying to write some code that will parse a webpage and check for updated content periodically, my problem is that I need to be logged in but I am unsure how to pass in my login details, the above is some of the source of the login page, how is it possible to achieve this?
I have tried something like the code below but to no avail.
browser = mechanize.Browser()
browser.open("https:xxxx")
browser.select_form(nr = 0)
browser.form['username'] = "email"
browser.form['password'] = "xxxxx"
browser.submit()
At least, the field is called email, not username:
browser.form['email'] = "email"
browser.form['password'] = "xxxxx"
browser.submit()
store the last updated date time in a variable and have a javascript timer function to invoke a function to check the last updated date time and if the content was updated more than the predefined time, make a call to backend and update the info on the page.
FYI.. there is no browser object. there is document object which has properties and methods to manipulate the page

Categories

Resources