diskusi.tech (beta) Community

loading...

Implementing SSO With Django-CAS-NG and JWT.

andhikayusup profile image andhikayusup Updated on ・3 min read

In this digital world, we need to have an account for each website to get full access to what they are offering. But, the internet is full of hackers and irresponsible people. Therefore, we need to set up an identification method so that you can keep bad people out. The basic and common way to secure an online account is using a password. But, there are alternative ways to enable authentication to choose from, for example, Token Based Authentication.

Token-based authentication requires a user to log in to the systems using their username/password to gain an access token. This token enable user to access some/all functionalities that have been issued for. If a user manages to log out or their token is expired, the system will invalidate the token and the user has to re-log in to update their token.

JWT

One of the well-known Token-based Authentication is JSON Web Tokens (JWT). JWT claims to implement industry-standard RFC7519 published by Internet Engineering Task Force in 2015. Another Token-Based Authentication you can use is Simple Web Token (SWT) and Security Assertion Markup Language Token (SAML). The main differences between these authentication methods are JWT is JSON-based whereas SWT is HTML-Based and SAML is XML-Based.

Central Authentication Service

If your company/institution has a lot of independent services, you might want to implement CAS. Central Authentication Service (CAS) is a web protocol for Single Sign-On (SSO) Methods. This practice allows users to have one account for many different services. So far, this protocol has 3 different version. The newest version is CAS 3.0 and you can read the documentation here

There is already a library that implement CAS protocol using Django that you can use. django-cas-ng provide wrapper function to let you easily using CAS. This library offers many features to support CAS 1.0/2.0/3.0 for Django 2.0/3.0. You can refer to this documentation for the guide and configuration.

Setup

For this guide, I am going to implement login/logout features with SSO Universitas Indonesia and JWT. The idea is we redirect our user into SSO UI to log in. Then, SSO Server returns the user's credential. Those credentials are saved to our server database. Last, JWT Token is generated based on the user's credentials so that the user's client use it to access our main product functionalities.

To be able to follow this guide you need to install some dependencies:

  • Python 3.6
  • Django 3.0
  • DRF 3.12

You will also need to install core library so that we can implement handling CAS and JWT.

To implement CAS SSO features, you will need to install django-cas-ng using this command:

pip install django-cas-ng
Enter fullscreen mode Exit fullscreen mode

To implement Token-based Authentication, you will need to install djangorestframework-jwt library using this command:

pip install djangorestframework_jwt
Enter fullscreen mode Exit fullscreen mode

Guide

First we need to build Profile Model first to save user's credentials returned by SSO.

class Profile(models.Model):
    """User Profile model."""

    user = models.OneToOneField(User, on_delete=models.CASCADE)
    org_code = models.CharField("kode organisasi", max_length=11, blank=True)
    role = models.CharField("peran pengguna", max_length=128, blank=True)
    npm = models.CharField("Nomor Pokok Mahasiswa", max_length=10, blank=True)
    faculty = models.CharField("fakultas", max_length=128, blank=True)
    study_program = models.CharField("program studi", max_length=128, blank=True)
    educational_program = models.CharField(
        "program pendidikan", max_length=128, blank=True
    )

    class Meta:
        verbose_name = "profil"
        verbose_name_plural = verbose_name

    def __str__(self):
        """Return username of the user."""
        return self.user.username
Enter fullscreen mode Exit fullscreen mode

Then, we write signals function to save user's credentials into Profile model.

@receiver(cas_user_authenticated)
def save_user_attributes(user, attributes, **kwargs):
    """Save user attributes from CAS into user and profile objects."""
    if not Profile.objects.filter(user=user).exists():
        if "nip" in attributes:
            save_lecturer_attr(user, attributes, **kwargs)
        else:
            save_student_attr(user, attributes, **kwargs)
Enter fullscreen mode Exit fullscreen mode

Next, we write views class to enable and redirect our user's to SSO Server. Then, return JWT Token to client's user.

class APILoginView(baseviews.LoginView):
    def successful_login(self, request: HttpRequest, next_page: str) -> HttpResponse:
        """
        This method is called on successful login.
        Overriden to render a page that send JWT token via postMessage
        if the page receive a message from one of the whitelisted origin.
        """
        user = request.user
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        data = {
            "token": token,
            "cors_origin_regex_whitelist": settings.CORS_ALLOWED_ORIGINS,
            "next_page": next_page,
        }

        return render(request, "data_to_frontend.html", data)
Enter fullscreen mode Exit fullscreen mode

Last, we should define our views class endpoint.

urlpatterns = [
    path("login/", APILoginView.as_view(), name="login"),
    path("logout/", APILogoutView.as_view(), name="logout")
]
Enter fullscreen mode Exit fullscreen mode

Result

Finally, our product has implemented SSO Server and JWT Authentication using the library. CAS has enable products to implement Single Sign-on and in the same time using Token-based Authentication as a means of identification between server and client.

Discussion

pic
Editor guide