DEV Community

Cover image for How to implement OIDC authentication with Django and Okta
Hesbon
Hesbon

Posted on • Edited on

How to implement OIDC authentication with Django and Okta

This article details how to implement OIDC authentication using Django and mozilla-django-oidc with Okta as our identity provider

Introduction

  • OpenID Connect (OIDC) is a protocol that allows a user to authenticate with a third-party service and then use that authentication to sign in to other services. OIDC is built on top of the OAuth2 protocol and adds an additional layer of authentication on top of it. This allows a user to not only grant permission for a service to access their data, but also to verify their identity.

  • Django is a popular web framework for building web applications in Python. It includes a robust authentication system that can be easily configured to support OIDC.

  • Mozilla-django-oidc is an open-source library that adds OIDC support to Django, making it easy to authenticate users with an OIDC provider.

  • Okta is an identity and access management platform that enables organizations to securely connect users to technology. It supports the OIDC protocol, which allows users to be authenticated and receive information about their identity and access rights across different applications.

Note: Here's a link to the final project on Github.

OIDC Oauth2 authentication using Django and mozilla-django-oidc with Okta

Tutorial 1: How to implement OIDC authentication with Django and Okta

Tutorial 2: Customizing mozilla-django-oidc

How to set up the project

Features

  • python 3.10
  • poetry as dependency manager

PROJECT SETUP

  • clone the repository
git clone https://github.com/Hesbon5600/oidc-connect.git
Enter fullscreen mode Exit fullscreen mode
  • cd into the directory
cd oidc-connect
Enter fullscreen mode Exit fullscreen mode

create environment variables

On Unix or MacOS, run:

cp .env.example .env
Enter fullscreen mode Exit fullscreen mode

You can edit whatever values you like in there.

Note: There is no space next to '='

On terminal

source .env
Enter fullscreen mode Exit fullscreen mode

VIRTUAL ENVIRONMENT


To Create:

make env
Enter fullscreen mode Exit fullscreen mode

To Activate:

source ./env/bin/activate
Enter fullscreen mode Exit fullscreen mode

Installing dependencies:

make install
Enter fullscreen mode Exit fullscreen mode

MIGRATIONS - DATABASE


Make migrations

make makemigrations
Enter fullscreen mode Exit fullscreen mode

THE APPLICATION


run application

make run
Enter fullscreen mode Exit fullscreen mode





Part 1 : Setting up an Okta Account

To set up an Okta account for our OIDC account, follow these steps:

  1. Go to the Okta developer website and create an account. Use your gmail account in order to get a free developer account.

  2. After you have created your Okta account, log in to the Okta dashboard.

  3. Click on the Applications tab in the left menu and then click on the Create App Integration button.Create App Integration

  4. Choose OIDC - OpenID Connect Sign-in method and Select an Application type of Web Application, then click Next
    Sign-in method Selection

  5. Enter an App integration name (e.g oidc-connect).
    Enter the Sign-in redirect URIs for local development, such as http://localhost:8080/authorization-code/callback.

  6. Optionally Enter the Sign-out redirect URIs for both local development, such as http://localhost:8080/signout/callback.
    App integration Details

  7. In the Assignments section, define the type of Controlled access for your app. Select the Everyone group for now. For more information, see the Assign app integrations topic in the Okta product documentation.
    App integration Access

  8. Click Save to create the app integration. The configuration pane for the integration opens after it's saved.

Note: Keep this pane open as you copy some values when configuring your app.


Part 2.0 : Setting up the Django application

To set up a Django application, follow these steps:

  1. Install Django by running the following command: ```bash

pip install django


2. Create a new Django project by running the following command:```bash


django-admin startproject oidc_app


Enter fullscreen mode Exit fullscreen mode
  1. This will create a new directory called "oidc_app" with the basic structure for a Django project. Change into the new directory by running the following command:```bash

cd oidc_app

4. Apply the default database migrations using the command.```bash


python manage.py migrate


Enter fullscreen mode Exit fullscreen mode
  1. Run the app on port 8080 using the following command.```bash

python manage.py runserver 8080


```Running App

  1. That's it! Your Django application is now set up and you are ready to move on to the next step: configuring Django to use OIDC.

Part 2.2 : Creating a dummy login page and home screen

  1. Create a superuser with the following command: ```bash

python manage.py createsuperuser


2. Create a new app in your project directory by running the command: ```python

 manage.py startapp authentication

Enter fullscreen mode Exit fullscreen mode
  1. Add authentication to the INSTALLED_APPS in settings.py as follows:```python

oidc_app/settings.py

INSTALLED_APPS = [
...
"authentication",
]


3. Let's make our login page! By default, Django will look for auth templates within a templates folder. To create a login page, create a directory called `templates`, and within it a directory called `registration`. 
4. Inside the `registration` directory, create a file called `login.html`. Add the following piece of code. ```html


<!-- oidc_app/templates/registration/login.html -->
<h2>Log In</h2>
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Log In</button>
</form>


Enter fullscreen mode Exit fullscreen mode
  1. Update the settings.py file to tell Django to look for a templates folder inside the oidc_app directory. Update the DIRS setting within TEMPLATES as follows.```json

django_project/settings.py

TEMPLATES = [
{
...
'DIRS': [BASE_DIR.joinpath("oidc_app/templates")],
...
},
]

6. If you start the app and navigate to: `http://127.0.0.1:8080/accounts/login/`, You should see/test the login page. ![Login Page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w1dvnt4et98etnlxgjng.png)
7. For the home page, we need to make a file called `home.html` located in the `templates` folder. The home page will display a different message to `logged out` and `logged in` users.```html


<!-- oidc_app/templates/base.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>{% block title %}Django OIDC{% endblock %}</title>
</head>
<body>
    <main>
        {% if user.is_authenticated %}
        Hi {{ user.username }} - {{ user.email }}!
        <p><a href="{% url 'logout' %}">Log Out</a></p>
        {% else %}
        <p>You are not logged in</p>
        <a href="{% url 'login' %}">Log In</a>
        {% endif %}
    </main>
</body>
</html>


Enter fullscreen mode Exit fullscreen mode
  1. We now update the urls.py file in order to display the home page.```python

from django.contrib import admin
from django.urls import path, include
from django.views.generic.base import TemplateView
urlpatterns = [
path("admin/", admin.site.urls),
path("accounts/", include("django.contrib.auth.urls")),
path('', TemplateView.as_view(template_name='home.html'), name='index')
]

9. Now that we have a homepage view we should use that instead of the default setup. We update the settings file as follows: ```python


#oidc_app/settings.py
LOGIN_REDIRECT_URL = "index"
LOGOUT_REDIRECT_URL = "index"


Enter fullscreen mode Exit fullscreen mode
  1. Let's create a superuser that we can use to test the authentication. Type in the command: ```bash

python manage.py createsuperuser


10. Enter your desired username, email address and password. You should now have a superuser created for your Django project.

<table>
    <tr>
        <th>Logged Out</th>
        <th>Logged In</th>
    </tr>
<tr>
    <td> <img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pnwr2x4ickiy82gq6c3w.png" alt="Logged Out" style="width: 250px;"/> </td>
    <td> <img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/59n84rui5g66rh99efcq.png" alt="Logged in" style="width: 250px;"/> </td>
    </tr>
</table>

**Note:** The above steps are a very basic example of how to set up a Django application. In a real-world scenario, you would likely want to do more advanced configuration and set up additional features such as a database and static file serving. For more information on how to do this, please see the [Django documentation](https://www.djangoproject.com/).

---

## Part 3.0 : Configuring Django to use OIDC.

**Note:** _We will be using the OpenID Connect Authorization Code Flow. Refer to the [Curity documentation](https://curity.io/resources/learn/openid-code-flow/) for more details._ 

> The Authorization Code Flow is the most advanced flow in OpenID Connect. It is also the most flexible, that allows both mobile and web clients to obtain tokens securely. It is split into two parts, the authorization flow that runs in the browser where the client redirects to the OpenID Provider (OP) and the OP redirects back when done, and the token flow which is a back-channel call from the client to the token endpoint of the OP.

`mozilla-django-oidc` package has abstracted all of the code flow steps required to enable OIDC authentication.

1. Once you’ve created and configured your Django application, you can start configuring `mozilla-django-oidc`. First, install mozilla-django-oidc using pip:```bash


pip install mozilla-django-oidc


Enter fullscreen mode Exit fullscreen mode
  1. Make the following changes to your settings.py file:```python

oidc_app/settings.py

Add 'mozilla_django_oidc' to INSTALLED_APPS

INSTALLED_APPS = (
# ...
'django.contrib.auth',
'mozilla_django_oidc', # Load after auth
# ...
)

Add 'mozilla_django_oidc' authentication backend

AUTHENTICATION_BACKENDS = (
'mozilla_django_oidc.auth.OIDCAuthenticationBackend',
# ...
)
OKTA_DOMAIN = "[Your Okta domain]"
OIDC_RP_CLIENT_ID = "[Your Okta application’s client ID]"
OIDC_RP_CLIENT_SECRET = "[Your Okta application’s client secret]"
OIDC_RP_SIGN_ALGO = "RS256"
OIDC_OP_AUTHORIZATION_ENDPOINT = f"https://{OKTA_DOMAIN}/oauth2/default/v1/authorize" # The OIDC authorization endpoint
OIDC_RP_TOKEN_ENDPOINT = f"https://{OKTA_DOMAIN}/oauth2/default/v1/token" # The OIDC token endpoint
OIDC_OP_USER_ENDPOINT = f"https://{OKTA_DOMAIN}/oauth2/default/v1/userinfo" # The OIDC userinfo endpoint
OIDC_OP_TOKEN_ENDPOINT = f"https://{OKTA_DOMAIN}/oauth2/default/v1/token" # The OIDC token endpoint
OIDC_OP_JWKS_ENDPOINT = f"https://{OKTA_DOMAIN}/oauth2/default/v1/keys" # The OIDC JWKS endpoint

3. Next, edit your `urls.py` and add the following:```python


#oidc_app/settings.py
from mozilla_django_oidc import views as oidc_views
urlpatterns = [
    # ...
    path("authorization-code/authenticate/", oidc_views.OIDCAuthenticationRequestView.as_view(), name="oidc_authentication_init"),
    path("authorization-code/callback/", oidc_views.OIDCAuthenticationCallbackView.as_view(), name="oidc_authentication_callback"),
    # ...
]


Enter fullscreen mode Exit fullscreen mode
  1. We need to add Login with Okta option to our login page. Edit the login.html file as follows:```html

Log In

{% csrf_token %} {{ form.as_p }} Log In
or
Log In with Ota
**Note:** 
- You can get your `Okta Domain` by clicking on your profile section on the top right side of the page. ![Okta Domain](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/58m8ni505bamjxm35i7s.png)  
- The Okta `client ID` and `client secret` are fund in the application settings (`oidc-connect` app we created)

## Part 3.1 Testing the Okta integration

1. Your login page should now have a 'Login with Okta' option
![Login with Okta](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9fsp7h7rtrjaw8j1mf8a.png)
2. When you click the 'Login with Okta' button, you should be redirected to the okta domain for authentication. 
![Okta Login](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u1qzu7eygigoeczbv3ge.png)
3. Enter your username and password or sign in with Google.
4. After successful authentication, you should be redirected to the `home` page. 
![Successful Login](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6jdz9pu4aa8bxxe228av.png)
**Note:** The Username is a base64 encoded sha224 of the email address. More information can be found [here](https://github.com/mozilla/mozilla-django-oidc/blob/63f56222e3/mozilla_django_oidc/auth.py#L24)

**That's it!** You now have a Django app that authenticated with Okta. 

The `mozilla-django-oidc` package can be further customized to better suit your application needs.

**Next Up:** 

Feel free to leave a comment or suggestion. Thank you!

Enter fullscreen mode Exit fullscreen mode

Top comments (1)

Collapse
 
tngeene profile image
Ted Ngeene

Great read!