When does Flask store the user's authentication? - python

I created this form:
<html>
<body>
<div>
<form action="{{ url_for('login') }}" method="POST">
<div class="row">
<div>
<input id="email" name="email" type="email" class="validate">
<label for="email">Email</label>
</div>
</div>
<div class="row">
<div>
<input id="password" type="password" name="password" class="validate">
<label for="password">Password</label>
</div>
</div>
<button type="submit" id="login" >Login</button>
<br>
</form>
<div>
</body>
</html>
and I have this Flask app that uses HTTPBasicAuth to do authentication.
#!flask/bin/python
from flask import Flask, jsonify, abort, request, make_response, url_for
from flask import render_template
from flask_httpauth import HTTPBasicAuth
#Needs: pip install flask-httpauth
app = Flask(__name__)
auth = HTTPBasicAuth()
#app.route('/', methods=['GET','POST'])
#auth.login_required
def login():
print('in login')
print(request.values.get('email'), request.values.get('password'))
templateToReturn = 'login.html'
if request.method == 'POST':
print('in post')
username = request.values.get('email')
password = request.values.get('password')
if verify_password(username, password):
print('password verified')
templateToReturn = 'index.html'
print('Curr user', auth.current_user())
print('request: ', request.method)
if request.method == 'GET' and auth.current_user():
templateToReturn = 'index.html'
return render_template(templateToReturn)
#app.route('/logout')
def logout():
return render_template('logout.html')
#auth.verify_password
def verify_password(email, password):
print('in verify pwd')
return verifyAuthentication(email, password)
def verifyAuthentication(email, password):
knownUsers = {'p1#gmail.com': 'pass',
'p2#yahoo.com': 'pass'}
authenticated = False
if email in knownUsers:
if knownUsers[email] == password:
authenticated = True
return authenticated
When I click the submit button of the form, I'm taken to the login() function. But isn't there supposed to be some way that it should go to the verify_password() function because it's decorated with #auth.verify_password?
How exactly and in which part of the code does the user authentication get registered with Flask? By which I mean: When does the #auth.login_required decorator actually allow their corresponding decorated functions to get executed?
Even the official page of HTTPBasicAuth() didn't explain this with an HTML example. Could someone please explain by adding to my code.

You forgot to add name attribute in your HTML input tag, so ideally it should be -
<input id="email" name="email" type="email" class="validate" />
<input id="password" name="password" type="password" class="validate" />

Related

TypeError at /login/user login() takes 1 positional argument but 2 were given

im trying to login using django.contrib.auth
it giving me error
whenever im trying to login it gives me error below
TypeError at /login/user
login() takes 1 positional argument but 2 were given
this is my login template and url work perfectly from login/user
<div class="container border border-2 border-info rounded-2 p-3" style="width: 400px;margin-top: 100px; margin-bottom: 200px;">
<form action="user" method="post">
{% csrf_token %}
<h3 class="p-3">
<small class="text-muted">Login To Your Account</small>
</h3>
<div class="mb-3 form-floating">
<input type="text" class="form-control" id="InputUsername" aria-describedby="emailHelp" name="username" placeholder="Enter Username">
<div id="emailHelp" class="form-text">We'll never share your email with anyone else.</div>
<label for="InputUsername" >Username</label>
</div>
<div class="mb-3 form-floating">
<input type="password" class="form-control" id="InputPassword" name="password" placeholder="Enter Password">
<label for="InputPassword" class="form-label">Password</label>
</div>
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="exampleCheck1">
<label class="form-check-label" for="exampleCheck1">Remember me</label>
</div>
<button type="submit" class="btn btn-primary">Login</button>Create Account
</form>
</div>
urls.py look like this
from store.settings import MEDIA_ROOT, MEDIA_URL
from . import views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('',views.home,name="home"),
path('login/',views.login,name="login"),
path('register/',views.register,name="register"),
path('register/user',views.registeruser,name="registeruser"),
path('login/user',views.handlelogin,name="loginuser"),
path('/user/logout',views.handlelogout,name="logout")
]+ static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
views.py my handle login function
def handlelogin(request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
# Redirect to a success page.
return redirect('')
else:
# Return an 'invalid login' error message
return redirect('login')
def handlelogout(request):
logout(request)
return redirect(' ')
i dont get what im doing wrong
can someone tell me please
Based on your urls.py, you defined a login function, this thus means that if you call login(request, user), it will call the view function, not the login function from the django.contrib.auth module.
You can import it with a different name, for example:
from django.contrib.auth import login as authlogin
# &vellip;
def login(request):
# &vellip;
def handlelogin(request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
authlogin(request, user)
# Redirect to a success page.
return redirect('')
else:
# Return an 'invalid login' error message
return redirect('login')

How can I write a python requests test for my login API written in Flask which renders the HTML form for the same?

I have been trying to write basic login test using the python requests module. I designed the API endpoints using Flask which renders the HTML pages. Below is the HTML form for the login:
<form action="{{ url_for('login') }}" method="post" id="login" >
<div class="msg"><p class = "messagep">{{ msg }}</p></div>
<div class="form-group row">
<label for="inputEmail3" class="col-sm-2 col-form-label" >Username</label>
<div class="col-sm-10">
<input type="text" class="form-control" placeholder="Username" id="username" name="username">
</div>
</div>
<div class="form-group row">
<label for="inputPassword3" class="col-sm-2 col-form-label">Password</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="password" name="password" placeholder="Password">
</div>
</div>
<input type="checkbox" id="check">
<span>Remember me</span> </br></br>
<div class="right">
<a style="font-family: 'Arial';" href="#">Forgot Password</a>
<button type="submit" class="btn btn-light mb-2" name="log" >Submit</button>
</div>
</form>
The Flask API endpoint for login is as below:
#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']
if not username or not password:
msg = 'Please enter your username/password!'
return render_template('login.html', msg=msg)
cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
cursor.execute("SELECT * FROM users WHERE username = %s AND password = %s", [username, password])
account = cursor.fetchone()
if account:
session['loggedin'] = True
# session['id'] = account['id']
session['username'] = account['username']
session['fname'] = account['first_name']
msg = 'Logged in successfully !'
return redirect(url_for("home"))
else:
msg = 'Incorrect username / password !'
elif request.method == 'POST':
msg = 'Please fill out the form !'
elif request.method == 'GET':
uname = session.get("username", "Unknown")
if uname == "Unknown":
return render_template('login.html')
else:
return redirect(url_for("home"))
return render_template('login.html', msg=msg)
The Python requests test for this is as below:
def check_sign_in():
try:
credentials = {'username': 'test', 'password': ''}
session = requests.Session()
response = session.post('http://127.0.0.1:5000/login', data=credentials)
assert response.status_code == 200
print('Sign in successful!')
except AssertionError as e:
print('Sign in error!')
e.args += ('Received response code:', response.status_code)
raise
My worry now is that this test always passes even if I give incorrect credentials like in the above case, an empty password. I tried a lot of different approaches but still don't understand why it keeps passing. However, this feature seems to work properly when testing manually.

Login form using Flask-WTForm with Postgresql database

Thanks in Advance!!
I did the following things to create a login or Sign in the form:-
1)Created secret key
2)Used LoginManager and passed the app
3)Created a route for login.html
I am getting a Method Not Allowed page when I access the login page on the localhost.
Here is the code:-
app.py
```
from flask import Flask, render_template, request, flash, redirect, url_for, session, logging
from flask_login import LoginManager
from config import Config
app = Flask(__name__)
app.config.from_object(Config)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:password#localhost/learning'
db = SQLAlchemy(app)
# LoginManager
login_manager = LoginManager(app)# Login Form class
#app.route('/login', methods=['GET,''POST'])
def login():
if request.method == 'POST':
# get form fields
username = request.form['username']
password_candidate = request.form['password']
# getting user
login_user = Flask_Users.query.filter_by(username).first()
if login_user > 0:
# Get stored hash
password = login_user.password # is this right way to get one field from login_user??
# Compare passwords
if sha256_crypt.verify(password_candidate, password):
app.logger.info('PASSWORD MATCHED')
else:
app.logger.info('NO user')
return render_template('login.html')```
login.html
```
{% extends 'layout.html' %}
{% block body %}
<h1>Login</h1>
{% include 'includes/_messages.html' %}
<form action="" method="POST">
<div class="form-group">
<label>Username</label>
<input type="text" name="username" class="form-control" value={{request.form.username}}>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" name="password" class="form-control" value={{request.form.password}}>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
{% endblock %}
I followed what was in the documentation page. In the console, I am getting code 405 and error is the pic[enter image description here][1]
[1]: https://i.stack.imgur.com/fkf0m.png
Any help is appreciated. I did go through relevant posts on the website as well, but could not find anything relatable
You have a typo in your code
methods=['GET,''POST']
You need to correct to
methods=['GET','POST']

session.get('name') returns none, not form data

I have done a lot of research through multiple posts about this issue, and and no matter what I try I am getting issues. Essentially what I am trying to do it write something in an input field, press a submit button and post the string from the input field and display it on a separate page/separate route in using flask. I think I am on the right track with what I have below, however it returns a value of None rather than what I write in my input field in index.html.
from flask import Flask, render_template, request, jsonify, Response,
redirect, url_for,session
from flask_bootstrap import Bootstrap
app = Flask(__name__)
Bootstrap(app)
app.secret_key = 'dljsaklqk24e21cjn!Ew##dsa5'
#app.route('/', methods=['GET', 'POST'])
def hello():
if request.method == 'POST':
nme = request.form['name']
session['name'] = nme
return url_for(deliver)
return render_template('index.html')
#app.route('/delivery', methods=['GET', 'POST'])
def deliver():
name = session.get('name')
return render_template('delivery.html', name=name)
index.html is
<form action = "{{ url_for('deliver')}}" method = "POST">
<p>Name <input type = text class="form-control" name = "name" /></p>
<p>Address <input type = text class="form-control" name = "Address" /></p>
<input type=submit name='submit'>
</form>
and delivery.html is
<div class="card-deck mx-auto" style="width: 75rem;">
<div class="card text-white bg-dark p-3" style="width: 45rem;">
<h5 class="card-title text-center"></h5>
<img class="card-img-top mx-auto" src="/static/img/hands.png" alt="Vibration
Image" style="width:20%">
<div class="card-body">
<h2 class="card-title text-center">Delivery Information</h2>
<h5> {{name}} </h5>
This code:
<form action = "{{ url_for('deliver')}}" method = "POST">
means that submitting the form will POST to /deliver, but you really want to POST to the index page to trigger the session['name'] = nme code. So just remove the action.
You also need to change
return url_for(deliver)
to
return redirect(url_for('deliver'))

Flask : ImmutableMultiDict has no attribute

I wrote a small flask file:
myapp.py
#APP.route('/login', methods=['GET','POST'])
def login():
return flask.render_template('login.html')
#APP.route('/loginNext', methods=['POST','GET'])
def loginNext():
user=request.form.username
passw=request.form.password
return str(user)+str(pass)
login.html
<form id="foo" method="post" action="/loginNext">
Username : <input type="text" name='username' value="admin">
Password : <input type="password" name='password' value="">
<input type="submit" name="submit" value="Submit">
</form>
When I am trying to do request.form.username, I am getting
*AttributeError: 'ImmutableMultiDict' object has no attribute 'username' *
I read on stackoverflow as well as other places but didnot work. I tried doing request.form.get('username',None') that did not fetch the username.
<input type="text" name='username' value="admin"> was your input in .html file so to access in flask It is done in this way
username = request.form['username']
and you get the data as username .. same for password also.
if form tag contains below:-
<input type="text" name='username'>
In Flask Function, we can access it in 2 ways:-
username = request.form['username']
username = request.form.get('username')

Categories

Resources