diff --git a/helios_auth/auth_systems/__init__.py b/helios_auth/auth_systems/__init__.py
index 5a0e9233ba4df89067688283e90649aef4f1ae70..aaaddb56b6b5a29d4a414b4c34b2ba4a11278085 100644
--- a/helios_auth/auth_systems/__init__.py
+++ b/helios_auth/auth_systems/__init__.py
@@ -2,6 +2,9 @@
 AUTH_SYSTEMS = {}
 
 import twitter, password, cas, facebook, google, yahoo, linkedin, clever
+import ldapauth
+
+
 AUTH_SYSTEMS['twitter'] = twitter
 AUTH_SYSTEMS['linkedin'] = linkedin
 AUTH_SYSTEMS['password'] = password
@@ -10,6 +13,7 @@ AUTH_SYSTEMS['facebook'] = facebook
 AUTH_SYSTEMS['google'] = google
 AUTH_SYSTEMS['yahoo'] = yahoo
 AUTH_SYSTEMS['clever'] = clever
+AUTH_SYSTEMS['ldap'] = ldapauth
 
 # not ready
 #import live
diff --git a/helios_auth/auth_systems/ldapauth.py b/helios_auth/auth_systems/ldapauth.py
new file mode 100644
index 0000000000000000000000000000000000000000..4e201f94ce2fef763c8891ea3ca57240fac76fb9
--- /dev/null
+++ b/helios_auth/auth_systems/ldapauth.py
@@ -0,0 +1,113 @@
+# -*- 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
+
diff --git a/helios_auth/auth_systems/ldapbackend/__init__.py b/helios_auth/auth_systems/ldapbackend/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/helios_auth/auth_systems/ldapbackend/backend.py b/helios_auth/auth_systems/ldapbackend/backend.py
new file mode 100644
index 0000000000000000000000000000000000000000..ef1930dcb81b3be2c052d0b6682f1a08ab3f7998
--- /dev/null
+++ b/helios_auth/auth_systems/ldapbackend/backend.py
@@ -0,0 +1,28 @@
+from django.conf import settings
+
+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 but naturally return just a set
+        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 settings.AUTH_LDAP_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
diff --git a/helios_auth/media/login-icons/ldap.png b/helios_auth/media/login-icons/ldap.png
new file mode 100644
index 0000000000000000000000000000000000000000..86f7807cbcf9f8d5add2c9450a1cf74b30ff1cb6
Binary files /dev/null and b/helios_auth/media/login-icons/ldap.png differ
diff --git a/helios_auth/tests.py b/helios_auth/tests.py
index f07f309fb5176007ca67a25ce14c712efc33af35..9b097cc97e0a346e3d13da87f1eb9156f1ee3094 100644
--- a/helios_auth/tests.py
+++ b/helios_auth/tests.py
@@ -13,6 +13,7 @@ from django.test import TestCase
 from django.core import mail
 
 from auth_systems import AUTH_SYSTEMS
+from helios_auth import ENABLED_AUTH_SYSTEMS
 
 class UserModelTests(unittest.TestCase):
 
@@ -128,3 +129,43 @@ class UserBlackboxTests(TestCase):
         self.assertEquals(len(mail.outbox), 1)
         self.assertEquals(mail.outbox[0].subject, "testing subject")
         self.assertEquals(mail.outbox[0].to[0], "\"Foobar User\" <foobar-test@adida.net>")
+
+
+import auth_systems.ldapauth as ldap_views
+
+
+class LDAPAuthTests(TestCase):
+    """
+    These tests relies on OnLine LDAP Test Server, provided by forum Systems:
+    http://www.forumsys.com/tutorials/integration-how-to/ldap/online-ldap-test-server/
+    """
+
+    def setUp(self):
+        """ set up necessary django-auth-ldap settings """
+        self.password = 'password'
+        self.username = 'euclid'
+
+    def test_backend_login(self):
+        """ test if authenticates using the backend """
+        if 'ldap' in ENABLED_AUTH_SYSTEMS:
+            from helios_auth.auth_systems.ldapbackend import backend
+            auth = backend.CustomLDAPBackend()
+            user = auth.authenticate(self.username, self.password)
+            self.assertEqual(user.username, 'euclid')
+
+    def test_ldap_view_login(self):
+        """ test if authenticates using the auth system login view """
+        if 'ldap' in ENABLED_AUTH_SYSTEMS:
+            resp = self.client.post(reverse(ldap_views.ldap_login_view), {
+                'username' : self.username,
+                'password': self.password
+                }, follow=True)
+            self.assertEqual(resp.status_code, 200)
+
+    def test_logout(self):
+        """ test if logs 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, "euclid")
+
diff --git a/helios_auth/urls.py b/helios_auth/urls.py
index e4dca398503d1e2f802fd4811330b66b9020a1a9..810d4f8f9e054bd413687e1cbde6af05c34f9bf7 100644
--- a/helios_auth/urls.py
+++ b/helios_auth/urls.py
@@ -9,6 +9,8 @@ from django.conf.urls import *
 from views import *
 from auth_systems.password import password_login_view, password_forgotten_view
 from auth_systems.twitter import follow_view
+from auth_systems.ldapauth import ldap_login_view
+
 
 urlpatterns = patterns('',
     # basic static stuff
@@ -28,4 +30,7 @@ urlpatterns = patterns('',
 
     # twitter
     (r'^twitter/follow', follow_view),
+
+    #ldap
+    (r'^ldap/login', ldap_login_view),
 )
diff --git a/requirements.txt b/requirements.txt
index 2cc4eb872cc1522a3d333dceee03caf92aa9d8d9..eb774f3c76615017da3351d362d8ed7b56a6687f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -22,3 +22,4 @@ boto==2.27.0
 django-ses==0.6.0
 validate_email==1.2
 oauth2client==1.2
+django-auth-ldap==1.2.7
diff --git a/settings.py b/settings.py
index f1e2ab28b09a12f6e826af7d676aa31f06f6575c..2f440d511388492d26cbb67c279012fb0447b3d0 100644
--- a/settings.py
+++ b/settings.py
@@ -1,6 +1,7 @@
-
+import ldap
 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
 import sys
 TESTING = 'test' in sys.argv
@@ -133,8 +134,8 @@ TEMPLATE_DIRS = (
 )
 
 INSTALLED_APPS = (
-#    'django.contrib.auth',
-#    'django.contrib.contenttypes',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
     'djangosecure',
     'django.contrib.sessions',
     #'django.contrib.sites',
@@ -206,7 +207,7 @@ HELIOS_VOTERS_EMAIL = True
 HELIOS_PRIVATE_DEFAULT = False
 
 # authentication systems enabled
-#AUTH_ENABLED_AUTH_SYSTEMS = ['password','facebook','twitter', 'google', 'yahoo']
+#AUTH_ENABLED_AUTH_SYSTEMS = ['password','facebook','twitter', 'google', 'yahoo','ldap']
 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)
 
@@ -242,6 +243,27 @@ CAS_ELIGIBILITY_REALM = get_from_env('CAS_ELIGIBILITY_REALM', "")
 CLEVER_CLIENT_ID = get_from_env('CLEVER_CLIENT_ID', "")
 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://ldap.forumsys.com" # 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_GROUP_TYPE = GroupOfNamesType(name_attr="cn")
+AUTH_LDAP_FIND_GROUP_PERMS = True
+AUTH_LDAP_BIND_AS_AUTHENTICATING_USER = True
+AUTH_LDAP_CACHE_GROUPS = True
+AUTH_LDAP_GROUP_CACHE_TIMEOUT = 3600
+AUTH_LDAP_ALWAYS_UPDATE_USER = False
+
 # email server
 EMAIL_HOST = get_from_env('EMAIL_HOST', 'localhost')
 EMAIL_PORT = int(get_from_env('EMAIL_PORT', "2525"))