Django LDAP authentication - django

Given an username and password, I want to authenticate against a LDAP directoy with these credentials in one of my Django apps. I've been taking a look Django-auth-ldap but I still don't know how to use it properly once I've configured it.
On the one hand, I receive a JSON with username and password and I need to add an user to LDAP with these credentials. And, on the other hand, in subsequent request, I need to check that the user who makes the request belongs to LDAP (and only LDAP not the own Django backend, so if there's an user with the same credentials in the Django users database should't be allow to continue).
I've tried something like this to add an user:
authbackends.py
class CustomLDAPBackend(LDAPBackend):
def authenticate(self, username, password, **kwargs):
# Add user to LDAP
user = LDAPBackend.authenticate(self, username, password)
return user
So I can import it in my view to add the user to LDAP.
Could anyone outline a solution?

Related

How to Login programmatically in Django?

I need to login programmatically in Django.I had registered by using normal registration page. but i need to login for a single person by saying the username and password in the program itself.So he is allowed to view the requested page.I don't need user authorization, just to redirect the page if username and password is " given in the program.."
You can use authenticate and login.
authenticate user credentials to confirm they are valid. If they are, authenticate will return a User object.
Then use login and you are all set.
Example:
from django.contrib.auth import login, authenticate
user = authenticate(request, username="some_user", password="some_password")
if user:
login(request, user)
Use with caution between sessions and make sure you are not mistakenly logging a stranger to an incorrect user.

How to set password in user table when user is signup using google or facebook django allauth

By overriding the SocialAccountManager
def save_user(self, request, sociallogin, form=None):
"""
Saves a newly signed up social login. In case of auto-signup,
the signup form is not available.
"""
u = sociallogin.user
u.set_unusable_password()
if form:
get_account_adapter().save_user(request, u, form)
else:
get_account_adapter().populate_username(request, u)
sociallogin.save(request)
return u
how to get the password from social account signup
Actually, you can't.
Django Allauth does not hash or store passwords for social login users. It does not handle the authentication on its end.
Suppose a user try to do a google login at your website, the authentication happens on google servers not on your end. If the user's password is correct then LOGIN_REDIRECT_URL = "url-name/" defined in your django project redirects that user to the url.
You can't get the password. If you can, or those social apps share the password of their users, then both you and that social apps have violate the user privacy rules. In my opinion it's a crime.
The only way you could do is ask your user to set a new password for your site. Send them an email to confirm the change. But that means you have to make an additional route for your app, which has no point.

how to generate token using username and pin field in django auth toolkit for a phone app while keeping username and password for the web application?

I am using DRF with auth toolkit and it is working fine. However, I want to have a second login api so a user can log in using username and pin number. It is cos we have a USSD application and it is easier to give them a pin based login system.
Currently, I have the following URL that, when called, generates token:
url(r'^signin/', include('oauth2_provider.urls', namespace='oauth2_provider')),
For the ussd app, I want something like that but the auth2 should check pin field, defined in a separate model defined as follows:
class Members(models.Model):
pin=models.IntegerField()
user=models.ForeignKey(User)
I am a little lost where to start.
Using this answer as a base to answer this question, and Django's documentation.
I would say you'd want to create a custom authentication backend, and you'd want a custom user model with two passwords, or using a one-to-one relationship to add the additional password field, something like so:
from django.contrib.auth.models import AbstractBaseUser
class UserExtension(AbstractBaseUser):
user = models.OneToOneField(User)
...
Inheriting from the AbstractBaseUser should add a password field like the user model, (although I haven't tried this). If you prefer the custom user approach, I actually have a github repo that has a custom user app, so if you'd like to get any ideas of how to achieve this check it out.
Or have a look through the documentation.
Either way, once you've got your two passwords, you need to decide which one to use as the pin. If you're using oauth for the pin field and the web applicaiton with the password, I would probably use the standard user password for the pin login, as that way you don't need to change the oauth package to work with your new password. Then for your web application build a custom login. To do this create a custom authentication backend along the lines of:
from django.contrib.auth.models import User
from django.contrib.auth.hashers import check_password
class AuthBackend(object):
supports_object_permissions = True
supports_anonymous_user = False
supports_inactive_user = False
def get_user(self, user_id):
return User.objects.filter(pk=user_id).first()
def authenticate(self, username, password):
user = User.objects.filter(username=username).first()
if not user:
return None
# this is checking the password provided against the secondary password field
return user if check_password(password, user.userextension.password) else None
Then you need to add this authentication backend to your settings:
AUTHENTICATION_BACKENDS = ('myapp.backends.AuthBackend',)
Then create the web application login (as per the stackoverflow answer above):
from django.contrib.auth import authenticate, login
def my_login_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:
# Return a 'disabled account' error message
...
else:
# Return an 'invalid login' error message.
...
You should now have a custom authentication login for the web application using your password2 field, and you can use the oauth authentication to work with the standard Django password in which you're going to store the pin. Which I think is what you're trying to do?
NOTE: All of the above I haven't tested, so this may not work perfectly, but it should hopefully be able to at least point you in the right direction and give you a few ideas. If I'm understanding your problem correctly, this is the sort of approach that I would take to tackle the problem.

Want different lookup parameters in django login

I am using django and have email verification feature so when someone verifiy email , I activate his/her account by setting status. If some one will someone else email address then he will not be able to verify and will not able to login with that. So I was expecting django to look at status of user also while login as this status field is in table that is of django auth app. While on login django tries to login with only username param. So on login it says:
MultipleObjectsReturned at /accounts/login/
get() returned more than one User -- it returned 2! Lookup parameters were {'username': u'kaasib122#gmail.com'}
Is there a way to add status field also in lookup? Is there something in cofiguration for that or I need to write some sort of login backend for that? Or should I write my own view for login table in some different way? What is recommended way? Also I am thinking to let user either login using email or username in username field. So what is recommended way?
You need to write an authentication backend that suits your needs. Check out the django documentation.
Basically, you will need to write an "authenticate" method which will use "status" in the filter parameters. For using email or username, you could basically filter on one field (username or email) and if no User objects are returned for that field, filter on the other. Or you can get the user in a single filter by ORing those fields. Here's a pseudocode:
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User
class AuthenticationBackend(ModelBackend):
def authenticate(self, username=None, password=None):
try:
user = User.objects.get(email=username, status=True)
except User.DoesNotExist:
try:
user = User.objects.get(username=username, status=True)
except User.DoesNotExist:
return None
# check password too
if user.check_password(password):
return user
return None
Note that when you write new authentication backend, you need to add it to AUTHENTICATION_BACKENDS parameter in your settings.py for it to be used. If you don't need the default one Django provides because you have customized it, just override that parameter, no need to add to the tuple.

how to access the request in a django custom authentication backend?

I want to do the following with django's authentication:
Log incorrect log-in attempts
Temporarily lock accounts after 'x' number of incorrect log-in attempts
Log successful log-ins.
I thought a custom auth backend would be the solution.
I can do most of what i want, but I want to log the IP and REMOTE_HOST of the user making the attempt.
how can I access the request object in the auth backend?
Thanks
The authentication backend can take any number of custom parameters for the authenticate() method. For example:
class MyBackend:
def authenticate(self, username=None, password=None, request=None):
# check username, password
if request is not None:
# log values from request object
If you are calling authenticate in your own view, you can pass the request object:
from django.contrib.auth import authenticate
def login(request):
# discover username and password
authenticate(username=username, password=password, request=request)
# continue as normal
If you're using django's login view (or the admin login), you wont have the extra information. Put simply, you'll have to use your own custom login view.
Also, be careful when automatically locking accounts: you allow someone to deliberately lock one of your user's accounts (denial of service). There are ways around this. Also, make sure your log of incorrect attempts doesn't contain any attempted passwords.
In recent versions of Django, authenticate() accepts "request" as first parameter:
optionally since Django 1.1
required since Django 2.1
See:
https://docs.djangoproject.com/en/2.1/releases/1.11/#deprecated-features-1-11
https://docs.djangoproject.com/en/2.1/releases/2.1/