Skip to content
Snippets Groups Projects
Commit 135ebc93 authored by Shirlei Chaves's avatar Shirlei Chaves
Browse files

Add ldap auth

parent fc7d532a
No related branches found
No related tags found
No related merge requests found
......@@ -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
......
# -*- 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.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
helios_auth/media/login-icons/ldap.png

4.65 KiB

......@@ -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")
......@@ -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),
)
......@@ -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
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"))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment