A simple Django middleware for Duo V4 2-factor authentication.

Overview

django-duo-universal-auth

A lightweight middleware application that adds a layer on top of any number of existing authentication backends, enabling 2FA with the user's Duo account using the Universal Prompt after signing in with your Django application.

Note: In order to interface this middleware with Duo, you must create a new Duo Web SDK application from within your organization's Duo Admin Portal and enable the "Show new Universal Prompt" setting. You will acquire a Client ID, Client Secret, and API Hostname, of which you will include in your settings.py file in the format listed below. It is strongly recommended not to hardcode these values in the settings file itself.

From Duo's documentation for protecting applications:

Treat your Secret key or Client ID like a password The security of your Duo application is tied to the security of your Secret key (skey) or Client secret (client_secret). Secure it as you would any sensitive credential. Don't share it with unauthorized individuals or email it to anyone under any circumstances!

Installation

To install the middleware application, use the following pip command (or equivalent for your package manager application):

pip install django-duo-universal-auth

Sample Configuration (in your settings.py file)

First, add the package to your INSTALLED_APPS list variable:

INSTALLED_APPS = [
    # ...
    'duo_universal_auth', # Add this!
]

Next, add the path for the middleware application to the MIDDLEWARE list variable:

MIDDLEWARE = [
    # ...
    'duo_universal_auth.middleware.DuoUniversalAuthMiddleware', # Add this!
]

Then, add a new DUO_UNIVERSAL_AUTH configuration variable:

DUO_UNIVERSAL_AUTH = {
    'MAIN': {
        'DUO_HOST': '
   
    '
   ,
        'CLIENT_ID': '
   
    '
   ,
        'CLIENT_SECRET': '
   
    '
   ,
        'AUTH_BACKENDS': [
            'django.contrib.auth.backends.ModelBackend',
        ],
        'FAIL_ACTION': 'CLOSED'
    }
}

Duo API Callback Setup

Note: This step allows the application to communicate with Duo. If the view is not registered, the application will raise a NoReverseMatch error upon starting the Duo authentication flow.

To create the callback for the API to communicate with, you must add an entry to your urlpatterns variable from within your application's urls.py file (with any prepending path you choose):

from django.urls import path, include

urlpatterns = [
    # ...
    path('duo/', include('duo_universal_auth.urls')), # Add this!
]

Configuration Docs

Configurations for each Duo application are specified within individual dictionary objects inside a parent DUO_UNIVERSAL_AUTH dictionary each containing the following values:

DUO_HOST

Required: True

Represents the API Hostname for your organization's Duo API.

'DUO_HOST': 'api-XXXXXXX.duosecurity.com'

CLIENT_ID

Required: True

Represents the Client ID for your application registered from within the Duo Admin Portal.

'CLIENT_ID': 'DIXXXXXXXXXXXXXXXXXX'

CLIENT_SECRET

Required: True

Represents the Client Secret for your application registered from within the Duo Admin Portal.

'CLIENT_SECRET': 'deadbeefdeadbeefdeadbeefdeadbeefdeadbeef'

AUTH_BACKENDS

Required: True

A list of authentication backends that the middleware will work with for the specific application. The Duo authentication middleware will only execute upon a successful authentication result from one of these backends.

'AUTH_BACKENDS': [
    'django.contrib.auth.backends.ModelBackend',
]

FAIL_ACTION

Required: False (Default: 'CLOSED')

How the middleware should respond should the Duo authentication server be unavailable (from failing the preliminary health check).

  • 'CLOSED': Log out the user and return to the login page, disallowing any authentication while Duo servers are unavailable.
  • 'OPEN': Temporarily bypass Duo authentication until the Duo servers become available upon a future authentication attempt.
'FAIL_ACTION': 'CLOSED'

USERNAME_REMAP_FUNCTION

Required: False

An optional one-argument function that takes in the current Django HttpRequest object and returns the current authenticated user's username to send for Duo authentication. If unspecified, the username from HttpRequest.user will be used.

'USERNAME_REMAP_FUNCTION': lambda r: r.user.username  # Mimics default behavior

Post-Authentication Redirect

Once successfully authenticated with Duo, the middleware will automatically redirect the user to the path specified in the DUO_NEXT_URL session variable, falling back to the LOGIN_REDIRECT_URL settings variable if it is not present. Because the next query parameter does not travel along with the Duo authentication flow, this session variable is not assigned in the middleware, but can be assigned using a custom instruction in your AuthenticationBackend. This is a feature that I plan to add to this package either through a decorator function or other means. If anyone has any ideas on how to implement this, feel free to submit a pull request!

You might also like...
Django-environ allows you to utilize 12factor inspired environment variables to configure your Django application.
Django-environ allows you to utilize 12factor inspired environment variables to configure your Django application.

Django-environ django-environ allows you to use Twelve-factor methodology to configure your Django application with environment variables. import envi

Rosetta is a Django application that eases the translation process of your Django projects
Rosetta is a Django application that eases the translation process of your Django projects

Rosetta Rosetta is a Django application that facilitates the translation process of your Django projects. Because it doesn't export any models, Rosett

Cookiecutter Django is a framework for jumpstarting production-ready Django projects quickly.
Cookiecutter Django is a framework for jumpstarting production-ready Django projects quickly.

Cookiecutter Django Powered by Cookiecutter, Cookiecutter Django is a framework for jumpstarting production-ready Django projects quickly. Documentati

Django project starter on steroids: quickly create a Django app AND generate source code for data models + REST/GraphQL APIs (the generated code is auto-linted and has 100% test coverage).

Create Django App 💛 We're a Django project starter on steroids! One-line command to create a Django app with all the dependencies auto-installed AND

django-quill-editor makes Quill.js easy to use on Django Forms and admin sites
django-quill-editor makes Quill.js easy to use on Django Forms and admin sites

django-quill-editor django-quill-editor makes Quill.js easy to use on Django Forms and admin sites No configuration required for static files! The ent

A Django chatbot that is capable of doing math and searching Chinese poet online. Developed with django, channels, celery and redis.

Django Channels Websocket Chatbot A Django chatbot that is capable of doing math and searching Chinese poet online. Developed with django, channels, c

A handy tool for generating Django-based backend projects without coding. On the other hand, it is a code generator of the Django framework.
A handy tool for generating Django-based backend projects without coding. On the other hand, it is a code generator of the Django framework.

Django Sage Painless The django-sage-painless is a valuable package based on Django Web Framework & Django Rest Framework for high-level and rapid web

A beginner django project and also my first Django project which involves shortening of a longer URL into a short one using a unique id.

Django-URL-Shortener A beginner django project and also my first Django project which involves shortening of a longer URL into a short one using a uni

Dockerizing Django with Postgres, Gunicorn, Nginx and Certbot. A fully Django starter project.

Dockerizing Django with Postgres, Gunicorn, Nginx and Certbot 🚀 Features A Django stater project with fully basic requirements for a production-ready

Comments
  • getting error on callback

    getting error on callback

    Hi Adam,

    Thank you for sharing your package and providing very clear instructions.

    I took a django application (https://github.com/mdn/django-locallibrary-tutorial) and confirmed that the standard django authentication was working.

    I then added the changes to the settings.py and urls.py files mentioned in your README.md. When I run it and attempt to login, I get the following error in the browser:

    {"error": "invalid_grant", "error_description": "Invalid redirect URI 'http://127.0.0.1:8000/duo/callback/'."}

    I get the same error using django 3.2 or 4.1.

    I verified that my duo credentials work by using the demo app in https://github.com/duosecurity/duo_universal_python

    Any insight you can provide would be greatly appreciated!

    Kelvin Lim

    opened by kelvinlim 0
Releases(v0.2.0)
Owner
Adam Angle
UC Berkeley EECS '25 | Student Intern at Exquadrum, Inc.
Adam Angle
Logan is a toolkit for building standalone Django applications

Logan Logan is a toolkit for running standalone Django applications. It provides you with tools to create a CLI runner, manage settings, and the abili

David Cramer 206 Jan 03, 2023
Show how the redis works with Python (Django).

Redis Leaderboard Python (Django) Show how the redis works with Python (Django). Try it out deploying on Heroku (See notes: How to run on Google Cloud

Tom Xu 4 Nov 16, 2021
Automated image processing for Django. Currently v4.0

ImageKit is a Django app for processing images. Need a thumbnail? A black-and-white version of a user-uploaded image? ImageKit will make them for you.

Matthew Dapena-Tretter 2.1k Jan 04, 2023
A app for managing lessons with Django

Course Notes A app for managing lessons with Django Some Ideas

Motahhar.Mokfi 6 Jan 28, 2022
Highlight the keywords of a page if a visitor is coming from a search engine.

Django-SEKH Django Search Engine Keywords Highlighter, is a middleware for Django providing the capacities to highlight the user's search keywords if

Julien Fache 24 Oct 08, 2021
REST API with Django and SQLite3

REST API with Django and SQLite3

Luis Quiñones Requelme 1 Nov 07, 2021
A GitHub Action for checking Django migrations

🔍 Django migrations checker A GitHub Action for checking Django migrations About This repository contains a Github Action that checks Django migratio

Oda 5 Nov 15, 2022
A simple porfolio with Django, Bootstrap and Sqlite3

Django Portofolio Example this is a basic portfolio in dark mode Installation git clone https://github.com/FaztWeb/django-portfolio-simple.git cd djan

Fazt Web 16 Sep 26, 2022
Official Python agent for the Elastic APM

elastic-apm -- Elastic APM agent for Python This is the official Python module for Elastic APM. It provides full out-of-the-box support for many of th

elastic 369 Jan 05, 2023
Django Email Sender

Email-Sender Django Email Sender Installation 1.clone Repository & Install Packages git clone https://github.com/telman03/Email-Sender.git pip install

Telman Gadimov 0 Dec 26, 2021
Quick example of a todo list application using Django and HTMX

django-htmx-todo-list Quick example of a todo list application using Django and HTMX Background Modified & expanded from https://github.com/jaredlockh

Jack Linke 54 Dec 10, 2022
An airlines clone website with django

abc_airlines is a clone website of an airlines system the way it works is that first you add flights to the website then the users can search flights

milad 1 Nov 16, 2021
Django Persistent Filters is a Python package which provide a django middleware that take care to persist the querystring in the browser cookies.

Django Persistent Filters Django Persistent Filters is a Python package which provide a django middleware that take care to persist the querystring in

Lorenzo Prodon 2 Aug 05, 2022
A Django based shop system

django-SHOP Django-SHOP aims to be a the easy, fun and fast e-commerce counterpart to django-CMS. Here you can find the full documentation for django-

Awesto 2.9k Dec 30, 2022
Djangoblog - A blogging platform built on Django and Python.

djangoblog 👨‍💻 A blogging platform built on Django and Python

Lewis Gentle 1 Jan 10, 2022
An extremely fast JavaScript and CSS bundler and minifier

Website | Getting started | Documentation | Plugins | FAQ Why? Our current build tools for the web are 10-100x slower than they could be: The main goa

Evan Wallace 34.2k Jan 04, 2023
A django model and form field for normalised phone numbers using python-phonenumbers

django-phonenumber-field A Django library which interfaces with python-phonenumbers to validate, pretty print and convert phone numbers. python-phonen

Stefan Foulis 1.3k Dec 31, 2022
Django models and endpoints for working with large images -- tile serving

Django Large Image Models and endpoints for working with large images in Django -- specifically geared towards geospatial tile serving. DISCLAIMER: th

Resonant GeoData 42 Dec 17, 2022
APIs for a Chat app. Written with Django Rest framework and Django channels.

ChatAPI APIs for a Chat app. Written with Django Rest framework and Django channels. The documentation for the http end points can be found here This

Victor Aderibigbe 18 Sep 09, 2022
A quick way to add React components to your Django templates.

Django-React-Templatetags This django library allows you to add React (16+) components into your django templates. Features Include react components u

Fröjd Agency 408 Jan 08, 2023