Can't create DJANGO login form, that accepts either username or email - django

I am trying to create a login form in django that accepts either username or email. I made custom authentication backend and it does work. Problem is in HTML input type. The form method is POST and i did write csrf_token tag, but if i set input type to text, than when i try to login with username everything works, but when i put email in it, i get an error: CSRF verification failed. Request aborted. And if i set type to email, than i can't put username in. My django version is 4.0.6 and python version is 3.10.4

Add this in urls.py file
path('', include('django.contrib.auth.urls')),
Add this in your HTML template
{% extends 'registration/base.html' %}
{% block title %} Login {% endblock title %}
{% load crispy_forms_tags %}
{% block body %}
<h4>Hello! let's get started</h4>
<h6 class="font-weight-light">Sign in to continue.</h6>
<form class="pt-3" method="post">
{% csrf_token %}
{{ form|crispy }}
<div class="mt-3">
<button class="btn btn-block btn-primary btn-lg font-weight-medium auth-form-btn">SIGN IN</button>
</div>
<div class="my-2 d-flex justify-content-between align-items-center">
<div class="form-check">
<label class="form-check-label text-muted">
<input type="checkbox" class="form-check-input"> Keep me signed in </label>
</div>
Forgot password?
</div>
<div class="text-center mt-4 font-weight-light">
</div>
</form>

Related

Django 403 forbidden only happens at login in prod environment

I have a Login using the Django Login/authentication, once I Post the request to login I get the 403 Forbidden error with the following message:
CSRF verification failed. Request aborted.
You are seeing this message because this site requires a CSRF cookie
when submitting forms. This cookie is required for security reasons,
to ensure that your browser is not being hijacked by third parties.
If you have configured your browser to disable cookies, please
re-enable them, at least for this site, or for “same-origin” requests.
Help Reason given for failure:
CSRF cookie not set.
This only happens with the login and not with the other forms that I have in my application.
this is my login form:
{% extends "main/base.html" %}
{% load static %}
{% load widget_tweaks %}
{% block content%}
<div class='container'>
<div class='row pt-4'>
<div class="col">
</div>
<div class="col-md-4 col-md-offset-4">
<div class="card text-center">
<!-- Login Form -->
<div class="card-header bg-dark">
<h2 class="text-secondary">Login</h2>
</div>
<div class="card-body card text-left">
<form method="POST">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
<div class="form-group">
<label>{{ field.label_tag }}</label>
{% render_field field class="form-control" %}
{% for error in field.errors %}
<span class="help-block">{{ error }}</span>
{% endfor %}
</div>
{% endfor %}
<div class="form-group">
<p>¿Olvidaste tú usuario o contraseña? Click aquí!</p>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Ingresar</button>
</div>
</form>
</div>
</div>
</div>
<div class="col">
</div>
</div>
</div>
{% endblock %}
I have tried with everything in settings:
ALLOWED_HOSTS = ['http://*', 'https://*'] ( I have tried with the specific url)
CSRF_TRUSTED_ORIGINS = ['http://*', 'https://*'] ( I have tried with the specific url)
CSRF_COOKIE_SECURE = True (I have tried with False)
SESSION_COOKIE_SECURE = True (I have tried with False)
The functionality works fine in local for login.
If in production I access first to the admin and then go back to the login of the application, It works fine, but if I close the browser windonw and access through the login again I get the 403 error.
I'm using Djano 3.2 version
browser inspect -- network
The problem was that I had to access through https:// and I was accesing the site with only http://

Django-allauth Password Reset Email not sending

I have a weird problem where my allauth email will send to verify new user email address but no email will send for resetting the password. I have checked the gmail account from which the email should be sent but it only shows the verification emails as sent, its as though nothing is being done when the user clicks the reset password button on the template side. I'm not sure what I am missing..
My template
<body class="login-page container-fluid">
<div class="row vygr-login">
<div class="user_card">
<div class="container-fluid h-100">
<div class="row h-100">
<div class="form_container col vygr-signup-container">
{% load i18n %}
<form class="signup" method="POST" action="{% url 'account_login' %}">
{% if user.is_authenticated %}
{% include "account/snippets/already_logged_in.html" %}
{% endif %}
<p class="registration-element" style="font-size: 2rem;">{% trans "Trouble Logging In?" %}</p>
<p class=" registration-element">{% trans "Enter your email and we'll send you a link to get back into your account." %}</p>
<form method="POST" action="{% url 'account_reset_password' %}" class="password_reset">
{% csrf_token %}
{% for field in form %}
{{ field }}
{% endfor %}
<input class="signup-button" type="submit" value="{% trans 'Reset My Password' %}">
<p class="" style="text-align: center;">{% blocktrans %}Please contact us if you have any trouble resetting your password.{% endblocktrans %}</p>
</form>
</div>
</div>
</div>
</div>
</div>
</body>

Django: Trouble with logging user using Bootstrap login.html

I'm using Django 3.0.2 + Boostrap. I have created a registration/login.html page. The contents of this page are shown below.
The page renders correctly and most of it works OK. However, I am unable to login to my website through this page. I keep getting Your username and password did not match. Please try again. I can login to the admin website without any issues if I use the same username/password. I am not sure what is wrong with my login.html. Any ideas?
{% extends "base.html" %}
{% block content %}
{% if form.errors %}
<p>Your username and password did not match. Please try again.</p>
{% endif %}
{% if next %}
{% if user.is_authenticated %}
<p>Your account does nohave access to this page. To proceed,please login with an account that has access.</p>
{% else %}
<p>Please login to see this page.</p>
{% endif %}
{% endif %}
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-lg-6">
<div class="p-5">
<div class="text-center">
<h1 class="h4 text-gray-900 mb-4">Welcome Back!</h1>
</div>
<form class="user" method="post" action="{% url 'login' %}">
{% csrf_token %}
<div class="form-group">
<input type="text" class="form-control form-control-user" id="exampleInputUserName" placeholder="Username">
</div>
<div class="form-group">
<input type="password" class="form-control form-control-user" id="exampleInputPassword" placeholder="Password">
</div>
<input type="submit" class="btn btn-primary btn-user btn-block" value="Login">
<input type="hidden" name="next" value="{{ next }}">
</form>
<hr>
<div class="text-center">
<a class="small" href="forgot-password.html">Forgot Password?</a>
</div>
<div class="text-center">
<a class="small" href="register.html">Create an Account!</a>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
Contents of views.py:
from django.contrib.auth import logout
def logout_view(request):
"""Log out user from the website."""
logout(request)
Your input types are missing the name attribute. As per the Mozilla docs:
A string specifying a name for the input control. This name is
submitted along with the control's value when the form data is
submitted.
So the name is submitted with the form. But what if there is no name attribute?
Same Documentation explains:
Consider the name a required attribute (even though it's not). If an
input has no name specified, or name is empty, the input's value is
not submitted with the form.
So your username and password are not sent to the backend.
You need to provide the name attributes to your input types.
<form class="user" method="post" action="{% url 'login' %}">
{% csrf_token %}
<div class="form-group">
<input type="text" class="form-control form-control-user" id="exampleInputUserName" placeholder="Username" `name="username"`>
</div>
<div class="form-group">
<input type="password" class="form-control form-control-user" id="exampleInputPassword" placeholder="Password" name="password">
</div>
<input type="submit" class="btn btn-primary btn-user btn-block" value="Login">
<input type="hidden" name="next" value="{{ next }}">
</form>
It is front-end issue, not particularly related to Django.

Django login not showing errors

I know there are multiple questions like this around, but none of them contain a clear answer. I am using the default authentication from Django, but have trouble displaying something like 'Your username/password combination is incorrect'. Is it possible to fix this without making a custom view function?
My urls.py looks like this:
url(r'^login/$', auth_views.login, {'template_name': 'login.html'},
name='mysite_login')
Then my login.html has the following code:
{% block content %}
<section class="content">
<div class="container block">
<div class="row">
<div class="col-md-12"></div>
<form action="{% url 'mysite_login' %}" class="form-control" method="post" accept-charset="utf-8">
{% csrf_token %}
{% for field in form %}
<p>
{{ field.label_tag }}<br>
{{ field|addcss:'form-control' }}
{% if field.help_text %}
<small style="color: grey">{{ field.help_text|safe }}</small>
{% endif %}
{% for error in field.errors %}
<p style="color: red">{{ error }}</p>
{% endfor %}
</p>
{% endfor %}
<button type="submit" class="btn btn-dark">Login</button>
<input class="form-control" type="hidden" name="next" value="{{ next }}"><br>
</form>
</div>
</div>
</div>
</section>
{% endblock %}
So this all works, except for displaying the error messages. I've seen answers where you can write a custom view function and form to fix this, but I assume it should be also possible while using the build-in login functionality right? Thanks a lot.
The built-in login form doesn't display errors at an individual field level; it's a security risk to say that just the password is wrong, because it confirms the existence of a particular username. So the errors are raised in the general clean() method and are displayed in the template via {{ form.non_field_errors }}.

Show form validation error for User login on Modal itself- Django

Although my User login is working perfectly fine but I am unable to handle User form validation on modal itself. I mean, I am able to get the user name and pwd and validate it but if the user name and pwd didn't match, the page is redirected to a Django template. But I want to show the message like username pwd didn't match on modal itself not on another Django template.
Modal code
<div class="modal signUpContent fade" id="ModalLogin" tabindex="-1" role="dialog">
<div class="modal-dialog ">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"> × </button>
<h3 class="modal-title-site text-center"> Login </h3>
</div>
<div class="modal-body">
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
{% if next %}
{% if user.is_authenticated %}
<p>Your account doesn't have access to this page. To proceed,
please login with an account that has access.</p>
{% else %}
<p>Please login to see this page.</p>
{% endif %}
{% endif %}
<form action="{% url 'django.contrib.auth.views.login' %}" method="post">
{% csrf_token %}
{% if next %}
<input type="hidden" name="next" value="{{ next }}" />
{% endif %}
<div class="form-group login-username">
<div>
<input name="username" id="login-user" class="form-control input" size="20" placeholder="Enter Username" type="text" value="{{ username }}">
</div>
</div>
<div class="form-group login-password">
<div>
<input name="password" id="login-password" class="form-control input" size="20" placeholder="Password" type="password" value="">
</div>
</div>
<div class="form-group">
<div>
<div class="checkbox login-remember">
<label>
<input name="rememberme" value="forever" checked="checked" type="checkbox">
Remember Me
</label>
</div>
</div>
</div>
<div>
<div>
<input name="submit" class="btn btn-block btn-lg btn-primary" value="Log In" type="submit">
</div>
</div>
</form>
</div>
<div class="modal-footer">
<p class="text-center"> Not here before? <a data-toggle="modal" data-dismiss="modal" ng-href="#ModalSignup"> Sign Up. </a> <br>
<a data-toggle="modal" data-dismiss="modal" ng-href="#ModalPwdReset"> Lost your password? </a> </p>
</div>
</div>
</div>
setting.py
LOGIN_URL = '/login/'
LOGIN_REDIRECT_URL = '/index'
So, how to get error message on modal form itself ?
I have been having the same issue, I wanted to use the Django build in authentication system to make a login page for my portfolio/blog website, this means that I am not implementing custom forms/views at all for this, and I just create the view in the url.py directly from django.contrib.auth.views.login , I found a workaround that helps to my case, and maybe putting some logic in it others could find a way to adjust the idea to their projects as well, here is the code:
urls.py :
from django.conf.urls import url, include
from django.contrib import admin
from . import views as view
from django.contrib.auth import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^coltapp/', include('coltapp.urls')),
url(r'^$', view.HomePage.as_view(), name='home'),
url(r'accounts/login/$', views.login, name='login'),
url(r'accounts/logout/$', views.logout, name='logout', kwargs={'next_page': '/'}),
]
Notice this line:
url(r'accounts/login/$', views.login, name='login'),
Here I am using the build In Django login view - views.login - , so , like i said before, no custom form or views created for this pourpose.
Base.html
I am calling the modal as the bootstrap documentation recommend it, also, I am including this custom_modal.html inside of the base.html so i can use it in future operations; I have to point out that I have this on a nav-var, that's why is inside of a list item tag.
<li><a id="loginAnchor" data-toggle="modal" href="{% url 'login' %}" data-target="#custom_modal"><span class="glyphicon glyphicon-user"></span></a></li>
{# THIS WILL INCLUDE THE MODAL CONTACT WINDOW FOR FURTHER USE #}
{% include "coltapp/custom_modal.html" %}
custom_modal.html
a simple .html file with JUST the logic structure for the modal to work, but nothing else inside, no extended from base no nothing just as you can see.
<!-- Modal HTML -->
<div id="custom_modal" class="modal fade" >
<div class="modal-dialog">
<div class="modal-content modal-custom" >
</div>
</div>
</div>
In this way, i make this modal reusable, and after I will be able to inject any other data that I want inside of modal-content div by Ajax or whatever.
login.html
Here I managed the Rendering fields manually, I found this more practical as I have total control over each field from this form, remember, I have no view/form code for this login view, this comes with Django build-in auth views
<div id="login-jumbo" class="jumbotron">
<div style="margin-bottom:1%" class="modal-header">
<button id="login_close" type="button" class="close .login-close" data-dismiss="modal" aria-hidden="true">×</button>
<h1>Welcome back Nestor!</h1>
</div>
{% if form.errors %}
{% for error in form.non_field_errors %}
<div class="error-message">
<div class="alert alert-danger">
<h4>Ops! Invalid Data...</h4>
</div>
<ul><li><h5>{{ error|safe }}</h5></li></ul>
</div>
{% endfor %}
<script type="text/javascript">
var divisor = document.querySelectorAll(".form-div");
var len = divisor.length
for (let i=0; i < len; i++ ){
divisor[i].className += " has-error";
}
</script>
{% endif %}
<form id="login_form" action="{% url 'login' %}" method="POST">
{% csrf_token %}
{% for field in form.fields %}
{% if field == 'username' %}
<div class="form-group form-div">
<h4 class="control-label">{{ field|title }}</h4>
<input class="form-control" type="text" name="username">
</div>
{% else %}
<div class="form-group form-div">
<h4 class="control-label">{{ field|title }}</h4>
<input class="form-control" type="password" name="password">
</div>
{% endif %}
{% endfor %}
<div style="margin-top:2%" id="login_footer" align="right" class="modal-footer">
<button type="submit" class="btn btn-danger" value="login">Log In</button>
<input type="hidden" name="next" value="{{ next }}">
</div>
</form>
</div>
Have to note: I've managed the errors inside of this template,
{% if form.errors %} then I will call an alert message from bootstrap, this is really important for what I'm going to do in the next section in the JS file, also I've iterated over the fields and put them into a div in pairs, login, and password fields, and also I have made a little script that will add a class to those divs in case of errors found on form. class='has-error', these error classes comes directly from bootstrap for error handling.
- this is the data that will be rendered inside of the modal!
Jquery ajax request
The Ajax call is very self-explained, and also there are a lot of reference on internet about this o about how they have to be implemented
$(document).on('submit','#login_form', function(e){
e.preventDefault();
var login_form = $('#login_form');
var action = login_form.attr('action');
var method = login_form.attr('method');
var data_ = login_form.serialize();
$.ajax({
type: method,
url: action,
data: data_,
success: function(data, status) {
if ($(data).find('.alert-danger').length > 0) {
$('.modal-custom').html(data);
// console.log(data)
}else{
console.log('Log In Form Successfuly Summited')
$('#custom_modal').modal('hide')
location.reload(); //Reload the current document page on success
}
}
});
return false;
});
going through this, you pass the necessary data to the ajax call, and if this function is a success, you will apply some logic:
If find any element with ('.alert-danger') class on it, this means that the form has some errors on it, (you could use 'has-error' too), so if this condition is true, keep the modal open, and send the data again with the line:
$('.modal-custom').html(data);
'modal-custom' is the inner div from the custom_modal.html, where everything is rendered.
If not errors in form, that means no ('.alert-danger') class found on it, hide the modal, and reload the current document location, it means to reload the actual URL on the web browser, I made this because is a modal login page, sI i will need some elements to appear after the user is logged In.
also, I made to little more procs to clean the modal from errors on hiding, because if I was not logged In, and close the modal again without re-loading any page, these errors will appear again on the modal, so this was more for a cleanness procedure.
var restoreModalOnClose = function(){
var error_fields = $('.has-error')
var danger_pop = $('.alert-danger')
danger_pop.parent().remove()
$.each(error_fields, function(index, value){
$(value).removeClass('has-error');
// console.log(value)
})
};
$('#custom_modal').on('hidden.bs.modal', function (e){
console.log('here')
restoreModalOnClose()
});
I hope this helps to anyone in the future, I been reading a lot of post, docs and etc etc, and at the end, i found a workaround what satisfied what I was looking for.
JPG reference:
You can override the clean method:
from django.core.exceptions import ValidationError
class MyForm(forms.ModelForm):
.... # your code here
def clean(self):
if wrong_credentiels():
raise ValidationError("username pwd didn't match")
wrong_credentiels is a method where you can put in your verification logic