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.
Related
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).
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')
We use custom authentication for our django webapp, where we hit the company ldap. Since we're using a custom backend, we seem to only be able to return None, or the username of a user from our db.
def authenticate(self,username,password):
"""
Authenticate the username credentials, and return the
"""
try:
self.ldap.simple_bind_s(username+"#"+settings.AUTH_LDAP_DOMAIN,password)
self.ldap.unbind_s()
except ldap.INVALID_CREDENTIALS:
logger.debug("Invalid credentials used for login.")
username = None
except ldap.SERVER_DOWN, e:
logger.debug("Ldap server is down.")
username = None
return username
Clearly there are three different use cases here - one where it works, one where it doesn't because the credentials are invalid, and one where the server is down. Django's custom backend seems to only really handle two of these though - invalid credentials, or working ones. How would I redirect to an error page, or inform the user that ldap is down?
I'd look at raising a custom exception in your auth backend, and catch it in your login view. Returning None from your auth backend simply means "I couldn't authenticate these credentials - try the next backend".
So, in pseudo-code,
class LoginView(TemplateView):
def post(self, request):
try:
user = authenticate(request.POST['username'], request.POST['password'])
except MyCustomLdapError:
return HttpResponseRedirect('ldap_server_unavailable.html')
else:
if user:
return HttpResponseRedirect('logged_in.html')
else:
return HttpResponseRedirect('login_failed.html')
In real life, you'd of course use a form to validate some of this - but you get the idea.
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/
I've been searching here and there, and based on this answer I've put together what you see below.
It works, but I need to put some stuff in the user's session, right there inside authenticate.
How would I store acme_token in the user's session, so that it will get cleared if they logged out? The request object is not available in this context
class AcmeUserBackend(object):
# Create a User object if not already in the database?
create_unknown_user = False
def get_user(self, username):
return AcmeUser(id=username)
def authenticate(self, username=None, password=None):
""" Check the username/password and return an AcmeUser. """
acme_token = ask_another_site_about_creds(username, password)
if acme_token:
return AcmeUser(id=username)
return None
Shove it onto the returned user, then handle it in middleware.