Skip to content
Snippets Groups Projects
Commit ae49f9dd authored by Ben Adida's avatar Ben Adida
Browse files

Revert "Add ldap auth"

parent eb5bb241
No related branches found
No related tags found
No related merge requests found
...@@ -2,9 +2,6 @@ ...@@ -2,9 +2,6 @@
AUTH_SYSTEMS = {} AUTH_SYSTEMS = {}
import twitter, password, cas, facebook, google, yahoo, linkedin, clever import twitter, password, cas, facebook, google, yahoo, linkedin, clever
import ldapauth
AUTH_SYSTEMS['twitter'] = twitter AUTH_SYSTEMS['twitter'] = twitter
AUTH_SYSTEMS['linkedin'] = linkedin AUTH_SYSTEMS['linkedin'] = linkedin
AUTH_SYSTEMS['password'] = password AUTH_SYSTEMS['password'] = password
...@@ -13,7 +10,6 @@ AUTH_SYSTEMS['facebook'] = facebook ...@@ -13,7 +10,6 @@ AUTH_SYSTEMS['facebook'] = facebook
AUTH_SYSTEMS['google'] = google AUTH_SYSTEMS['google'] = google
AUTH_SYSTEMS['yahoo'] = yahoo AUTH_SYSTEMS['yahoo'] = yahoo
AUTH_SYSTEMS['clever'] = clever AUTH_SYSTEMS['clever'] = clever
AUTH_SYSTEMS['ldap'] = ldapauth
# not ready # not ready
#import live #import live
......
# -*- coding: utf-8 -*-
"""
LDAP Authentication
Author : shirlei@gmail.com
Version: 1.0
Requires libldap2-dev
django-auth-ldap 1.2.7
LDAP authentication relies on django-auth-ldap (http://pythonhosted.org/django-auth-ldap/),
which considers that "Authenticating against an external source is swell, but Django’s
auth module is tightly bound to a user model. When a user logs in, we have to create a model
object to represent them in the database."
Helios, originally, does not rely on default django user model. Discussion about that can be
found in:
https://groups.google.com/forum/#!topic/helios-voting/nRHFAbAHTNA
That considered, using a django plugin for ldap authentication, in order to not reinvent the
wheel seems ok, since it does not alter anything on original helios user model, it is just
for authentication purposes.
However, two installed_apps that are added when you first create a django project, which were
commented out in helios settings, need to be made available now:
django.contrib.auth
django.contrib.contenttypes'
This will enable the native django authentication support on what django-auth-ldap is build upon.
Further reference on
https://docs.djangoproject.com/en/1.8/topics/auth/
"""
from django import forms
from django.conf import settings
from django.core.mail import send_mail
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from helios_auth.auth_systems.ldapbackend import backend
# some parameters to indicate that status updating is possible
STATUS_UPDATES = False
LOGIN_MESSAGE = "Log in with my LDAP Account"
class LoginForm(forms.Form):
username = forms.CharField(max_length=250)
password = forms.CharField(widget=forms.PasswordInput(), max_length=100)
def ldap_login_view(request):
from helios_auth.view_utils import render_template
from helios_auth.views import after
error = None
if request.method == "GET":
form = LoginForm()
else:
form = LoginForm(request.POST)
request.session['auth_system_name'] = 'ldap'
if request.POST.has_key('return_url'):
request.session['auth_return_url'] = request.POST.get('return_url')
if form.is_valid():
username = form.cleaned_data['username'].strip()
password = form.cleaned_data['password'].strip()
auth = backend.CustomLDAPBackend()
user = auth.authenticate(username, password)
if user:
request.session['ldap_user'] = {
'user_id': user.email,
'name': user.first_name + ' ' + user.last_name,
}
return HttpResponseRedirect(reverse(after))
else:
error = 'Bad Username or Password'
return render_template(request, 'password/login', {
'form': form,
'error': error,
'enabled_auth_systems': settings.AUTH_ENABLED_AUTH_SYSTEMS,
})
def get_user_info_after_auth(request):
return {
'type': 'ldap',
'user_id' : request.session['ldap_user']['user_id'],
'name': request.session['ldap_user']['name'],
'info': {'email': request.session['ldap_user']['user_id']},
'token': None
}
def get_auth_url(request, redirect_url = None):
return reverse(ldap_login_view)
def send_message(user_id, name, user_info, subject, body):
send_mail(subject, body, settings.SERVER_EMAIL, ["%s <%s>" % (name, user_id)], fail_silently=False)
def check_constraint(constraint, user_info):
"""
for eligibility
"""
pass
def can_create_election(user_id, user_info):
return True
from django.core.exceptions import ImproperlyConfigured
from django_auth_ldap.backend import LDAPBackend
from django_auth_ldap.config import LDAPSearch
from django_auth_ldap.backend import populate_user
class CustomLDAPBackend(LDAPBackend):
def authenticate(self, username, password):
"""
Some ldap servers allow anonymous search, returning just a subset
of user attributes. So here we re-perform search after user is authenticated,
in order to populate other user attributes.
For now, just in cases where AUTH_LDAP_BIND_PASSWORD is empty
"""
user = super(CustomLDAPBackend, self).authenticate(username, password)
if user and self.settings.BIND_PASSWORD == '' :
search = self.settings.USER_SEARCH
if search is None:
raise ImproperlyConfigured('AUTH_LDAP_USER_SEARCH must be an LDAPSearch instance.')
results = search.execute(user.ldap_user.connection, {'user': user.username})
if results is not None and len(results) == 1:
(user.ldap_user._user_dn, user.ldap_user.user_attrs) = results[0]
user.ldap_user._load_user_attrs()
user.ldap_user._populate_user_from_attributes()
user.save()
return user
helios_auth/media/login-icons/ldap.png

4.65 KiB

# -*- coding: utf-8 -*-
""" """
Unit Tests for Auth Systems Unit Tests for Auth Systems
""" """
...@@ -14,7 +13,6 @@ from django.test import TestCase ...@@ -14,7 +13,6 @@ from django.test import TestCase
from django.core import mail from django.core import mail
from auth_systems import AUTH_SYSTEMS from auth_systems import AUTH_SYSTEMS
from helios_auth import ENABLED_AUTH_SYSTEMS
class UserModelTests(unittest.TestCase): class UserModelTests(unittest.TestCase):
...@@ -130,197 +128,3 @@ class UserBlackboxTests(TestCase): ...@@ -130,197 +128,3 @@ class UserBlackboxTests(TestCase):
self.assertEquals(len(mail.outbox), 1) self.assertEquals(len(mail.outbox), 1)
self.assertEquals(mail.outbox[0].subject, "testing subject") self.assertEquals(mail.outbox[0].subject, "testing subject")
self.assertEquals(mail.outbox[0].to[0], "\"Foobar User\" <foobar-test@adida.net>") self.assertEquals(mail.outbox[0].to[0], "\"Foobar User\" <foobar-test@adida.net>")
'''
tests for LDAP auth module.
Much of the code below was get or inspired on django-auth-ldap package.
See site-packages/django_ldap_auth/tests.py
'''
import ldap
import auth_systems.ldapauth as ldap_views
from mockldap import MockLdap
from django_auth_ldap.backend import LDAPSettings
from django_auth_ldap.config import LDAPSearch
from helios_auth.auth_systems.ldapbackend.backend import CustomLDAPBackend
try:
from django.test.utils import override_settings
except ImportError:
override_settings = lambda *args, **kwargs: (lambda v: v)
class TestSettings(LDAPSettings):
"""
A replacement for backend.LDAPSettings that does not load settings
from django.conf.
"""
def __init__(self, **kwargs):
for name, default in self.defaults.items():
value = kwargs.get(name, default)
setattr(self, name, value)
class LDAPAuthTests(TestCase):
"""
These tests uses mockldap 0.2.7 https://pypi.python.org/pypi/mockldap/
"""
top = ("o=test", {"o": "test"})
people = ("ou=people,o=test", {"ou": "people"})
groups = ("ou=groups,o=test", {"ou": "groups"})
alice = ("uid=alice,ou=people,o=test", {
"uid": ["alice"],
"objectClass": ["person", "organizationalPerson", "inetOrgPerson", "posixAccount"],
"userPassword": ["password"],
"uidNumber": ["1000"],
"gidNumber": ["1000"],
"givenName": ["Alice"],
"sn": ["Adams"],
"mail": ["alice@example.com"]
})
bob = ("uid=bob,ou=people,o=test", {
"uid": ["bob"],
"objectClass": ["person", "organizationalPerson", "inetOrgPerson", "posixAccount"],
"userPassword": ["password"],
"uidNumber": ["1001"],
"gidNumber": ["50"],
"givenName": ["Robert"],
"sn": ["Barker"],
"mail": ["bob@example.com"]
})
john = ("uid=john,ou=people,o=test", {
"uid": ["john"],
"objectClass": ["person", "organizationalPerson", "inetOrgPerson", "posixAccount"],
"userPassword": ["password"],
"uidNumber": ["1002"],
"gidNumber": ["60"],
"givenName": ["Robert"],
"sn": ["Doe"]
})
directory = dict([top, people, groups, alice, bob, john])
def _init_settings(self, **kwargs):
self.backend.settings = TestSettings(**kwargs)
@classmethod
def setUpClass(cls):
cls.mockldap = MockLdap(cls.directory)
@classmethod
def tearDownClass(cls):
del cls.mockldap
def setUp(self):
self.mockldap.start()
self.ldapobj = self.mockldap['ldap://localhost']
self.backend = CustomLDAPBackend()
self.backend.ldap # Force global configuration
def tearDown(self):
self.mockldap.stop()
del self.ldapobj
def test_backend_login(self):
""" Test authentication usign correct username/password """
if 'ldap' in ENABLED_AUTH_SYSTEMS:
self._init_settings(
BIND_DN='uid=bob,ou=people,o=test',
BIND_PASSWORD='password',
USER_SEARCH=LDAPSearch(
"ou=people,o=test", ldap.SCOPE_SUBTREE, '(uid=%(user)s)'
)
)
user = self.backend.authenticate(username='alice', password='password')
self.assertTrue(user is not None)
def test_backend_bad_login(self):
""" Test authentication using incorrect username/password"""
if 'ldap' in ENABLED_AUTH_SYSTEMS:
self._init_settings(
BIND_DN='uid=bob,ou=people,o=test',
BIND_PASSWORD='password',
USER_SEARCH=LDAPSearch(
"ou=people,o=test", ldap.SCOPE_SUBTREE, '(uid=%(user)s)'
)
)
user = self.backend.authenticate(username='maria', password='password')
self.assertTrue(user is None)
@override_settings(AUTH_LDAP_BIND_DN='uid=bob,ou=people,o=test',
AUTH_LDAP_BIND_PASSWORD='password',AUTH_LDAP_USER_SEARCH=LDAPSearch(
"ou=people,o=test", ldap.SCOPE_SUBTREE, '(uid=%(user)s)'
)
)
def test_ldap_view_login_with_bind_credentials(self):
""" Test if authenticates using the auth system login view """
if 'ldap' in ENABLED_AUTH_SYSTEMS:
response = self.client.post(reverse(ldap_views.ldap_login_view), {
'username' : 'bob',
'password': 'password'
}, follow=True)
self.assertEqual(self.client.session['user']['name'], 'Robert Barker')
self.assertEqual(self.client.session['user']['type'], 'ldap')
self.assertEqual(self.client.session['user']['info']['email'],'bob@example.com')
@override_settings(AUTH_LDAP_BIND_DN='uid=bob,ou=people,o=test',
AUTH_LDAP_BIND_PASSWORD='password',AUTH_LDAP_USER_SEARCH=LDAPSearch(
"ou=people,o=test", ldap.SCOPE_SUBTREE, '(uid=%(user)s)'
)
)
def test_ldap_view_login_with_bad_password(self):
""" Test if given a wrong password the user can't login """
if 'ldap' in ENABLED_AUTH_SYSTEMS:
response = self.client.post(reverse(ldap_views.ldap_login_view), {
'username' : 'john',
'password': 'passworddd'
}, follow=True)
self.assertEqual(response.status_code, 200)
self.assertFalse(self.client.session.has_key('user'))
def test_ldap_view_login_anonymous_bind(self):
"""
Test anonymous search/bind
See https://pythonhosted.org/django-auth-ldap/authentication.html#search-bind
"""
self._init_settings(
BIND_PASSWORD='',
USER_ATTR_MAP={'first_name': 'givenName', 'last_name': 'sn','email':'mail'},
USER_SEARCH=LDAPSearch(
"ou=people,o=test", ldap.SCOPE_SUBTREE, '(uid=%(user)s)'
)
)
user = self.backend.authenticate(username='alice', password='password')
self.assertEqual(user.username, 'alice')
self.assertEqual(user.first_name, 'Alice')
self.assertEqual(user.last_name, 'Adams')
self.assertEqual(user.email,'alice@example.com')
def test_ldap_bind_as_user(self):
"""
Test direct bind
See https://pythonhosted.org/django-auth-ldap/authentication.html#direct-bind
"""
self._init_settings(
USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test',
USER_ATTR_MAP={'first_name': 'givenName', 'last_name': 'sn','email':'mail'},
BIND_AS_AUTHENTICATING_USER=True,
USER_SEARCH=LDAPSearch(
"ou=people,o=test", ldap.SCOPE_SUBTREE, '(uid=%(user)s)'
)
)
user = self.backend.authenticate(username='alice', password='password')
self.assertEqual(user.username, 'alice')
self.assertEqual(user.first_name, 'Alice')
self.assertEqual(user.last_name, 'Adams')
self.assertEqual(user.email,'alice@example.com')
def test_logout(self):
""" test logging out using the auth system logout view """
if 'ldap' in ENABLED_AUTH_SYSTEMS:
response = self.client.post(reverse(views.logout), follow=True)
self.assertContains(response, "not logged in")
self.assertNotContains(response, "alice")
...@@ -9,8 +9,6 @@ from django.conf.urls import * ...@@ -9,8 +9,6 @@ from django.conf.urls import *
from views import * from views import *
from auth_systems.password import password_login_view, password_forgotten_view from auth_systems.password import password_login_view, password_forgotten_view
from auth_systems.twitter import follow_view from auth_systems.twitter import follow_view
from auth_systems.ldapauth import ldap_login_view
urlpatterns = patterns('', urlpatterns = patterns('',
# basic static stuff # basic static stuff
...@@ -30,7 +28,4 @@ urlpatterns = patterns('', ...@@ -30,7 +28,4 @@ urlpatterns = patterns('',
# twitter # twitter
(r'^twitter/follow', follow_view), (r'^twitter/follow', follow_view),
#ldap
(r'^ldap/login', ldap_login_view),
) )
...@@ -22,5 +22,3 @@ boto==2.27.0 ...@@ -22,5 +22,3 @@ boto==2.27.0
django-ses==0.6.0 django-ses==0.6.0
validate_email==1.2 validate_email==1.2
oauth2client==1.2 oauth2client==1.2
django-auth-ldap==1.2.7
mockldap==0.2.7
import ldap
import os, json import os, json
from django_auth_ldap.config import LDAPSearch, GroupOfNamesType
# a massive hack to see if we're testing, in which case we use different settings # a massive hack to see if we're testing, in which case we use different settings
import sys import sys
TESTING = 'test' in sys.argv TESTING = 'test' in sys.argv
...@@ -135,8 +134,8 @@ TEMPLATE_DIRS = ( ...@@ -135,8 +134,8 @@ TEMPLATE_DIRS = (
) )
INSTALLED_APPS = ( INSTALLED_APPS = (
'django.contrib.auth', # 'django.contrib.auth',
'django.contrib.contenttypes', # 'django.contrib.contenttypes',
'djangosecure', 'djangosecure',
'django.contrib.sessions', 'django.contrib.sessions',
#'django.contrib.sites', #'django.contrib.sites',
...@@ -202,7 +201,7 @@ HELIOS_VOTERS_EMAIL = True ...@@ -202,7 +201,7 @@ HELIOS_VOTERS_EMAIL = True
HELIOS_PRIVATE_DEFAULT = False HELIOS_PRIVATE_DEFAULT = False
# authentication systems enabled # authentication systems enabled
#AUTH_ENABLED_AUTH_SYSTEMS = ['password','facebook','twitter', 'google', 'yahoo','ldap'] #AUTH_ENABLED_AUTH_SYSTEMS = ['password','facebook','twitter', 'google', 'yahoo']
AUTH_ENABLED_AUTH_SYSTEMS = get_from_env('AUTH_ENABLED_AUTH_SYSTEMS', 'google').split(",") AUTH_ENABLED_AUTH_SYSTEMS = get_from_env('AUTH_ENABLED_AUTH_SYSTEMS', 'google').split(",")
AUTH_DEFAULT_AUTH_SYSTEM = get_from_env('AUTH_DEFAULT_AUTH_SYSTEM', None) AUTH_DEFAULT_AUTH_SYSTEM = get_from_env('AUTH_DEFAULT_AUTH_SYSTEM', None)
...@@ -238,25 +237,6 @@ CAS_ELIGIBILITY_REALM = get_from_env('CAS_ELIGIBILITY_REALM', "") ...@@ -238,25 +237,6 @@ CAS_ELIGIBILITY_REALM = get_from_env('CAS_ELIGIBILITY_REALM', "")
CLEVER_CLIENT_ID = get_from_env('CLEVER_CLIENT_ID', "") CLEVER_CLIENT_ID = get_from_env('CLEVER_CLIENT_ID', "")
CLEVER_CLIENT_SECRET = get_from_env('CLEVER_CLIENT_SECRET', "") CLEVER_CLIENT_SECRET = get_from_env('CLEVER_CLIENT_SECRET', "")
# ldap
# see configuration example at https://pythonhosted.org/django-auth-ldap/example.html
AUTH_LDAP_SERVER_URI = "ldap://localhost" # replace by your Ldap URI
AUTH_LDAP_BIND_DN = "cn=read-only-admin,dc=example,dc=com"
AUTH_LDAP_BIND_PASSWORD = "password"
AUTH_LDAP_USER_SEARCH = LDAPSearch("dc=example,dc=com",
ldap.SCOPE_SUBTREE, "(uid=%(user)s)"
)
# Populate the Django user from the LDAP directory.
AUTH_LDAP_USER_ATTR_MAP = {
"first_name": "givenName",
"last_name": "sn",
"email": "mail",
}
AUTH_LDAP_BIND_AS_AUTHENTICATING_USER = True
AUTH_LDAP_ALWAYS_UPDATE_USER = False
# email server # email server
EMAIL_HOST = get_from_env('EMAIL_HOST', 'localhost') EMAIL_HOST = get_from_env('EMAIL_HOST', 'localhost')
EMAIL_PORT = int(get_from_env('EMAIL_PORT', "2525")) EMAIL_PORT = int(get_from_env('EMAIL_PORT', "2525"))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment