Routing in Flask when no function is given - python

I was going through this website where no function has been given to the '/' route but it still opens the login page when not logged in, I'm not sure how exactly this routing works...
Link:
https://www.geeksforgeeks.org/profile-application-using-python-flask-and-mysql/
Code:
#app.route('/')
#app.route('/login', methods =['GET', 'POST'])
def login():
msg = ''
if request.method == 'POST' and 'username' in request.form and 'password' in request.form:
username = request.form['username']
password = request.form['password']
cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
cursor.execute('SELECT * FROM accounts WHERE username = % s AND password = % s', (username, password, ))
account = cursor.fetchone()
if account:
session['loggedin'] = True
session['id'] = account['id']
session['username'] = account['username']
msg = 'Logged in successfully !'
return render_template('index.html', msg = msg)
else:
msg = 'Incorrect username / password !'
return render_template('login.html', msg = msg)

Flask lets you define routes in decorators. A given function may have one or more decorators.
Since the decorator for the / route is on the same function as the login/ route, both routes are handled by the login() function.
Since it's kind of confusing to have both routes pointing to the same function, one suspects that the author of the tutorial is using the first decorator as a placeholder, and will eventually change the / route to point to a template for a "landing page". (There are lots of reasons to have multiple routes hitting the same function, but no others are apparent from the code).
You might have been better served had the author included a comment, or explicitly redirected /:
#route("/")
def placeholder():
"""Redirect root to ``login`` for now"""
return redirect("/login")
Does this make sense?

Related

How can I use a json with flask_login.login_user

#app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
email = request.form['email']
password = request.form['password']
user = {
"email": str(email),
"password": str(password)
}
res = post("http://127.0.0.1:5000/auth/login", json=user)
if res.status_code == 200:
login_user(user, remember=True) #here is my problem
return redirect(url_for('products', pag=1))
else:
flash('Error')
return redirect(url_for('login'))
else:
return render_template('login.html')
How can I use login_user if I'm using a rest-api to get the user, and it return me a json?
I know flask_login uses a python-object, but my var res it return me a json not a python object.
I'm working with JWT at the rest-api, so my var res is just a JWT.
Why don't you just perform the login business logic under this login route but chose to call some other API endpoint? Also, you might return just the User object from that endpoint you are using and pass it to login_user(). The issue is that you provided little details. Please show what is going under http://127.0.0.1:5000/auth/login but also your User Model. That would help to provide a good and useful answer.

How do I know whether the registered email is verified or not in firebase?

I am making an app in the flask using firebase authentication with the pyrebase library.
following is the code I use for authentication...
#app.route('/register', methods=['GET', 'POST'])
def register_page():
form = RegisterForm()
if form.validate_on_submit():
data = {
"username": form.username.data,
"email_address": form.email_address.data,
"password_hash": form.password.data
}
db.collection('users').document(form.username.data).set(data)
def register():
email = form.email_address.data
password = form.password.data
confirm_pass = form.confirm_password.data
if password == confirm_pass:
sign_in = auth.create_user_with_email_and_password(email, password)
auth.send_email_verification(sign_in['idToken']) # for email verification
print("email verification sent")
register()
return redirect(url_for('market_page'))
if form.errors != {}: # if no errors occur from validators
for err_msg in form.errors.values():
print(f'there was an error creating the user {err_msg}')
return render_template('register.html', form=form)
I read most of the firebase documentation but I wasn't able to find any answer.
It looks like there is an emailVerified in the result from calling the get_account_info function.
I find it easiest to find this type of information by look at the Pyrebase auth implementation and then finding the Google documentation for the REST API that is invoked, which is getAccountInfo here.

Decrypting password with sha512_crypt - python3

I am implementing a basic web scraping webapp that requires registration and login to use the features. I am now facing an issue in the login [see below the code, please] when trying to decrypt a pwd from the mongodb database. I cannot pass the correct value in the sha512_crypt function, resulting in errors such as: '''ValueError: not a valid sha512_crypt hash'''
I have extensively researched the problem and tried multiple things, but still issues: What can you suggest? Thanks
#route for the signin page
#app.route("/signin", methods = ['GET', "POST"])
def signin():
form = Signin(request.form)
if request.method == 'GET': # make sure the method used is define above
return render_template('signin.html', form = form), print("you are under the signin page now, well done mrbacco")
if request.method == 'POST' and form.validate():
# the following are the data from the init form
email = form.email.data
password_form = form.password.data
print("these are the email and password inserted", email, password_form)
user_db = mycol_u.find_one({'email' : email})
for key, value in user_db.items():
print ("these are the fields in the db ", key, value)
if user_db is None:
flash("No USER FOUND!!, please try again", "danger")
return render_template('signin.html', form = form), print("user not found, flashed a message on the web page")
if sha512_crypt.verify(user_db['password'], password_form):
flash("You are now logged in", "success")
return redirect(url_for("home.html",form = form))
else:
flash("credential not correct, please try again", "danger")
print("redirecting to scraping page")
return render_template('signin.html', form = form)

Can we use JWT with sqlalchemy in flask api as below?

Following are the code files with relevant code snippets:
init.py:
app = Flask(__name__)
cors = CORS(app, resources={r"/api/*": {"origins": "*"}})
app.config['SECRET_KEY'] = 'super-secret'
In auth.py:
def authenticate_user(login, password):
'''
Return dict or None after checking against db for valid user
'''
s = select([users]).where(users.c.email==login)
result_set = conn.execute(s)
if result_set.rowcount == 1:
for r in result_set:
print r[users.c.password], 'result_set[users.c.password]'
if pwd_context.verify(password, r[users.c.password]):
# There is only one unique email/password pair
print 'matched'
return dict(r)
else:
return None
return
How to get the access_token value for the user on login? I have installed Flassk-JWT in the virtualenv and followed this doc: https://pythonhosted.org/Flask-JWT/ But please note I am not using OOPs ie. User class etc. I am using sqlalchemy core with Flask and python. To further use this token, I need to call it as a decorator for the API call is what I understand as:
#app.route('/rt/api/v1.0/list', methods=['GET'])
#jwt_required()
In views.py:
from myapp.auth import authenticate_user
#app.route('/auth', methods=['POST','GET'])
def login():
email = request.form["email"]
password = request.form["password"]
if request.method == 'POST':
result_set = authenticate_user(email, password)
if result_set:
session['email'] = result_set['email']
user_dict = result_set
if user_dict:
session['email'] = user_dict['email']
jwt = JWT(app, user_dict['email'], user_dict["id"])
How to exactly connect the various code files to get the access token value is what I am stuck up with.Please guide. Also Wish to exclude the login API request from the before_request callback(). All other APIs can have the before and after_request callbacks() executed.
Finally found a way better implementation with the basic usage on readthedocs

flask-login user is set to anonymous after login

im new to flask and flask-login and ive been struggling with this for days.
Im trying to log a user in like this:
from creds import auth_username, auth_password, pgsql_dbuser, pgsql_dbpassword, pgsql_db1name
from flask import Flask, render_template, request, Response, redirect, url_for
from flask.ext.bcrypt import Bcrypt
from flask.ext.login import LoginManager, login_required, login_user, current_user, logout_user
import logging
import psycopg2
import uuid
import datetime
app = Flask(__name__)
app.secret_key = str(uuid.uuid4()) # <- required by login_manager.init_app(app)
bcrypt = Bcrypt(app)
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'index'
#app.route('/', methods=['GET','POST'])
def index():
page_name = '/'
if request.method == 'POST':
email = request.form['email']
candidate_password = request.form['password']
user = finduserindbbyemail(email)
if user != None:
password_hash = checkuserpasswordindb(email)
if bcrypt.check_password_hash(password_hash, candidate_password):
user_object = User(user)
result = login_user(user_object) # <- here for successful login
return redirect(url_for('loggedin', user_object=type(user_object), user=user, result=result, current_user=current_user))
else:
user_object = User(user)
error_message = "The password you entered is incorrect"
return render_template('index.html', error_message=error_message)
else:
error_message = "The email address you entered does not match any we have in our records"
return render_template('index.html', error_message=error_message)
if request.method == 'GET':
return render_template('index.html')
I have a User class and a user callback:
class User():
def __init__(self, user):
self.user = user
def is_authenticated(self):
return True
def is_active(self):
return True
def is_anonymous(self):
return False
def get_id(self):
return unicode(self.user)
#login_manager.user_loader
def load_user(user):
con = psycopg2.connect(database=pgsql_db1name, user=pgsql_dbuser, password=pgsql_dbpassword, host='localhost')
uuid = "'"+user+"'"
cur = con.cursor()
cur.execute("SELECT uuid FROM users WHERE uuid = "+ uuid)
uuid = cur.fetchone()
con.close()
if uuid != None:
user = unicode(uuid[0])
return User.get_id(user)
else:
return None
After authentication is successful (apparently?), the user is redirected to a loggedin page which has a #login_required decorator. But instead of loading the loggedin page, the app redirects the user to the login page, telling me the user isnt being logged in?
If try to send values to the page and i remove the #login_required decorator so i can see the page, this is what i see in the browser after 'logging in':
current_user.is_authenticated() = False
current_user.is_active() = False
current_user.is_anonymous() = True
current_user.get_id() = None
user_object = <type 'instance'>
user = 2ca1296c-374d-43b4-bb7b-94b8c8fe7e44
login_user = True
current_user = <flask_login.AnonymousUserMixin object at 0x7f2aec80f190> Logout
It looks like my user hasn't been logged and is being treated as anonymous?
Can anyone see what I've done wrong? I'm having a lot of trouble understanding how this is supposed to work.
Another reason you might not be able to log a user in or current_user is Anonymous after going through your login form: The active=false flag is set on the user in the db. This behavior is confirmed in the docs:
flask_login.login_user(user, remember=False, duration=None, force=False, fresh=True)[source]
Logs a user in. You should pass the actual user object to this. If the user’s is_active property is False, they will not be logged in unless force is True.
This will return True if the log in attempt succeeds, and False if it fails (i.e. because the user is inactive).
So, when you call login_user, you can do this:
login_user(user, remember=form.remember_me.data, force=True), if you want to allow inactive users to log in.
So.. I managed to get it to work, but not using the user_loader callback. For whatever reason, my user loader exhibits the same behaviour as this:
Flask-login with static user always yielding 401- Unauthorized
Anyway, I used a request_loader callback instead based on this example:
http://gouthamanbalaraman.com/blog/minimal-flask-login-example.html
so for a user logging in, which starts here:
if bcrypt.check_password_hash(password_hash, candidate_password):
user_object = User(user, password_hash)
result = login_user(user_object) # <- here for successful login
token = user_object.get_auth_token(user, password_hash)
return redirect(url_for('loggedin', token=token))
I create a user object which has the user's id and their password hash.
then i log the user in. then i create a time-serialized token of the user id and password hash using itsdangerous. the get_auth_token function is part of the User class. it looks like this:
class User():
def __init__(self, user, password_hash):
self.user = user
self.password = password_hash
.
.
.
def get_auth_token(self, user, password):
data = [str(self.user), self.password]
return serializer.dumps(data, salt=serializer_secret)
you need to create a serializer at the beginning of your code somewhere:
serializer = URLSafeTimedSerializer(serializer_secret)
So after the token is created, pass it to the loggedin view as a URL query parameter.
When you try to load a login_required page, like my loggedin page, which is where login_user redirects me to after a successful login, the request_loader callback is executed. it looks like this:
#login_manager.request_loader
def load_user_from_request(request):
if request.args.get('token'):
token = request.args.get('token')
max_age = 1
try:
data = serializer.loads(token, salt=serializer_secret, max_age=max_age)
username = data[0]
password_hash = data[1]
found_user = finduserindbbyuuid(username)
found_password = checkuserpasswordindbbyuuid(username)
if found_user and found_password == password_hash:
user_object = User(found_user, password_hash)
if (user_object.password == password_hash):
return user_object
else:
return None
else:
return None
except BadSignature, e:
pass
else:
return None
This is the point where my user_loader was failing. I was logging in successfully, but the user_loader was always returning None and so my user would be deemed as anonymous.
So with the request loader, it checks that the request URL contains a 'token' argument in the query string. if so, it takes its value and using itsdangerous, deserializes the data.
you can make the token expire with timed serializers, but there are also non timed ones. after the token is deserialized, take the user and password hash and check in the database if they exist, in exactly the same way that the user_loader was supposed to work.. i imagine? my user_loader didnt work so i was most probably doing it wrong.
anyway if a user and password match in the db, then return the user object and bam, login works.
Im not sure if im doing it the right way, cos pretty much flying by the seat of my pants. i saw examples where people used the token_loader, rather than the request_loader callback function, to load the token, but i couldnt figure out how to set & get the auth token to & from the client. maybe ill figure it out... one day...
if you have the same problem, maybe this might help? or just let me know what you think
cheers
I found this page when searching for help with Flask-Login + Flask-Dance. I was seeing current_user as AnonymousUserMixin in a handler with the #login_required decorator. In my case making sure #app.route is on the line above #login_required fixed the problem. The correct order is in the docs: https://flask-login.readthedocs.io/en/latest/#flask_login.login_required.

Categories

Resources