views:

844

answers:

4

On the intranet at my part time job (not IT related) there are various web applications that we use that do not require logging in explicitly. We are required to login to Windows obviously, and that then authenticates us some how.

I'm wondering how this is done? Without worrying about security TOO much, how would I go about authenticating a user to a web application, utilizing the windows login information? I'd be using Python (and Django).

Are there limitations on how this can be achieved? For instance, would a specific browser be required? Would the application and intranet backend have to be hosted at the same location or at least have to communicate? Or is it simply getting the users Windows credentials, and passing that to the authentication software of the web application?

A: 

I know that with ASP.Net based applications you can use Windows Authentication. See this link for information. Other than ASP.net, I don't know of any way to use Windows credentials (and I believe that there might not be another way).

Perchik
This functionality is not specific to ASP.Net; see the discussion of NTLM.
Charles Duffy
+1  A: 

Once upon a time Internet Explorer supported NTLM authentication (similar to Basic Auth but it sent cached credentials to the server which could be verified with the domain controller). It was used to enable single-signon within an intranet where everyone was expected to be logged into the domain. I don't recall the details of it and I haven't used it for ages. It may still be an option if it fits your needs.

Maybe someone more familiar with it may have more details.

See: NTLM Authentication Scheme for HTTP

The tricky part of using non-microsoft server framework is going to be talking with the necessary services to verify the credentials.

Mark Renouf
Do you think a .NET web service could be used for authentication which is passed to the Django app?
Josh Smeaton
You may wish to point to http://modntlm.sourceforge.net/
Charles Duffy
+1  A: 

From here:

-- Added to settings.py --

### ACTIVE DIRECTORY SETTINGS

# AD_DNS_NAME should set to the AD DNS name of the domain (ie; example.com)  
# If you are not using the AD server as your DNS, it can also be set to 
# FQDN or IP of the AD server.

AD_DNS_NAME = 'example.com'
AD_LDAP_PORT = 389

AD_SEARCH_DN = 'CN=Users,dc=example,dc=com'

# This is the NT4/Samba domain name
AD_NT4_DOMAIN = 'EXAMPLE'

AD_SEARCH_FIELDS = ['mail','givenName','sn','sAMAccountName']

AD_LDAP_URL = 'ldap://%s:%s' % (AD_DNS_NAME,AD_LDAP_PORT)


-- In the auth.py file --

from django.contrib.auth.models import User
from django.conf import settings
import ldap

class ActiveDirectoryBackend:

  def authenticate(self,username=None,password=None):
    if not self.is_valid(username,password):
      return None
    try:
      user = User.objects.get(username=username)
    except User.DoesNotExist:
      l = ldap.initialize(settings.AD_LDAP_URL)
      l.simple_bind_s(username,password)
      result = l.search_ext_s(settings.AD_SEARCH_DN,ldap.SCOPE_SUBTREE, 
               "sAMAccountName=%s" % username,settings.AD_SEARCH_FIELDS)[0][1]
      l.unbind_s()

      # givenName == First Name
      if result.has_key('givenName'):
        first_name = result['givenName'][0]
      else:
        first_name = None

      # sn == Last Name (Surname)
      if result.has_key('sn'):
        last_name = result['sn'][0]
      else:
        last_name = None

      # mail == Email Address
      if result.has_key('mail'):
        email = result['mail'][0]
      else:
        email = None

      user = User(username=username,first_name=first_name,last_name=last_name,email=email)
      user.is_staff = False
      user.is_superuser = False
      user.set_password(password)
      user.save()
    return user

  def get_user(self,user_id):
    try:
      return User.objects.get(pk=user_id)
    except User.DoesNotExist:
      return None

  def is_valid (self,username=None,password=None):
    ## Disallowing null or blank string as password
    ## as per comment: http://www.djangosnippets.org/snippets/501/#c868
    if password == None or password == '':
      return False
    binddn = "%s@%s" % (username,settings.AD_NT4_DOMAIN)
    try:
      l = ldap.initialize(settings.AD_LDAP_URL)
      l.simple_bind_s(binddn,password)
      l.unbind_s()
      return True
    except ldap.LDAPError:
      return False
GregD
I believe the question is related to Single Sign On support, not mere AD authentication.
Charles Duffy
A: 

To the best of my knowledge the only browser that automatically passes your login credentials is Internet Explorer. To enable this feature select "Enable Integrated Windows Authentication" in the advanced Internet options dialog under the security section. This is usually enabled by default.

The web server will have to have the Anonymous user permission removed from the web application and enable windows authentication option checked. Simply add the users you want to have access to the web application to the file/folder permissions.

I have only tried this with IIS so I'm not sure if it will work on other web servers.