Central Authentication Service (CAS) implementation using Django microservices

Microservices are popular these days and a lot of companies tend to move from monolithic architecture to distributed ones.  I’ve just finished implementing CAS for Django microservices at BeSmart. I tried to find some tutorials on the subject, but didn’t find anything except for the official documentation on readthedocs.org, so I will try to make other devs’ lives a little bit easier.

Prerequisites

In this tutorial, I will be using Django framework for microservices. And then I will use django-mama-cas and django-cas-ng packages. So before beginning, make sure you go through the official documentation of the packages and get familiar with them.

django-mama-cas is CAS server package adapted to Django framework.

django-cas-ng is CAS client package adapted to Django framework.

The Central Authentication Service (CAS)

Before beginning, we need to understand what CAS is and what problems it solves.

The Wikipedia says: The Central Authentication Service (CAS) is a single sign-on protocol for the web. Its purpose is to permit a user to access multiple applications while providing their credentials (such as user id and password) only once. It also allows web applications to authenticate users without gaining access to a user’s security credentials, such as a password. The name CAS also refers to a software package that implements this protocol.

In other words, CAS consists of two parts – the server part and the client part. I have a very good analogy of what CAS is. Say, your are going to a live concert of your favorite band. So, your application you want the users to authenticate to using the CAS protocol is the concert itself. There are ticket-agents that sell and validate tickets to the concert. The ticket-agent is the CAS server that gives the users permissions to access your application and validates their access credentials. And of course, people that go to the concert are CAS clients that get tickets and go to the concert.

Django microservices with CAS

Say you are building online shopping web application. So microservices will probably go like django-shop, django-billing, django-auth.

django-shop will present the products to users.

django-billing will accept users’s money for the products.

django-auth will authorize users, so that they have access to other two microservices.

Django-shop and django-billing both need provide users with authentication interface. You do not want users to provide their login and password to the first app and then repeat the same when purchasing goods. You want users login one time and have access to all your microservices.

I will not explain how to create django projects. You can find tons of tutorials on the subject if you google it. Just create the above three projects using virtualenv and continue here.

So, we have two CAS clients (django-shop and django-billing) and one CAS server (django-auth).

 

Django-auth project.

We will setup django-auth project first. Activate the environment and then do the following:

pip install django-mama-cas                # install CAS server package

Add django-mama-cas package to the list of installed apps in your settings.py file.

INSTALLED_APPS = (
    # ...existing apps...
    'mama_cas',
)

Once added, run ./manage.py migrate to create the required database tables.

Now we need to setup urls:

urlpatterns = [
    # ...existing urls...
    url(r'', include('mama_cas.urls')),
]

This makes the CAS server available at the top level of your project’s URL (e.g.http://127.0.0.1:8000/login)

MAMA_CAS_ENABLE_SINGLE_SIGN_OUT = True

Now add the following setting to your settings.py file. This will make sure that when you logout from one microservice, the CAS server will send logout requests to the rest of microservices.

MAMA_CAS_SERVICES = [
    {
        'SERVICE': 'http://127.0.1.1:8000',
        'CALLBACKS': [
            'mama_cas.callbacks.user_name_attributes',
        ],
        'LOGOUT_ALLOW': True,
        'LOGOUT_URL': 'http://127.0.1.1:8000/accounts/callback',
    },
    {
        'SERVICE': 'http://127.0.2.1:8000',
        'CALLBACKS': [
            'mama_cas.callbacks.user_name_attributes',
        ],
        'LOGOUT_ALLOW': True,
        'LOGOUT_URL': 'http://127.0.2.1:8000/accounts/callback',
    },
 ]

This setting is important. MAMA_CAS_SERVICES setting contains the information about CAS clients that will be able to authenticate to the CAS server.

As you probably have noticed, the SERVICE setting contains 127.0.1.1 and 127.0.2.1 as hosts. It is important to keep hosts for every microservice different since the authentication cookies will be saved to hosts, not ports.

The LOGOUT_URL setting contains the url where a request will be sent when user logs out from any service connected to the CAS server.

That is it for the CAS server.

Django-shop project.

Now we will setup our CAS client Django project. Activate the corresponding environment and run the following command:

pip install django-cas-ng                # this will install CAS client

And add this app to the list of INSTALLED_APPS:

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django_cas_ng',
    ...
)

Also, we need to add it’s middleware to our settings.

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    ...
)

And in order to authenticate from CAS server, add AUTHENTICATION_BACKEND

AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.ModelBackend',
    'django_cas_ng.backends.CASBackend',
)

And finally, add the following settings.

CAS_SERVER_URL = '127.0.0.1:8000'
CAS_VERSION = '3'

CAS_SERVER_URL contains the url of the CAS server, so that this app know where to redirect when user wants to authenticate.

CAS_VERSION is the version of the CAS Protocol. We will use the third version since it is tested well by django-mama-cas and django-cas-ng packages.

Now go to the main urls file and add the following urls so that proper authentication form is loaded.

import django_cas_ng

url(r'^accounts/login$', django_cas_ng.views.login, name='cas_ng_login'),
url(r'^accounts/logout$', django_cas_ng.views.logout, name='cas_ng_logout'),
url(r'^accounts/callback$', django_cas_ng.views.callback, name='cas_ng_proxy_callback'),

It is clear what first two urls do, they just use login and logout views of the django-cas-ng package. The last url processes logout request that come from the CAS server. (Look at the LOGOUT_URL setting of the django-auth settings.

Once added, run ./manage.py migrate to create the required database tables.

Django-billing project.

Do the same as for django-shop project.

 

Conclusion

Hopefully, it did not took too much time. I would recommend you to look at the official documentation and check for other functionalities of these packages. Also, make yourself familiar with the CAS protocol itself so that you can build more with this protocol.

And do not be shy to ask question!

 

Advertisements

One thought on “Central Authentication Service (CAS) implementation using Django microservices

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s