Integrate LDAP Authentication with Flask

Integrate LDAP Authentication with Flask

Integrate LDAP Authentication with Flask

This article is aimed at developers who are interested to integrate LDAP Authentication with Flask. In the following example, I will start with an overview of LDAP technology followed by the code that explains to integrate LDAP with Flask Web Application.


1. LDAP Authentication

We will begin the journey by understanding LDAP authentication. Directory services are a critical part of any identity infrastructure. A popular choice for many identity projects is LDAP. I’m not going to give a comprehensive guide to LDAP in this article. I will be giving an overview of the technology.

An authentication method is a process of confirming an identity.

In the case of an application, a user is given a username and a secret security token also known as a password and uses them to verify their identity on the application itself. There are several authentication methods and types, used for different types of applications such as API,  intranet.

LDAP a short form for Lightweight Directory Access Protocol is an open standard described currently by RFC4511 . LDAP’s purpose is to implement a distributed information directory over the IP. This directory normally contains information related to users, groups, and even devices. It has a fixed schema describing each object’s attributes, however, this schema can be changed using LDIF( LDAP Data Interchange Format).

LDAP is usually based on the idea of a tree data structure ( Yes, you are right very similar to a family tree).  Look at the below namespace for an example company.

LDAP namespace example

LDAP namespace example

The very first level is called the root node which consists of one entry (dc=example, dc=com) where dc stands for domain component. The second level consists of two entries ( ou=groups and ou=people)  where ou stands for an organizational unit. It is pretty much similar to the file system folder concept. The third level contains the leaf entries with the actual data. In our example, we have two entries for two groups and two people.

The DN (Distinguished Name) for an entry can be known by starting from the entry in question and traversing up the tree until you hit the root, for example, uid=roger,ou=people,dc=example,dc=com.

To summarize, the DC phrase is the domain component, and it identifies the domain where the user is (an LDAP directory can have trees of domains and subdomains). In our example, the domain is example.com. The phrase OU refers to the organizational unit where the user is, and CN is its common name.

Alright, now I wanted to touch base on the basics LDAP protocol.

LDAP protocol sequence example

LDAP protocol sequence example

LDAP is a client-server message-oriented protocol not a simple text-based protocol like HTTP. The LDAP implementation has various operations, such as adding users, searching, deleting, modifying, and so on. The scope/interest of this article is only for Bind and Search operations.

Finally, the two most common LDAP services are Microsoft Active Directory (You have to pay for this) and OpenLDAP (As the name suggested it’s open-source).


2. Getting Ready With LDAP Server

In this section, I will walk you through the installation of the LDAP Server locally. If you already have an LDAP server that you can access, feel free to skip the LDAP setup instructions in this section.

To get the LDAP server locally installed you need to have access to Docker and I’m going to make a fair assumption that you have some knowledge of Docker. Docker can be installed from here.

The reason we need Docker is that it is the easiest way to spin up a demo LDAP Server locally. Open up your terminal and run the below command and wait for the process to complete. Refer to the screenshot below.

LDAP server installation on Windows

LDAP server installation on Windows

Now, let’s test the server by searching for an example user with the username and password as admin and admin, as follows.

LDAP server testing

LDAP server testing

The successful execution of the preceding command indicates that the LDAP server is running and is ready for our use.


3. Python LDAP3

LDAP3 server is a modern and more pythonic way of accessing LDAP.

We need to install the python package that will help us talk to LDAP. We can do it using the python package installer.

In order to use LDAP with Python we need to import the Server and the Connection object, and any additional constant we will use in our LDAP.

As you might remember from the LDAP Protocol diagram the authentication operation is called Bind. A bind can be performed in 3 different ways:

  1. Anonymous Bind – A public access where the password is not required.
  2. Simple Password Bind – Provide username and credentials that the LDAP server uses to determine your authorization level.
  3. Simple Authentication and Security Layer (SASL) –  Provide username and credentials that the LDAP server uses to determine your authorization level.

We will be making a simple password bind as below.

In case your server is commercial and encrypted then you can make a connection to the server using the below code.

With LDAP3 we can perform CRUD operations as well like Create user/groups, Read users/groups, Update groups/users, and even Delete users or groups.

** Note: Admin user is very similar to the root user in Linux/Unix with all the privileges. Just for demonstration purposes only I have used admin users and I highly recommend not to use or share the admin password.


4. Integration With Flask Web Application

Flask is very simple to use, but it supports many extensions that are useful in professional web development. It’s my personal favorite among Python web frameworks because it balances ease of use with a rich feature set.

The flask package also includes the jinja2 template library that is quite powerful with a very rich set of features.

First thing first let us set up the app like below and then we will go into details.

 

Time to discuss the components in detail before we go and run it to see LDAP validation. We will first discuss the design steps that are being implemented. The design is pretty simple and I will do my best to explain it in that way.

4a). Design Steps

  1. The user will initiate the flask web application through the URL which displays the login form and the button to log in.
  2. Upon clicking the button the App will do an LDAP validation.
  3. If the User and credentials match in the server the user will see a success message.
  4. If the user validation fails then we will display the error page.

4b). Components: Templates

I will be using a couple of templates simple enough for this demonstration purpose. Well, don’t get too harsh on me with the naming conventions, I have used the naming conventions that are more suitable for the explanation purpose. However, these are not the right naming conventions for real production use and I do know that, feel free to change it to your standards.

login.html

This is our home page which the user uses to enter his credentials for authentication. I have not put in a lot of fancy stuff into this just the login form to go along with the button that the user is expected to submit to authenticate.

In this template, we have used Jinja to render fields from the Flask form stored in the /forms directory. The username and password fields are rendered from the form. Another interesting note in this template is the use of CSRF (Cross Site Request Forgery).

We have protected our web app from the CSRF attack, so we need to use it in all our forms just to make sure we are not be attacked by anonymous request.

Apart from the above couple of points, there is not much to explain just boring bootstrap content integration with the Flask form.

Success.html

Upon the successful LDAP authentication, the user is directed to this template. It justs displays the success message.

error.html

Upon the un-successful LDAP authentication, the user is directed to this error template. The error message as to why the LDAP Bind had failed will be displayed on this page.  Again here we have used the Jinja2 variable to display the error message.

Upon the LDAP authentication failure, the error message is captured in the error_message variable which is then sent to this template.


4c). Components: views

global_ldap_authentication.py

The LDAP3 function that was discussed in detail in the above section will go in here. I’m using the local LDAP server to authenticate so the below code reflects the function with no encryption.


4d). Components: forms

LoginForm.py

The LoginForm is a simple flask form with a couple of fields i.e. Username and Password. The values in these fields are mandatory and cannot be empty.


4e). Components: manage.py

If you are experienced with Flask or Django, you might remember that we typically work with the manage.py file when we’d like to run project-wide tasks, such as launching the server or applying database migrations.

Below is my version of manage.py.


4f). Components: main/__init.py__

This is the main configuration file that will be initiated by Flask. I have set the template and the root path here. Please change them as per your directory setup.


4g). Components: app.py

The logic in the app.py is very simple. First, we import the form, LDAP authentication function. We then configure the route /login.

In this route, we capture the username and password entered in the front end form and send them to the  global_ldap_authentication function for validation.

The final step in this route is to display one of the success or error templates based on the return message from the LDAP authentication function.


5. Final Step – Executing The Code

It is time now to initiate the Flask App. Once the APP is initiated, it’s time to open the browser and hit the URL – “http://127.0.0.1:5000/login”.

I will show you two scenarios where the user enters :

  1. Correct Credentials.
  2. Wrong credentials.

 

5a.) LDAP Authentication with correct credentials.

The username is “admin” and the password is “admin”.

LDAP authentication with FLask home page

LDAP authentication with FLask home page

LDAP authentication with FLask success

LDAP authentication with FLask success


5b.) LDAP Authentication with In-correct credentials.

The username is “admin” and the password is “A wrong credential”.

LDAP authentication with FLask failed

LDAP authentication with FLask failed


If you liked this article and if it helped you in any way, feel free to like it and subscribe to this website for more tutorials.

If you believe this article will be of big help to someone, feel free to share.

About the author

Stay Informed

It's important to keep up
with industry - subscribe!

Stay Informed

Looks good!
Please enter the correct name.
Please enter the correct email.
Looks good!

Related articles

Uploading Files To Amazon S3 With Flask Form – Part1 – Uploading Small Files

This article is aimed at developers who are interested to upload small files to Amazon S3 using Flask Forms. In the following tutorial, I will start ...

Email Support with Flask

This article is aimed at developers who are interested in implementing email support with Flask. In the following example, I will start with an ...

Web development with Flask framework illustrated an address book project

This is a sample software development project which is to showcase how to develop a web application utilizing Linux, Apache, SQLite and Python ...

7 comments

The Haag April 28, 2021 at 3:01 pm
0

What’s stopping someone from typing in the next route, so say for example your app will launch with /upload you can just skip the login page, how can you prevent that?

The Haag May 4, 2021 at 3:13 am
0

The CSRF session token is missing.

 
The Haag May 4, 2021 at 5:09 am
0

Okay, so the base search doesnt look for samaccountname thats why it was failing to login. You dont have the entry for external ldap servers what context to use.

Paulin KONAN June 1, 2021 at 5:28 pm
0

Something goes wrong with this tutorial. it seems you have forgotten something. Do you think you could share the code source with us, using GitHub for instance.

best regards

satyr0909 June 2, 2021 at 9:57 am
0

Hi I find the tutorial is good but there are some errors in the presented code.

so to make the life easiear for those who will give it a try here is the correction for the first login snippet
with the simple connection to LDAP Server, without the TLS:

wrong: -> # user
user = f’cn={ldap_user_name},root_dn’

right: -> user = f’cn={ldap_user_name},{root_dn}’

satyr0909 June 2, 2021 at 3:07 pm
0

One needs to import a couple of more modules to make the ldap authentication with TLS work but it works as well, so the tutorial is good!

Here how the imports from the authentication partshould look to make things going with tls 😉 … :

#!/usr/bin/env python
import sys
sys.path.insert(0,’/usr/local/lib/python2.7/dist-packages’)

# … please notice the SIMPLE auth method was missing but is
# … needed should you not use NTLM as authentication method
# … and you will probably need to enlist the NTLM should you really use it
# … as auth method inside your OpenLDAP domain subtree…
#
from ldap3 import Server, Connection, ALL, SIMPLE, NTLM, SUBTREE
from ldap3.core.exceptions import LDAPException, LDAPBindError

# … for tls actions:
#
import ssl
from ldap3.core.tls import Tls

 
juliano duarte July 26, 2021 at 5:48 pm
0

Hello,

I’m trying to follow this guide but I received this message:

jinja2.exceptions.UndefinedError: the template ‘includes/_formhelpers.html’ (imported on line 20 in ‘login.html’) does not export the requested name ‘render_field’

Please, what is _formhepers and formmsg content?

Best regards

Sign in

Forgot password?

Or use a social network account

 

By Signing In \ Signing Up, you agree to our privacy policy

Password recovery

You can also try to

Or use a social network account

 

By Signing In \ Signing Up, you agree to our privacy policy