I am trying to use django's inbuilt authentication system for my application.
I'm able to authenticate a user during login but, for the following requests request.user.is_authenticated is coming as False
login view:
user_name = request_body['username']
password = request_body['password']
user = authenticate(username=user_name, password=password)
if user is not None:
login(request, user)
request.session.set_expiry(86940)
I've written a decorator to check authentication, the code is:
from django.http import HttpResponse
def authenticate_request(f):
def check(request):
if request.user.is_authenticated: #coming as false even after authenication is done
return f(request)
else:
return HttpResponse(status=401)
return check
What am I missing while authenticating the request?
Check your current SESSION_COOKIE_AGE and make sure that you dont overwrite it somewhere else in you program. Make sure that you dont immediately get logged out. The default value of SESSION_COOKIE_AGE is 1209600 (2 weeks, in seconds).
Related
I am using Django 1.9.
Base on the Django documentation:
" To log a user in, from a view, use login(). It takes an HttpRequest object and a User object. login() saves the user’s ID in the session, using Django’s session framework."
So how do I retrieve the information in that session.
For example: (this is also taken from the documentation)
from django.contrib.auth import authenticate, login
def my_view(request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
**login(request, user)**
# Redirect to a success page.
else:
How do I retrieve the user information such as username or if possible the password out on the success page.
P.S
If you could also kinda explain the solution in layman term as possible
EDIT
I was playing around with the framework back then. So I was testing if it can be done.
You don't get it from the session.
The authentication middleware adds the current user to the request, as request.user.
(And you definitely do not ever retrieve or display the password.)
I'm looking for a way in which I can send out a user an email with a url that will log them into their user. This doesn't even necessarily have to expire. I have found tons of material on sessions however this is not what I'm after. What I need is this:
User submits something to the website
They have an account made in the background
An email is sent out containing a link "site.com/&token=foobar23124123"
The user can log in using that link (optional: for the next week)
Is there something out there that I'm missing that would help me or would I have to implement my own solution? Could I potentially just include the token from Django REST framework's Tokens?
Thank you for taking the time to read my question.
I'm Using Django 1.9 and Python 2.7
I don't think there is something for authenticating users using url get-parameters. AFAIK Django REST framework's Tokens uses HTTP headers for tokens.
You can write your own auth backend, it's quite easy. Here is an example
myproject/setting.py
AUTHENTICATION_BACKENDS = [
'myproject.backends.UrlTokenBackend',
'django.contrib.auth.backends.ModelBackend'
]
myproject/backends.py
class UrlTokenBackend(ModelBackend):
def authenticate(self, token):
try:
user = User.objects.get(token=token)
except User.DoesNotExist:
return None
if not user.is_active:
return None
return user
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
Now when you will call authenticate and login function Django will check your user against each of your backends. You can manually login user like this (this is view function):
from django.contrib.auth import authenticate, login
def user_auth(request):
token = request.GET.get('token')
user = authenticate(token=token)
login(request, user)
return redirect('index')
Update
Or you can use this hack and do only this (without custom backend):
def user_auth(request):
token = request.GET.get('token')
user = User.objects.get(token=token)
user.backend = 'django.contrib.auth.backends.ModelBackend'
login(request, user)
return redirect('index')
I know there is documentation for this question here https://docs.djangoproject.com/en/1.9/topics/auth/customizing/, however I need some clarification on my use case.
I basically have an api that I created. What this api does is submit user form data to an external url, and once submitted, the data is saved to that external urls database.
I can then get a specific user through another api call. The user is returned as an object. Now I am trying to log that user in on my end using the django.contrib.auth through my system but what I have isn't working.
Here is my process:
A. I added a custom authentication backend to my settings.py file
AUTHENTICATION_BACKENDS =(
'new_app.backends.SettingsBackend',
'django.contrib.auth.backends.ModelBackend',
)
B. In my new_app's backend file, I have the following code:
class SettingsBackend(object):
def authenticate(self, username=None, password=None):
if username and password:
user = api.get_user()
#add pk to user object to satisfy django error warning
user.pk = user.unique_field
return user
return None
def get_user(self, user_id):
try:
if self.user.pk == user_id:
return self.user
except:
return None
In a signin view, I am trying to log the user in using this:
def login_user(request, username, password):
from django.contrib import auth
if not username and password:
raise ValueError("Invalid username and password")
auth_user = auth.authenticate(username=username, password=password)
if auth_user is None:
raise ValueError("Invalid username and password")
auth.login(request, auth_user)
return auth_user
I get the error saying:
'api.get_user()' object has no attribute 'save'
The error is occuring on the auth.login(request, auth_user) line.
I think the reason is because the django.contrib.auth thinks my user object is a django model. So, the question is how should I tackle this to make it work given my scenario? Thanks for the time.
I'm not an expert at django subtleties (as it's been a while I left django for microframeworks).
That said, if I were you, what I'd do is to make sure that whatever api.get_user() is returning, implement whatever API django is expecting from that object, which means starting with an empty save() method on it.
But I'd also do standard django stuff, like #RA123 suggests in a comment, by setting AUTH_USER_MODEL up.
this is the code :
def openid_done(request, provider=None):
"""
When the request reaches here, the user has completed the Openid
authentication flow. He has authorised us to login via Openid, so
request.openid is populated.
After coming here, we want to check if we are seeing this openid first time.
If we are, we will create a new Django user for this Openid, else login the
existing openid.
"""
if not provider:
provider = request.session.get('openid_provider', '')
if hasattr(request,'openid') and request.openid:
#check for already existing associations
openid_key = str(request.openid)
#authenticate and login
try:
user = authenticate(openid_key=openid_key, request=request, provider = provider)
except:
user = None
if user:
login(request, user)
if 'openid_next' in request.session :
openid_next = request.session.get('openid_next')
if len(openid_next.strip()) > 0 :
return HttpResponseRedirect(openid_next)
return HttpResponseRedirect(LOGIN_REDIRECT_URL)
# redirect_url = reverse('socialauth_editprofile')
# return HttpResponseRedirect(redirect_url)
else:
return HttpResponseRedirect(LOGIN_URL)
else:
return HttpResponseRedirect(LOGIN_URL)
and the code use like this :
authenticate(openid_key=openid_key, request=request, provider = provider)
Is it right ?
I think the code must be like this :
user = authenticate(username='john', password='secret')
Does authenticate have the argument openid_key,provider ?
Should i Rewrite authenticate my myself to handle it .
thanks
No, django does not have an authenticate function that expects openid_key, provider arguments.
grep -r "openid" django returns nothing for version 1.2.3
What you are looking at is a custom authentication backend, like the one found on github here: https://github.com/agiliq/Django-Socialauth/blob/master/socialauth/auth_backends.py
class OpenIdBackend:
def authenticate(self, openid_key, request, provider, user=None):
try:
assoc = UserAssociation.objects.get(openid_key=openid_key)
return assoc.user
#....
Next time you notice that a function isn't being used normally, you should start wondering if it's even the same one you are thinking about : )
You should look at where the authenticate function was imported from, and you'd see it's not django project code.
Hay I was wondering if anyone knew a better way to do this.
def login_user(request):
username = request.POST.get('username')
password = request.POST.get('password')
user = User.objects.filter(username=username)
if user:
user = user[0]
if user.password == generate_password(password):
return HttpResponse("password fine")
else:
return HttpResponse("password incorrect")
else:
return HttpResponse("no user found by that username")
and the generate_password function is just
generate_password(string):
return hashlib.sha224(str(string)).hexdigest()
Any ideas would be great.
Thanks
Why don't use Django auth default views ?
the only amelioration i see is use get instead of filter (it will save you one line)
user = User.objects.get(username=username)
Looking at the level of control you want to have, you'll want to make use of the authenticate and maybe login functions in django.contrib.auth. These are the main functions for accessing authentication. I should stress that you really, really should use these instead of finding the user and checking the password hash manually. There are a number of reasons why:
they will make use of whatever authentication backend you or someone else in the future have installed
your version will be far less tested than Django's and is more likely to open security holes
it's quicker, shorter, more flexible and more readable
Django's auth app will probably change in the near future, sticking to authenticate will help you migrate to the new auth app when it gets written/committed/released
If you do want to rewrite the way a user is found and authenticated, write your own Authenticate backend, which will be used when you call authentication (even in someone else's app, like the admin). This is the only place you should rewrite authentication in Django.
The following examples are from the Django auth docs.
1. Checking a user's password:
from django.contrib.auth import authenticate
user = authenticate(username='john', password='secret')
if user is not None:
if user.is_active:
print "You provided a correct username and password!"
else:
print "Your account has been disabled!"
else:
print "Your username and password were incorrect."
2. Custom authentication backend:
Here is a backend that uses the same authenticate method as Django's, which you can find at django.contrib.auth.backends.ModelBackend:
from django.contrib.auth.models import User
class MyBackend:
def authenticate(self, username=None, password=None):
try:
user = User.objects.get(username=username)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
You should download django-registration and go through the code. It manages everything for you, including cleaning the code. Your original code will not handle empty submissions.
http://bitbucket.org/ubernostrum/django-registration/