Recommended·

Performing SAML SSO using JWT in Django

Performing SAML SSO authentication using JWT in Django. The step by step configuration.
Performing SAML SSO using JWT in Django

When the Django application needs to be separated into front-end and back-end, and you want to authenticate your calls to your other platforms/services, the stateless JWT in pair with Django Rest Framework is a good choice. But what if you want to integrate single sign-on/single log-out with the other applications which are using SAML? Moreover, your application may be Service Provider and Identity Provider at the same time.

SAML (Security Assertion Markup Language) is an open standard that allows you to perform single sign-on (SSO), namely secure log in to third-party applications using session from another application. That means you don’t need to enter your credentials to authenticate some sites (Service Providers) if you once logged in to the particular site (Identity Provider).

There are many libraries on the internet that allow us to easily integrate the Django authentication mechanism with the SAML, but all of them are based on the standard Django’s session-based authentication, but you can’t use that. Therefore, you need some adapter between JWT → SAML and vice versa SAML → JWT. Have a look at the illustration below:

Libraries used in the project:

  • djangorestframework – Rest framework
  • django-rest-framework-simplejwt – JWT Auth
  • djangosaml2 – SAML Service Provider
  • djangosaml2idp – SAML Identity Provider

Assuming that the SAML and metadata are configured properly, and you can perform SSO using Django and obtain a session. Let’s start from the part when the Django app acts as a Service Provider.

Django app as a Service Provider

First, you have to create view, to which the user will be redirected after SAML login:

Add this view to urls.py:

And to get redirected to this view, add this line to settings.py

What just happened? Basically, you obtained a JWT token for the authenticated (session-based) user, set it to the cookie, and deleted the session as you didn’t need it. It was easy, wasn't it?

To increase security, it’s better to store refresh and auth token in the httpOnly cookie instead of local storage (Be aware that this option closes the XSS vulnerability but opens the CSRF). At the time of writing, library Django-rest-framework-simplejwt doesn’t deliver storing tokens in the cookies, this functionality can be found in one of the pull requests. If you don’t want to use cookie storage, as an option, you can just add these tokens as URL params to the redirected URL, instead of setting them into cookies.

Django app as an Identity ProviderIn

this case, things are even easier. Let’s say you have logged in into your site, you have set JWT cookie, and you want to perform IDP-initiated login to the different site. And here you are stuck again because to perform an IDP-initiated login, you have to have a Django session (SSOInitView is using LoginRequiredMixin), but as we are using stateless tokens, from the perspective of Django views, you are not authenticated:

This time you have to do the opposite: Authenticate Django view using JWT token. To implement this in the clean and reusable way, let’s create the view decorator:

Also you can reuse this decorator to decorate the SLO view in the same way.

Conclusion

As you can see, The solution turned out to be easier than it seemed at first. And if the library doesn't provide needed functionality out of the box, it doesn't mean that you have to dig and rewrite everything. You can just do the adapter:)

Need Help with This?

Building something similar or facing technical challenges? We've been there.

Let's talk — no sales pitch, just honest engineering advice.