Logging into an external website with flask - python

I'm currently having some trouble with my flask webapp, where I have written it as below, but when I try to run the flask app, I run into a Bad Request Error. (The browser (or proxy) sent a request that this server could not understand)
Essentially, I am trying to allow users to log in to an external website through the flask webapp
What is the cause of this error? Apologies if I am making a stupid mistake, I'm very new to flask.
from flask import Flask,render_template, request, redirect
import requests
from bs4 import BeautifulSoup as bs
app = Flask(__name__)
#app.route('/', methods = ["POST", "GET"])
def login():
username = request.form['username']
pin = request.form['password']
s = requests.Session()
r = s.get("https://www.example.com/User/Login")
soup = bs(r.text, 'html.parser')
loginToken = soup.findAll(attrs={"name" : "__RequestVerificationToken"})[0]['value']
#Create Login Payload
login_payload = {
"__RequestVerificationToken" : loginToken,
"UserName" : username,
"Password" : pin,
"returnUrl" : "https://example.com/user-action/?action=login&returnUrl=https://www.example.com/User/Information",
}
#Post Login Payload
r = s.post("https://www.example.com/Account/Login", data = login_payload)
if r.status_code == 200:
return render_template('home.html')
else:
return render_template('login.html')
return render_template('login.html')
#app.route('/home') #If login works, redirect to this page
def hello_world():
return 'Hello, World!'
if __name__ == "__main__":
app.run(debug = True)
In addition, if there are other resources that I could refer to with regards to allowing a user to log in to a external URL from the flask webapp as compared to the conventional tutorials that only show a user logging in to the flask webapp itself, do share it with me, thank you!

Your endpoint' s has two Http verbs ["POST", "GET"]. You should specify your methods as below.
#app.route('/', methods = ["POST", "GET"])
def login():
if request.method == "GET":
#something do stuff
return render_template("your_html_page")
if request.method == "POST":
#something do stuff
return your_response, 200
Edited Block
#app.route('/', methods = ["POST", "GET"])
def login():
if request.method == "GET":
return render_template('login.html')
if request.method == "POST":
#same logic here
if status_code == 200:
return redirect(url_for('home'))
return render_template('login.html')

Related

How do i send data to a flask app and then have the flask app display it [duplicate]

This question already has answers here:
Sending data from HTML form to a Python script in Flask
(2 answers)
Closed 10 months ago.
I want to send some POST data to a flask webpage then have it display that data but when I try to send the data {"hi": "hi"} it gives me these errors:
code 400, message Bad request syntax ('hi=hi')
"None / HTTP/0.9" HTTPStatus.BAD_REQUEST -
my code is this:
from flask import Flask, request
app = Flask("__name__")
#app.route("/", methods=['GET', 'POST'])
def hi():
return "hi"
if request.method == "POST":
data = request.values
return f"<p>{data}</p>"
the flask app:
and the post data sending program:
import requests
requests.post('http://127.0.0.1:5000', data={ "req": "hi" })
am I just not understanding POST requests right or am I doing something really wrong?
please see this answer regarding how to access the request's data.
the requests.post you are using as http client is sending the data as form-encoded, so we could use Flasks' request.form to access the data. Also your function needs some restructuring, else it will always return "hi", we can make it:
from flask import Flask, request
app = Flask("__name__")
#app.route("/", methods=['GET', 'POST'])
def hi():
if request.method == "GET":
return "hi"
if request.method == "POST":
# data = request.values
# data will be = req if your POST request has req field, else will be = field: req was not provided
data = request.form.get("req", "field: req was not provided")
return f"<p>{data}</p>"
if you dont know the fields the POST request will contain, you can use this loop to get the fields and their values:
#app.route("/", methods=['GET', 'POST'])
def hi():
if request.method == "GET":
return "hi"
if request.method == "POST":
# data = request.values
for field in request.form:
print(field, request.form.get(field))
return "hi"

Authentication in Flask application using dictionary database structure

I am creating a basic application to demonstrate the register and login activities in Flask using sessions. For the below code, each user available in the dictionary should be able to login. However, the application only accepts the login for the first user named 'Mary'. I don't understand where did it went wrong.
from flask import Flask, app, session, render_template, request,redirect, url_for, jsonify
app = Flask(__name__)
app.config['SECRET_KEY'] = "Zd9TUg1aE03bHc28"
#app.route('/')
def load():
return render_template("authusers.html")
class Mydatabase:
appdb=[{'username':'Mary','password':'Password#123'},
{'username':'John','password':'Password#456'},
{'username':'Tara','password':'Password#789'}]
mydbusers=Mydatabase()
#app.route('/login',methods = ['GET','POST'])
def success():
if request.method == "POST":
username_val = request.form['user_id']
userpassword_val = request.form['user_password']
for authuser in Mydatabase.appdb:
for authpassword in authuser.values():
if authuser['username'] == username_val and authpassword['password'] == userpassword_val:
session['reg_user'] = username_val
return f'{session.get("reg_user")} have successfully logged into the application';
else:
return redirect(url_for('register'))
#app.route('/logout', methods=['GET','POST'])
def logout():
if 'reg_user' in session:
session.pop('reg_user',None)
return render_template("authusers.html")
#app.route('/register', methods=['GET','POST'])
def register():
return render_template('register.html')
#app.route('/reg_success',methods=['GET','POST'])
def reg_success():
newusercred={'username':request.form['user_id'], 'password':request.form['user_password']}
mydbusers.appdb.append(newusercred)
# return jsonify(Mydatabase.appdb)
return render_template("authusers.html")
if __name__=="__main__":
app.run(debug=True)
I see some logical issue in your code
Try like this ->
class Mydatabase:
appdb=[{'username':'Mary','password':'Password#123'},
{'username':'John','password':'Password#456'},
{'username':'Tara','password':'Password#789'}]
username_val = 'Tara'
userpassword_val = 'Password#789'
d = [a for a in Mydatabase.appdb if a["username"] == username_val and a["password"]==userpassword_val]
if d:
print(f'have successfully logged into the application')
else:
print(f'Wrong credentials')
There are some unwanted loops in your code, and you do return even in the else of part.

Python flask POST request

I develop an app in Python and use flask.
Here is a snippet of code that tries to generate a message by user input and then attach it to my database:
#app.route('/MakeMessage',methods = ['POST', 'GET'])
def MakeMessage():
if request.method == 'POST':
user_id = request.form['user_id']
content = request.form['content']
paticipants = [request.form['participant1'],request.form['participant2'],request.form['participant3']]
m = Message(user_id=user_id,content=content,participants=paticipants)
return redirect('/AddMessage',m = m)
#app.route('/AddMessage',methods = ['POST', 'GET'])
def AddMessage(m):
if request.method == 'POST':
db.session.add(m)
db.session.commit()
return 'Your message has been successfully saved'
I know something is wrong with the code, but I don't know what.
Any idea?
AddMessage
takes a parameter m
So in the app.route it should be changed to this
#app.route('/AddMessage/<m>')
You would want to use url_for() in the redirect function to redirect to a route in your application. In addition, you need to put <m> in your route for AddMessage.
from flask import redirect, url_for, request
#app.route('/MakeMessage',methods = ['POST', 'GET'])
def MakeMessage():
if request.method == 'POST':
...
return redirect(url_for('/AddMessage',m=m))
#app.route('/AddMessage/<m>',methods = ['POST', 'GET'])
def AddMessage(m):
...

Flask: request.referrer returns none when referred from external URL

New to Flask and Python. I've cloned a github Flask chat app example and am trying to get a referrer URL (i.e. the URL the user was in before going into my app). However, when I run the app locally, the referrer link always come back as None if the request comes from an external URL. If it is sent from within the app, I am getting the right referrer URL.
Here's the relevant bits of code. I've tried looking at previous questions, but couldn't find a solution.
My routing logic:
from flask import session, redirect, url_for, render_template, request
from . import main
from .forms import LoginForm
#main.before_request
def before_request():
print("Ref1:", request.referrer)
print("Ref2:", request.values.get("url"))
#main.route('/', methods=['GET', 'POST'])
def index():
form = LoginForm()
ip_address = request.access_route[0] or request.remote_addr
print("ip_addr:", ip_address)
if form.validate_on_submit():
session['name'] = form.name.data
session['room'] = form.room.data
return redirect(url_for('.chat'))
elif request.method == 'GET':
form.name.data = session.get('name', '')
form.room.data = session.get('room', '')
return render_template('index.html', form=form)
#main.route('/chat')
def chat():
name = session.get('name', '')
room = session.get('room', '')
if name == '' or room == '':
return redirect(url_for('.index'))
return render_template('chat.html', name=name, room=room)
My main app code is:
#!/bin/env python
from app import create_app, socketio
app = create_app(debug=True)
if __name__ == '__main__':
socketio.run(app)
Would really appreciate any advice.
Thanks!

How to integrate login required decorator to flask routes with a static user ID and password?

I am new to flask and python, i am trying to add login required and all routes other than home page. I read about flask-login module, haven't had any success. Looking for suggestions !
I tried using flask-login and prevent access of "/data" route. It did not work. My login requirement is very simple, allow login if user pass is admin/admin. And make sure the user is logged in for all subsequent routes.
Here is my flask code
from flask import Flask, render_template, redirect, url_for, request
import subprocess
import os
import datetime
import time
app = Flask(__name__)
#app.route("/")
def home():
now = datetime.datetime.now()
timeString = now.strftime("%Y-%m-%d %H:%M")
templateData = {
'title' : 'HELLO!',
'time': timeString
}
return render_template('main.html', **templateData)
#app.route('/login', methods=['GET', 'POST'])
def login():
error = None
if request.method == 'POST':
if request.form['username'] != 'admin' or request.form['password'] != 'admin':
error = 'Invalid Credentials. Please try again.'
else:
return redirect(url_for('data'))
return render_template('login.html', error=error)
#app.route("/data")
def data():
now = datetime.datetime.now()
timeString = now.strftime("%Y-%m-%d %H:%M")
templateData = {
'title' : 'HELLO!',
'time': timeString
}
return render_template('api.html', **templateData)
if __name__ == "__main__":
app.run(host='0.0.0.0', debug=True)
I dont want /data route to be accessed without login as admin/admin
flask_login should do the trick.
import and use the '#login_required' decorator on any route that you want to make unavailable to users who aren't currently logged in.
from flask_login import login_required
#app.route("/data")
#login_required
def data():
...
...
leave the decorator off of any routes that don't require login.
since you only have need for generic authentication you might look into session login.
for this, you'll need a secret key...
import secrets
app = Flask(__name__)
app.config['SECRET_KEY'] = secrets.token_hex(16)
and an example usage of flask session management.
from flask import session
#app.route('/login', methods=['GET', 'POST'])
def login():
error = None
if request.method == 'POST':
if request.form['username'] != 'admin' or request.form['password'] != 'admin':
error = 'Invalid Credentials. Please try again.'
else:
session['logged_in'] = True
return redirect(url_for('data'))
return render_template('login.html', error=error)

Categories

Resources