Looking for some help on Django authentication with Angular login page - django

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

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.

Django MIDDLEWARE problem with RemoteUsers

My settings.py:
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.RemoteUserBackend',
'django.contrib.auth.backends.ModelBackend',
]
MIDDLEWARE = [
# ...
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.RemoteUserMiddleware',
# ...
]
ModelBackend is used by the DRF Browsable API.
RemoteUserBackend is used by the frontend app.
If a user logs into the Browsable API, the frontend will send both the auth token and the session token. Both credentials are diferent django users.
AUTHENTICATION_BACKENDS are suposed to work by order, but AuthenticationMiddleware goes first in MIDDLEWARE , it's mandatory.
A session-authenticated user gets wrong data in the frontend app. Django ignores remote user credentials. The user must logout from the browsable API.
How can I fix this?
Just for the record. I simply did a logout from the frontend at page load.

I'm not able to login after django version upgrade

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.

Django, csrf_token does not appear on form after redirection

I am using this middleware to redirect all pages to a landing page: (part of AuthRequiredMiddleware class.
def process_request(self, request):
assert hasattr(request, 'user')
if not request.user.is_authenticated():
path = request.path_info.lstrip('/')
if path not in ['ipn/', 'pp_cancel/', 'pp_success/', 'sitemap/', 'welcome/']:
lang = request.GET.get('lang', 'en')
ru = request.GET.get('ru', '')
return render_to_response('landing_en.html', RequestContext(request, {'ru': ru}))
and this is my settings.py
MIDDLEWARE_CLASSES = (
'django.middleware.cache.UpdateCacheMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'main.common.SessionBasedLocaleMiddleware.SessionBasedLocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'main.common.tz_middleware.TimezoneMiddleware',
'main.common.sslMiddleware.SSLRedirect',
'main.common.RedirectAllMiddleware.AuthRequiredMiddleware',
)
if the url is (for example) /welcome/ and no redirection is performed {% csrf_token %} works and shows in the form. If user is redirected no csrf_token is shown in the form.
What am I doing wrong?
From the wiki page about CSRF:
Cross-site request forgery, also known as a one-click attack or
session riding [...] is a type of malicious exploit of a website
whereby unauthorized commands are transmitted from a user that the
website trusts.
and later, under prevention:
Verifying that the request's header contains a X-Requested-With (used
by Ruby on Rails before v2.0 and Django before v1.2.5), or checking
the HTTP Referer header and/or HTTP Origin header.
So actually, your csrf protection is working well. Because, while I'm not 100% that the problem is specifically the missing referrer, I do think that it's caused by not using a proper redirect which triggers a csrf violation.
The solution - use HttpResponseRedirect and pass the information to the other view. You can pass it as GET data:
d = {'ru': ru, 'other': 'variables'}
url = '/landing/?%' % '&'.join( map(lambda x: '='.join(x), d.items()) )
return HttpResponseRedirect(url)
You can also use regex patterns in the urls (if that makes sense) or use sessions if there's anything sensitive in there.

Disable anonymous user cookie with Django

I use django auth for my website, which needs to have the session middleware installed.
Django session middleware always adds a session cookie, even for anonymous users (users that are not authenticated). When they authenticate the cookie is replaced by another one indicating the user is logged-in.
I want to disable the anonymous user cookie for caching purposes (varnish).
Is there a way to disable anonymous user cookies without removing session middleware which is necessary for apps using auth?
Session data is set in the cookie in the process_response of SessionMiddleware. This function doesn't use any setting or request.user, so you do not have any way of knowing inside this method whether the user is a logged in user or an anonymous user. So, you can't disable sending the session cookie to the browser.
However if you want this functionality then you can subclass SessionMiddleware and overide process_response.
from django.contrib.sessions.middleware import SessionMiddleware
from django.conf import settings
class NewSessionMiddleware(SessionMiddleware):
def process_response(self, request, response):
response = super(NewSessionMiddleware, self).process_response(request, response)
#You have access to request.user in this method
if not request.user.is_authenticated():
del response.cookies[settings.SESSION_COOKIE_NAME]
return response
And you can use your NewSessionMiddleware in place of SessionMiddleware.
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'myapp.middleware.NewSessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.doc.XViewMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
)