I'm not able to login after django version upgrade - django

I'm trying to upgrade an old code from django 1.5 to 1.8 for a client. The project use django.contrib.auth.views.login to verify the login. the urls.py looks as follow:
urlpatterns = patterns('',
url(r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'accounts/login.html', 'authentication_form': LoginForm}, name="login"),
url(r'^accounts/logout/$', 'django.contrib.auth.views.logout', {'template_name': 'accounts/logged_out.html'}, name="logout"),
)
Here is the LoginForm class:
class LoginForm(forms.Form):
username = forms.CharField(label=_("Username"), max_length=120)
password = forms.CharField(label=_("Password"), widget=forms.PasswordInput)
def __init__(self, request=None, *args, **kwargs):
self.request = request
self.user_cache = None
super(LoginForm, self).__init__(*args, **kwargs)
def clean(self):
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
if self.request:
if not self.request.session.test_cookie_worked():
raise forms.ValidationError(_("Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in."))
return self.cleaned_data
and here is the list of the middlewares:
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
'apps.facebook.middleware.FacebookMiddleware',
)
Before the upgrade I was able to login, but after upgrading I'm no longer able to login. I got the following non-field error:
Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in.
If I downgrade to django 1.5 I can login again. How can I solve the problem and why the login is not working in django 1.8.

Remove the cookie test from your login form, it isn't necessary. The check was removed from the Django login form in Django 1.7 (release notes).
You have CSRF protection enabled, which already ensures that cookies are enabled.
It's not clear why you are defining your own login form, instead of using the built in form. Using your own form means you hit problems like this, and miss out on new features like the confirm_login_allowed hook.

Related

Django csrf token not refreshed after first login

I have hosted a website at http://cognezic-dev.ap-south-1.elasticbeanstalk.com/login/. On closer inspection, the form has the same csrf token across page refreshes and browsers, which I suspect to be the cause of the issue,this works fine on the local django server.Dont know where this is being cached. I have added CSRF Middleware in the settings.py too.
You can use the test credentials as username bismeet and password bis12345 for testing.
I have also tried creating a custom middleware as follows:
from django.middleware.csrf import rotate_token, CsrfViewMiddleware
from django.utils.deprecation import MiddlewareMixin
class CSRFRefresh(CsrfViewMiddleware,MiddlewareMixin):
def process_response(self, request, response):
print("Custom MiddleWare called")
rotate_token(request)
return response
But it still fails.
My settings.py with custom middleware contains:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'solvesto.middleware.csrf_refresh.CSRFRefresh'
]
If not using the custom middleware,I use:
'django.middleware.csrf.CsrfViewMiddleware'
instead of
'solvesto.middleware.csrf_refresh.CSRFRefresh'
The only last resort I see to make this work is to remove csrf altogether,which is of course,bad for security.
I removed the csrf security,no other solution,works now.

How to add an attribute to Django request object

I try to add the business attribute to the request object by using my own middleware, it nicely works with rest_framework.authentication.SessionAuthentication and I can use request.business in my views. But when I try to authenticate with JWT method (rest_framework_simplejwt.authentication.JWTAuthentication) when my middleware code is run request.user is set to AnonymouseUser so can't fetch business associated with user? Why did this happen?
# middleware.py
class MyMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
request.business = None
if request.user.is_authenticated and hasattr(request.user, 'business'):
request.business = request.user.business
response = self.get_response(request)
return response
Middlewares:
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'my_app.middleware.MyMiddleware',
]
rest_framework settings:
REST_FRAMEWORK = {
...
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
'rest_framework.authentication.SessionAuthentication',
],
}
Unfortunately, DEFAULT_AUTHENTICATION_CLASSES are not processed in middleware process, but in the view itself. What is giving you the proper user when using session is the Django's AuthenticationMiddleware and REST Framework is just using this value when the session authentication is enabled.
To solve that, you can do one of the following:
Move adding request.business to the views (for example by adding some class that all your views will inherit from)
Move JWT authentication into Django middlewares (this has a side effect of DRF enforcing CSRF checks by default when user is logged in)

Looking for some help on Django authentication with Angular login page

I have an angular login page that sends an Ajax request to my django server (listening on a separate port from the angular application), and I am able to log my user in but a session cookie is not getting returned in the response for the client to store in the angular app. Here is what my backend settings.py looks like the for authentication specific stuff:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',]
# Here are the session specific settings
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_AGE = 1800 # The age of session cookies, in seconds
CORS_ORIGIN_ALLOW_ALL = True
And here is my login view function that is hooked up to my login path:
#csrf_exempt
#require_POST
def login_view(request: HttpRequest):
payload = request.body.decode()
body = json.loads(payload)
username = body['username']
password = body['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)# Log the user in
return HttpResponse('Success')
else:
return HttpResponseBadRequest()
I am trying to used cookie/ session based authentication so that if the user closes the page and relaunches it before the session time has expired, it will direct them back to the landing page, and for a specific input select field only certain options are supposed to be returned based on the user, and that would need to be handled via the session authentication. Is there something that is not correct in my settings file?
Try to set SESSION_COOKIE_SECURE and CSRF_COOKIE_SECURE to False, maybe because your request is insecure
Django CSRF Cookie Not Set

curl request on django working without csrf token

I have a django project running on Heroku, using Django REST framework
I use the following middlewares:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
Here is one of my class-based views :
class CommunityMemberView(APIView):
permissions_classes = [IsAuthenticated, ]
serializer_class = CommunitySerializer
def post(self, request, community_id=None):
"""
add the member identified by 'id'
to the community 'community_id', if it exists.
"""
data = request.data
id = data.get('id')
account = Account.objects.get(id=id)
community = Community.objects.get(id=community_id)
community.add_member(account)
serializer = self.serializer_class(community, context={'request': request})
return Response(serializer.data, status=status.HTTP_201_CREATED)
When I try to do a POST request using curl, and without any csrf token, it works fine, and I don't know why. I don't use any decorator, but if I understand the django doc correctly, I don't need to.
curl -v -H "content:application/json" -X POST -H "Content-Type:application/json" -d '{"id":"3"}' https://www.example.com/api/v1/community/2/member/ | python -m json.tool
I'm guessing there is an obvious reason, but I can't find it in the django doc nor on Stack Overflow, all the previous questions on a related topic were about why it's not working, not the contrary.
Thanks
Im assuming you are using django-rest-framework?
DRF views are wrapped w/ #csrf_excempt decorator unless you're using SessionAuthentication
See http://www.django-rest-framework.org/topics/ajax-csrf-cors/

middleware does an infinite redirect

I've already read this but the answer doesnt fit my needs.
I've made this very simple middleware:
class RedirectIfUserIsNotActiveMiddleware(object):
"""
Middleware to redirect if account is disabled
"""
#staticmethod
def process_request(request):
if not request.user.is_active:
try:
# test to see if not already on the right url:
a = resolve(request.path)
if a.url_name != settings.URL_REDIRECT_USER_NOT_ACTIVE:
return HttpResponseRedirect(
reverse_lazy(settings.URL_REDIRECT_USER_NOT_ACTIVE))
# request.path do a 404 if URL unknown -> do nothing :
except Resolver404:
pass
And I've added this here:
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
'third_party.hqf_middleware.RedirectIfUserIsNotActiveMiddleware',
)
But when the account is disabled I get an infinite loop with the message on the webbrowser: "mywebsite.com redirected you too many times.".
In my settings I have this:
URL_REDIRECT_USER_NOT_ACTIVE = 'my_home_profile_account_desactivated'
And the URL I'm trying to get is always (even each time step by step) /en/my-home/profile/edit
What am I missing?
It looks as if the my_home_profile_account_desactivated view is redirecting to your login page, and then the middleware redirects back to my_home_profile_account_desactivated, creating a redirect loop.
You should be able to break the authentication loop by changing the middleware so that you only redirect users that are authenticated and inactive.
#staticmethod
def process_request(request):
if request.user.is_authenticated() and not request.user.is_active:
...