Welcome to Django Keycloak’s documentation!

Testing with the Example project

The quickest way to experiment with this project is by running the example project. This project is setup using Docker compose.

Given you have installed Docker and Docker compose run:

$ cd example
$ docker-compose up

The project exists of a resource provider which mimics a web app and a resource provider which is only accessible by an API. Next to it is a Keycloak instance available which is backed by a Postgres database.

Once you have the containers running you can access it by navigating to: https://resource-provider.localhost.yarf.nl/ you can login with username: testuser and password: password. The admin is accessible at /admin with username: admin and password: password.

The Keycloak instance is available at: https://identity.localhost.yarf.nl/ the username of the admin user is admin and the password is password.

The API is available at: https://resource-provider-api.localhost.yarf.nl/ You probably don’t actually use this server or only for the admin. The admin is accessible at /admin with username: admin and password: password.

Setup for local user storage

By local user storage a User object get created for every logged in identity. This can be handy when you want to link objects to this User. If that’s not the case please read the scenario Setup for remote user.

Since this is the default behaviour for Django Keycloak you don’t have to configure any setting.

Important to point out the KEYCLOAK_OIDC_PROFILE_MODEL setting. This should contain django_keycloak.OpenIdConnectProfile (which is the case by default). The model to store the Open ID Connect profile is a swappable model. When configured to this model a foreign key to the configured Django User model is available.

# settings.py
KEYCLOAK_OIDC_PROFILE_MODEL = 'django_keycloak.OpenIdConnectProfile'

Setup for remote user

It’s not required to create a local User object for every logged in identity. If you don’t need a local user object you can setup the app to work with a remote user. This user behaves like Django’s User object but it is not a real one.

Note

For logging purposes Django admin only works with User objects which are stored in the database. So you cannot use this method to authenticate users for admin usage.

Warning

Set the configuration setting below before running the migrations!

Set the OIDC Profile model to the remote variant:

# your-project/settings.py
KEYCLOAK_OIDC_PROFILE_MODEL = 'django_keycloak.RemoteUserOpenIdConnectProfile'

Configure the remote user middleware:

MIDDLEWARE = [
    ...

    'django_keycloak.middleware.BaseKeycloakMiddleware',
    'django_keycloak.middleware.RemoteUserAuthenticationMiddleware',
]

By default the class django_keycloak.remote_user.KeycloakRemoteUser is used as user, this one will be available on the request when authenticated and will be returned when you access RemoteUserOpenIdConnectProfile.user. If you want another class (i.e. you need extra properties) you can configure this class using the setting KEYCLOAK_REMOTE_USER_MODEL:

KEYCLOAK_REMOTE_USER_MODEL = 'django_keycloak.remote_user.KeycloakRemoteUser'

Initial setup

Server configuration

First you have to add your Keycloak server. You can do this in the Django Admin.

_images/add-server.png

Note

When your application access the Keycloak server using a different url than the public one you can configure this URL as “internal url”. Django Keycloak will use that url for all direct communication but uses the standard server url to redirect users for authentication.

Realm configuration

After you have created a REALM and Client in Keycloak you can add these in the Django admin.

Note

Django-Keycloak supports multiple realms. However when you configure multiple realms you have to write your own middleware which selects the correct realm based on the request. The default middleware always selects the first realm available in the database.

_images/add-realm.png

After you have added the realm please make sure to run te following actions:

Tools

Refresh OpenID Connect .well-known

In the Django Admin you can apply the action “Refresh OpenID Connect .well-known” for a realm. This retrieves the .well-known content for the OpenID Connect functionality and caches this in the database. In this way it’s not required to fetch this file before each request regarding OpenID Connect to the Keycloak server.

_images/refresh_well_known.png

Refresh Certificates

This refreshes the cached certificates from the Keycloak server. These certificates are used for valiation of the JWT’s.

_images/refresh_certificates.png

Clear client tokens

While debugging client service account permissions it’s sometimes required to refresh te session in order to fetch the new permissions. This can be done with this action in the Django admin.

_images/clear_client_tokens.png

Migrating from Django Auth to Keycloak

There are some tools available which can help by migrating a running project to Keycloak.

Add user

A management command is available to create a Keycloak user based on a local one.

$ python manage.py keycloak_add_user --realm <insert realm name> --username <insert user name>

Note

In theory it would be possible to synchronize (hashed) passwords to Keycloak however Keycloak uses a 512 bit hash for pbkdf2_sha256 hashed passwords, Django generates a 256 bits hash. In that way passwords will not work when they are copied to Keycloak. The project includes a sha512 hasher (django_keycloak.hashers.PBKDF2SHA512PasswordHasher) which you can configure to hash passwords in a Keycloak-complient way.

# your-project/settings.py
PASSWORD_HASHERS = [
    'django_keycloak.hashers.PBKDF2SHA512PasswordHasher',
]

Permissions by roles

There are two ways of using permissions one by roles and the other one by resources/scopes. The roles method is the default one. In this method the available client roles are available as permissions in your Django Project.

Note

Please read synchronize_permissions if you want to synchronize all available permissions in your current project to roles in Keycloak.

Setup

Since this is the default method of handling permission you don’t have to configure anything. However it’s good to know that the KEYCLOAK_PERMISSIONS_METHOD is used to configure the way how permissions are interpreted.

# your-project/settings.py
KEYCLOAK_PERMISSIONS_METHOD = 'role'

Synchronize

This Django Admin action which can be triggered for a realm synchronizes all available permission to Keycloak. In keycloak the permissions will get registered as roles. These roles can be added to a user.

For this feature the service account should have the realm-management/manage-clients role assigned.

_images/keycloak_manage_clients.png

This only makes sense when you use the roles permission method. You can read about this at scenario: Permissions by roles.

Permissions by resources and scopes

Next to Permissions by roles you can also implement permissions by syncing Django models as resources in Keycloak and the default permissions in Django as scopes in Keycloak.

Setup

To configure Django Keycloak to make use of the Resource / Scope method of permission assigning add the following setting:

# your-project/settings.py
KEYCLOAK_PERMISSIONS_METHOD = 'resource'

Synchronization

In Keycloak enable “Remote Resource Management” for the client:

_images/keycloak_remote_resource_management.png

You can use the Django Admin action “Synchronize models as Keycloak resources” to synchronize models and scopes to Keycloak.

_images/synchronize_resources.png

An alternative is to run the Django management command keycloak_sync_resources:

$ python manage.py keycloak_sync_resources

Optionally you can supply a client to which the resources should be synchronized.

Usage

After synchronizing you can find the the models as resources and the default permissions as scopes:

Resources:

_images/keycloak_resources.png

Scopes:

_images/keycloak_scopes.png

From here you are able to configure your policies and permissions and assign them to users of groups using roles in Keycloak. Once assigned you get them back as permissions in Django where the policies are combined with the resources just like you are used to in the default Django permission system i.e. foo.add_bar or foo.change_bar.

Multi-tenancy

Django Keycloak supports multi tenancy by supporting multiple realms. The way to determine the currently active realm is set to the request in the middleware. In the project there is currently one middleware available. This is django_keycloak.middleware.BaseKeycloakMiddleware. This middleware add the first found Realm model to the request object.

# your-project/settings.py
MIDDLEWARE = [
    ...

    'django_keycloak.middleware.BaseKeycloakMiddleware',
]

If you want to support multiple reams you have to create your own middleware. There are several methods to determine the currently active realm. You can think of realm determination by:

  • Hostname
  • Environment variable
  • Selection during login
  • etc.

It’s up to you how the realm get determined and therefore it’s also up to you to write a proper middleware for it. The only think the middleware has to make the correct Realm model to the request as request.realm. This middleware has to be configured above other middlewares which have to be configured for authentication purposes.

Django Keycloak adds Keycloak support to your Django project. It’s build on top of Django’s authentication system. It works side-by-side with the standard Django authentication implementation and has tools to migrate your current users and permissions to Keycloak.

Features

  • Multi tenancy support
  • Permissions by roles or by resource/scope
  • Choose if you want to create a local User model for every logged in identity or not.

Read Testing with the Example project to quickly test this project.

Note

The documentation and the example project are all based on Keycloak version 3.4 since that is the latest version which is commercially supported by Red Hat (SSO).

Installation

Install requirement.

$ pip install git+https://github.com/Peter-Slump/django-keycloak.git

Setup

Some settings are always required and some other settings are dependant on how you want to integrate Keycloak in your project.

Add django-keycloak to your installed apps, add the authentication back-end, add the middleware, configure the urls and point to the correct login page.

# your-project/settings.py
INSTALLED_APPS = [
    ....

    'django_keycloak.apps.KeycloakAppConfig'
]

MIDDLEWARE = [
    ...

    'django_keycloak.middleware.BaseKeycloakMiddleware',
]

AUTHENTICATION_BACKENDS = [
    ...

    'django_keycloak.auth.backends.KeycloakAuthorizationCodeBackend',
]

LOGIN_URL = 'keycloak_login'
# your-project/urls.py
...

urlpatterns = [
    ...

    url(r'^keycloak/', include('django_keycloak.urls')),
]

Before you actually start using Django Keycloak make an educated choice between Setup for local user storage and Setup for remote user.

Then walk through the Initial setup to found out how to link your Keycloak instance to your Django project.

If you don’t want to take all that effort please read about Testing with the Example project

Usage

For requiring a logged in user you can just use the standard Django functionality. This also counts for enforcing permissions.

This app makes use of the Python Keycloak client