Single Sign-On with Django and Keycloak
Contents
Introduction
User management is a fundamental aspect of web application development. While a local login is the simplest method to grant users access to resources, it comes with certain limitations. If users want to access multiple services using the same credentials, a centralized authentication system is necessary.
For a diverse user base (spanning different contexts such as industry specialists, academia, and various organizations or locations) a Single Sign-On (SSO) solution is essential. Well-known identity providers (IdPs) like GitHub1 in the tech world, ORCID2 for the scientific community, and the lesser-known DNF-AAI3 in German academia enable users to reuse their credentials across services.
In this article, we will focus on integrating Django with Keycloak4, an open-source Identity and Access Management (IAM) solution that simplifies the process of adding authentication to applications with minimal effort.
The diagram below illustrates how Django and Keycloak interact when implementing Single Sign-On.
- The End-User attempts to access resources from the Service Provider (SP), which requires authentication.
- The Identity Provider (IdP) manages user identities and handles authentication (e.g., via username and password). It issues authentication tokens for the End-User, which are then provided to the Service Provider.
- The Service Provider (SP) offers resources to registered End-Users. Instead of handling the login directly, the SP redirects the authentication process to an IdP. The SP then consumes and verifies the authentication tokens issued by the IdP.
Although Keycloak is an Identity Provider itself, it can also integrate5 with other Identity Providers, offering users various login options.
Keycloak
Python Integration
The python-keycloak
package6 provides access to the Keycloak API and is compatible with the latest Keycloak versions. To establish a connection, credentials can be obtained by configuring the admin-cli client in Keycloak.
In the Credentials tab, the Client Secret can be retrieved. Client permissions are managed under Service Account Roles, where roles must be assigned based on the required API actions.
The Python setup is straight forward:
|
|
|
|
An indication that a permission is missing is the following error message:
|
|
Django Integration
The django-allauth
package7 provides various authentication solutions for Django.
By configuring Keycloak as an OpenID Connect provider, user data associated with Keycloak are stored in a dedicated model (SocialAccount8), which is linked to Django’s user model.
With this setup, it becomes possible to retrieve the Keycloak user ID from the SocialAccount object associated with a Django user.
|
|
The obtained user id can be used with python-keycloak:
|
|
Use Cases
After integrating Keycloak as a login provider for Django and setting up a Python API for Keycloak, both can work together seamlessly. The following use cases demonstrate solutions to common issues.
Update Django User
Update the data in the SocialAccount model whenever a user logs in.
|
|
Update Keycloak User
Update a user’s data in Keycloak for a specific Django user. This example demonstrates how to update the user’s email address.
|
|
This can can be implemented in user.save()
or as a post-save signal.
Delete/Disable Keycloak User
Delete or disable a Keycloak user.
|
|
Reset Keycloak Password
Reset the user password by sending an email
The user will receive an email with a temporary link to reset their password.
|
|
Reset the user password by triggering a login action
The user has to change their password with the next login.
|
|
Logout Keycloak User with Django Logout
Logging out from Django does not automatically log the user out of Keycloak.
A common misconception is that logging out from Django also ends the session in Keycloak. To achieve this behavior, a logout signal must be sent to Keycloak.
|
|
Otherwise, the Keycloak session will remain active, and subsequent logins will not prompt for credentials. Users will automatically continue their previous session without being redirected to Keycloak or asked to log in again.
Conclusion
Enhancing Django’s login functionality can improve user convenience, but it also introduces additional complexity to the system’s architecture.
Django offers various login options, ranging from simple methods like email-based login (django-unique-user-email
9) to more complex systems (django-allauth
7).
Any changes to the login process should be thoughtfully evaluated to ensure they comply with standard web practices and are customized to meet the needs of the user base.
Supplements
Example Project
The GitHub project ublabs-django-keycloak-example provides a Django project derived from the official
django-allauth
example. The example is extended to support a self-hosted Keycloak as a openid-connect provider.
A description of the most important configuration steps are included as well as a demonstration video of the login process.
Keycloak User Login Flow
The basic OIDC Login flow is described by Keycloak10 as follows:
- A user connects to an application using a browser. […].
- The application redirects the browser to Keycloak for authentication.
- The application passes a callback URL as a query parameter in the browser redirect. Keycloak uses the parameter upon successful authentication.
- Keycloak authenticates the user and creates a one-time, short-lived, temporary code.
- Keycloak redirects to the application using the callback URL and adds the temporary code as a query parameter in the callback URL.
- The application extracts the temporary code and makes a background REST invocation to Keycloak to exchange the code for an identity and access and refresh token. […].
-
Authorizing OAuth apps. URL: https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps (Retrieved 2024-08-19) ↩︎
-
Sign In Using ORCID Credentials. URL: https://info.orcid.org/documentation/integration-guide/sign-in-using-orcid-credentials/ (Retrieved 2024-08-19) ↩︎
-
Authentication and authorization infrastructure for research and education communities in Germany. URL: https://www.aai.dfn.de/index.en.html (Retrieved 2024-08-19) ↩︎
-
OIDC auth flows - Keycloak Server Administration Guide (Version 25.0.2). URL: https://www.keycloak.org/docs/latest/server_admin/index.html#con-oidc-auth-flows_server_administration_guide (Retrieved 2024-07-25) ↩︎
-
Integrating identity providers - Keycloak Server Administration Guide (Version 25.0.2). URL: https://www.keycloak.org/docs/latest/server_admin/#_identity_broker (Retrieved 2024-08-19) ↩︎
-
python-keycloak. URL: https://github.com/marcospereirampj/python-keycloak (Retrieved 2024-08-01) ↩︎
-
django-allauth. URL: https://allauth.org/ (Retrieved 2024-08-01) ↩︎ ↩︎
-
SocialAccount Model. URL: https://github.com/pennersr/django-allauth/blob/main/allauth/socialaccount/models.py#L92 (Retrieved 2024-10-16) ↩︎
-
django-unique-user-email. URL: https://github.com/carltongibson/django-unique-user-email (Retrieved 2024-08-01) ↩︎
-
Keycloak Server Administration Guide (Version 25.0.2). URL: https://www.keycloak.org/docs/latest/server_admin/index.html#_oidc-auth-flows-authorization (Retrieved 2024-07-25) ↩︎
Last Modified on 2024-10-22.