Certificate verify failed due to recaptcha - python-3.x

I registered recaptcha for my WTForms, and This error **
SSL: CERTIFICATE_VERIFY_FAILED pops up
when i submitted the form.
I registered recaptcha on google with label = localhost and domains = localhost and 127.0.0.1
When I submitted the form after verifying that I'm not a robot, I got redirected to the page with following error:
urllib.error.URLError urllib.error.URLError:
urlopen error [SSL:
CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)
If I set app.config['TESTING'] to True, the form gets submitted just fine.
Here's what my app.py looks like:
from flask import Flask, render_template
from flask_wtf import FlaskForm, RecaptchaField
from wtforms import StringField, PasswordField
from wtforms.validators import InputRequired, Length, AnyOf
app = Flask(__name__)
app.config['SECRET_KEY'] = 'Thisissecret!'
app.config['RECAPTCHA_PUBLIC_KEY'] = '6LdUxpsUAAAAAEKf7HmevAB9-ntHArEovS2pDmOP'
app.config['RECAPTCHA_PRIVATE_KEY'] = '6LdUxpsUAAAAACtXnVVOYTX1M9Hv83jkhzx4KxX1'
app.config['TESTING'] = False
class LoginForm(FlaskForm):
username = StringField('username', validators=[InputRequired(message='A username is required!'), Length(min=5, max=10, message='Must be between 5 and 10 characters')])
password = PasswordField('password', validators=[InputRequired(message='Password is required!'), AnyOf(values=['password', 'secret'])])
recaptcha = RecaptchaField()
#app.route('/form', methods=['GET', 'POST'])
def form():
form = LoginForm()
if form.validate_on_submit():
return '<h1>The username is {}. The password is {}.</h1>'.format(form.username.data, form.password.data)
return render_template('form.html', form=form)
if __name__ == '__main__':
app.run(debug=True)
In my form.html, I have included {{ form.recaptcha }} in the body section.
I expect that the form would submit just fine after the recaptcha validation.

Related

Django custom login issue

I have created a custom authenticate method because instead of username I want to log in through email for that I have written backends.py
backends.py
from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError
UserModel = get_user_model()
class EmailBackend(object):
def authenticate(username=None,password=None):
try:
user = UserModel.objects.get(email=username)
if user.check_password(password):
return user
else:
return None
except UserModel.DoesNotExist:
raise ValidationError('Invalid Credentials')
def get_user(self,user_id):
try:
return UserModel.objects.get(pk=user_id)
except UserModel.DoesNotExist:
return None
After authenticating i want user to be logged in.For that i am using login method as below:
login(request,user,backend='django.contrib.auth.backends.ModelBackend')
views.py
from django.shortcuts import render,redirect
from users.forms import RegisterForm,LoginForm
from users.backends import EmailBackend as em
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth import login
def register(request):
if request.method=='POST':
form = RegisterForm(request.POST)
if form.is_valid():
form.save()
print('Successfully Created')
else:
form = RegisterForm()
return render(request,'users/register.html',{'form':form})
def user_login(request):
if request.method == 'POST':
form = LoginForm(request.POST)
uname = request.POST['username']
pwd = request.POST['password']
user = em.authenticate(username=uname,password=pwd)
if user is not None:
if user.is_active==True:
k=login(request,user,backend='django.contrib.auth.backends.ModelBackend')
print(user,k)
print('Successfull login')
else:
print('Unsuccessfull login')
else:
form = LoginForm()
return render(request,'users/login.html',{'form':form})
In my console, I am trying to get the value returned by the login function but that is returning None .
k=login(request,user,backend='django.contrib.auth.backends.ModelBackend')
print(user,k)
Output in my console:
[16/Mar/2021 16:02:34] "POST /register/ HTTP/1.1" 200 881
[16/Mar/2021 16:02:52] "GET /login/ HTTP/1.1" 200 705
testuser#gmail.com None
Successfull login
[16/Mar/2021 16:02:58] "POST /login/ HTTP/1.1" 302 0
[16/Mar/2021 16:02:58] "GET /home HTTP/1.1" 200 237**
Print method is giving the correct value of user but for k it is giving None. That means the login function is not working and that means login authentication is not working properly.
How can I do login once authenticate method is returned, user? In which way login can be successful.
My code:
settings.py
AUTHENTICATION_BACKENDS = ['django.contrib.auth.backends.ModelBackend',
'users.backends.EmailBackend']
models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser,AbstractUser
from django.utils.translation import gettext_lazy as _
class CustomUser(AbstractBaseUser):
email = models.EmailField(_('email address'), unique=True)
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
USERNAME_FIELD='email'
forms.py
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django import forms
from users.models import CustomUser
class RegisterForm(UserCreationForm):
class Meta():
model = get_user_model()
fields = ('email', 'password1', 'password2')
class LoginForm(AuthenticationForm):
class Meta():
model = get_user_model()
You are doing you login wrong. You are referencing the auth Backend you just overwrote.
In your login function, do
login(request, user)
And in your settings
AUTHENTICATION_BACKENDS = ['users.backends.EmailBackend', 'django.contrib.auth.backends.ModelBackend']
One more thing, do not import your backend. Just import django authenticate module like you would do if weren't having your own backend
And change your authenticate line to
From django.contrib.auth import authenticate
user = authenticate(username=uname, password=pwd)
I got the answer login method has no return value that's why it is returning None. Once authenticate method is executed it will return a user if credentials are valid . After that login method will make you logged in.

How to redirect a page from one blueprint view to another?

I am using Flask along with the Blueprint module. In my application, I am trying to redirect the page to page/home after a successful login (user/login) using LDAP but the redirect takes forever without throwing any error.
I tried a couple of different variations of redirect(url_for('page.home')), redirect(url_for('page/home.html')). But each of these commands do not redirect. I am not sure what I am doing wrong. Kindly help.
Folder structure:
user/views.py:
from flask import Flask, Blueprint, request, render_template, redirect, url_for, session
from ldap3 import Server, Connection, ALL, NTLM
from snakeeyes.blueprints.page.views import page
import config.settings as p
user = Blueprint('user', __name__, template_folder='templates')
user.secret_key = 'dev key'
# #user.route('/')
# #user.route('/login')
# def login():
# return render_template('user/login.html')
def connect_ldap(username, password):
if not username or not password:
return False
# try:
# from ldap3 import Server, Connection, ALL, NTLM
# except ImportError as importException:
# print("LDAP3 import not found, run 'sudo pip install ldap3 && sudo pip3 install ldap3'")
# print(importException)
# return False
# define the server
server = Server('us01ds', port=389, get_info=ALL)
# define the connection
user = 'uid=%s,ou=people,ou=users,dc=global,dc=COMPANY,dc=com' % username
conn = Connection(server, user, password, auto_bind=True)
# perform the Bind operation
if not conn.bind():
print('error in bind', conn.result)
return False
else:
return True
#user.route('/', methods=['GET', 'POST'])
#user.route('/login/', methods=['GET', 'POST'])
def login():
# global username
# username = None
# If POST, redirect to dashboard
if request.method == 'POST':
username = request.form['username'].encode('utf8').decode("utf-8")
password = request.form['password'].encode('utf8').decode("utf-8")
# Try to login using ldap
test = connect_ldap(username, password)
# Invalid credentials
if not test:
return render_template(
'login.html',
isinvalid='is-invalid',
error='Username or Password is incorrect'
)
else:
# session['user_id'] = request.form['username']
print('redict to home page')
return redirect(url_for('page.home'))
# If GET, render the login page
else:
return render_template('user/login.html')
page/views.py:
from flask import Blueprint, render_template
page = Blueprint('page', __name__, template_folder='templates')
#page.route('/home')
def home():
return render_template('page/home.html')
#page.route('/terms')
def terms():
return render_template('page/terms.html')
#page.route('/privacy')
def privacy():
return render_template('page/privacy.html')
I found a fix for this problem.
In order to better facilitate the generation of URLs that make use of an HTTPS URL
scheme this patch adds a parameter with this specific purpose in mind. To
achieve this we explicitly pass in a param, _scheme='https', and then set the
url_scheme attribute of our MapAdapter instance appropriately.
Importantly, _external=True must be set in order for this to work properly.
As such, failure to do so results in a ValueError being raised.
So, I just replace return redirect(url_for('page.home')) => return redirect(url_for('page.home', _external=True, _scheme='https'))
Reference: https://github.com/pallets/flask/commit/b5069d07a24a3c3a54fb056aa6f4076a0e7088c7

Flask LDAP3 Auth Blueprint fails with Uninitialized ASN.1 value

I'm trying to put together a flask blueprint for LDAP3 auth. If I use the same code as a standard flask app, everything works as expected, the bind is successful and the user auth also succeeds:
DEBUG:root:Validating LDAPLoginForm against LDAP
DEBUG:flask_ldap3_login:Opening connection with bind user 'XXXX#XXXX.COM'
DEBUG:flask_ldap3_login:Successfully bound to LDAP as 'XXXX#XXXX.COM' for search_bind method
DEBUG:flask_ldap3_login:Performing an LDAP Search using filter '(&(objectclass=person)(sAMAccountName=YYYY))', base 'ou=Users,ou=XXXX,dc=XXXX,dc=COM', and scope 'SUBTREE'
DEBUG:flask_ldap3_login:Opening connection with bind user 'CN=YYYY,OU=Admin Users,OU=Users,OU=XXXX,DC=XXXX,DC=COM'
DEBUG:flask_ldap3_login:Directly binding a connection to a server with user:'CN=YYYY,OU=Admin Users,OU=Users,OU=XXXX,DC=XXXX,DC=COM'
DEBUG:flask_ldap3_login:Authentication was successful for user 'YYYY'
but as soon as I turn it into a blueprint:
DEBUG:root:Validating LDAPLoginForm against LDAP
DEBUG:flask_ldap3_login:Opening connection with bind user 'XXXX#XXXX.COM'
DEBUG:flask_ldap3_login:Destroying connection at <0x7f181f9ee2b0>
ERROR:flask_ldap3_login:Uninitialized ASN.1 value ("__len__" attribute looked up)
My init.py is as follows
from flask import Flask
app = Flask(__name__)
app.config.from_object('config')
from app.ldauth.views import auth_blueprint
app.register_blueprint(auth_blueprint)
And app/ldauth/views.py:
from flask import Flask, Blueprint, url_for
from flask_ldap3_login import LDAP3LoginManager
from flask_login import LoginManager, login_user, UserMixin, current_user
from flask import render_template_string, render_template, redirect
from flask_ldap3_login.forms import LDAPLoginForm
from app import app
auth_blueprint = Blueprint('ldauth',__name__,template_folder='templates')
login_manager = LoginManager(app) # Setup a Flask-Login Manager
ldap_manager = LDAP3LoginManager(app) # Setup a LDAP3 Login Manager.
login_manager.login_view = "auth.login"
users = {}
class User(UserMixin):
def __init__(self, dn, username, data):
self.dn = dn
self.username = username
self.data = data
def __repr__(self):
return self.dn
def get_id(self):
return self.dn
#login_manager.user_loader
def load_user(id):
if id in users:
return users[id]
return None
#ldap_manager.save_user
def save_user(dn, username, data, memberships):
user = User(dn, username, data)
users[dn] = user
return user
#auth_blueprint.route('/login', methods=['GET', 'POST'])
def login():
template = """
{{ get_flashed_messages() }}
{{ form.errors }}
<form method="POST">
<label>Username{{ form.username() }}</label>
<label>Password{{ form.password() }}</label>
{{ form.submit() }}
{{ form.hidden_tag() }}
</form>
"""
# Instantiate a LDAPLoginForm which has a validator to check if the user
# exists in LDAP.
form = LDAPLoginForm()
if form.validate_on_submit():
# Successfully logged in, We can now access the saved user object
# via form.user.
login_user(form.user) # Tell flask-login to log them in.
# TODO: Validate next to ensure it is safe!
return redirect(next) # Send them home
return render_template_string(template,form=form)
pip freeze:
Babel==2.5.1
blinker==1.4
click==6.7
Flask==0.12.2
Flask-BabelEx==0.9.3
flask-ldap3-login==0.9.13
Flask-Login==0.4.0
Flask-Mail==0.9.1
Flask-Principal==0.4.0
Flask-Security==3.0.0
Flask-SQLAlchemy==2.3.2
Flask-WTF==0.14.2
itsdangerous==0.24
Jinja2==2.10
ldap3==2.3
MarkupSafe==1.0
passlib==1.7.1
pkg-resources==0.0.0
pyasn1==0.3.7
pyasn1-modules==0.1.5
python3-ldap==0.9.8.4
pytz==2017.3
speaklater==1.3
SQLAlchemy==1.1.15
Werkzeug==0.12.2
WTForms==2.1
I'm clearly missing something here, any ideas?
Turns out this was some issue with the virtualenv. Created a new virtualenv this morning and moved the code into it, works as expected.

'NoneType' object has no attribute 'password'

I want to create a functional login form using flask web framework. I am using Google Datastore. Currently, I am getting the following error.
'NoneType' object has no attribute 'password'
Also, I am not sure about the id attribute I've used in the User Model. May be the server does not recognize id's for each user. Kind of confused. Any help is appreciated.
my models.py file in view:
import datetime
from google.appengine.api import memcache
from google.appengine.api import users
from google.appengine.ext import db
from google.appengine.ext import ndb
class User(ndb.Model):
id = ndb.StringProperty()
username = ndb.StringProperty()
email = ndb.StringProperty()
password = ndb.StringProperty()
joined_at = ndb.DateTimeProperty()
updated_at = ndb.DateTimeProperty()
is_admin = ndb.BooleanProperty(default=False)
# Flask-Login integration
def is_authenticated(self):
return True
def is_active(self):
return True
def is_anonymous(self):
return false
def get_id(self):
return self.id
forms.py file:
class LoginForm(Form):
username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
main.py:
from flask import Flask, g, flash, render_template, url_for, redirect
from flask_login import LoginManager, login_user
import models
import forms
#app.route('/login', methods=['GET', 'POST'])
def login():
form = forms.LoginForm()
if form.validate_on_submit():
try:
user = models.User.exists(username = form.username.data)
except models.DoesNotExist:
flash("Your email does not match", "error")
else:
if user.password == form.password.data:
login_user(user)
flash("You've been logged in!", "success")
return redirect(url_for('index'))
else:
flash("Your password does not match!", "error")
return render_template('login.html', form=form)
You are currently just checking weather username exists or not. You have to fetch that entity first then check username and password. This will solve your problem.
user_check = User.query(User.username == form.username.data).get()
if user_check:
if user_check.password == form.password.data:
print "Success"
else:
print "Wrong Password"
else:
print "No Username Exists"

Django REST: AttributeError: 'WSGIRequest' object has no attribute 'session'

I've created a Login APIView for my Django app. I'm continually getting the error, AttributeError: 'WSGIRequest' object has no attribute 'session'. I've looked at other posts and people mention reordering the middleware placing sessionMIddleware first which doesn't work. Here is the setup of the API. The error is occurring at login(request, user).
from django.contrib.auth import authenticate, login
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializers import LoginSerializer
from rest_framework.permissions import AllowAny
class Login(APIView):
permission_classes = (AllowAny, )
authentication_classes = ()
serializer = LoginSerializer
def post(self, request, format=None):
login_form = self.serializer(data=request.data)
data = dict()
if login_form.is_valid():
username = login_form.data['username']
password = login_form.data['password']
user = authenticate(username=username, password=password)
if user is not None:
print(request.data)
login(request, user)
data['data'] = 'OK'
return Response(data=data, status=200)
else:
data['error'] = 'Invalid login information provided'
return Response(data=data, status=401)
else:
data['invalid'] = 'Bad Request, form is invalid'
return Response(data=data, status=400)
Ok, I had my middleware defined as MIDDLEWARE in my settings.py instead of MIDDLEWARE_CLASSES. Pycharm generated it for me like that when I setup the new project. I believe Django 1.10 uses MIDDLEWARE and I'm using 1.9.

Resources