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
An example of Django project with basic user functionality and account activation.

Simple Django Login and Registration An example of Django project with basic user functionality. Screenshots Log In Create an account Authorized page

Hussein Sarea 3 Oct 19, 2022
Template de desarrollo Django

Template de desarrollo Django Python Django Docker Postgres Nginx CI/CD Descripción del proyecto : Proyecto template de directrices para la estandariz

Diego Esteban 1 Feb 25, 2022
Imparare Django ricreando un sito facsimile a quello Flask

SitoPBG-Django Imparare Django ricreando un sito facsimile a quello Flask Note di utilizzo Necessita la valorizzazione delle seguenti variabili di amb

Mario Nardi 1 Dec 08, 2021
django-compat-lint

django_compat_lint -- check Django compatibility of your code Django's API stability policy is nice, but there are still things that change from one v

James Bennett 40 Sep 30, 2021
A drop-in replacement for django's ImageField that provides a flexible, intuitive and easily-extensible interface for quickly creating new images from the one assigned to the field.

django-versatileimagefield A drop-in replacement for django's ImageField that provides a flexible, intuitive and easily-extensible interface for creat

Jonathan Ellenberger 490 Dec 13, 2022
Store model history and view/revert changes from admin site.

django-simple-history django-simple-history stores Django model state on every create/update/delete. This app supports the following combinations of D

Jazzband 1.8k Jan 08, 2023
Indonesia's negative news detection using gaussian naive bayes with Django+Scikir Learn

Introduction Indonesia's negative news detection using gaussian naive bayes build with Django and Scikit Learn. There is also any features, are: Input

Harifzi Ham 1 Dec 30, 2021
Send logs to RabbitMQ from Python/Django.

python-logging-rabbitmq Logging handler to ships logs to RabbitMQ. Compatible with Django. Installation Install using pip. pip install python_logging_

Alberto Menendez Romero 38 Nov 17, 2022
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
Full control of form rendering in the templates.

django-floppyforms Full control of form rendering in the templates. Authors: Gregor Müllegger and many many contributors Original creator: Bruno Renié

Jazzband 811 Dec 01, 2022
based official code from django channels, replace frontend with reactjs

django_channels_chat_official_tutorial demo project for django channels tutorial code from tutorial page: https://channels.readthedocs.io/en/stable/tu

lightsong 1 Oct 22, 2021
Django + AWS Elastic Transcoder

Django Elastic Transcoder django-elastic-transcoder is an Django app, let you integrate AWS Elastic Transcoder in Django easily. What is provided in t

StreetVoice 66 Dec 14, 2022
Store events and publish to Kafka

Create an event from Django ORM object model, store the event into the database and also publish it into Kafka cluster.

Diag 6 Nov 30, 2022
A collection of models, views, middlewares, and forms to help secure a Django project.

Django-Security This package offers a number of models, views, middlewares and forms to facilitate security hardening of Django applications. Full doc

SD Elements 258 Jan 03, 2023
Django With VueJS Blog App

django-blog-vue-app frontend Project setup yarn install Compiles and hot-reload

Flavien HUGS 2 Feb 04, 2022
📝 Sticky Notes in Django admin

django-admin-sticky-notes Share notes between superusers. Installation Install via pip: pip install django_admin_sticky_notes Put django_admin_sticky_

Dariusz Choruży 7 Oct 06, 2021
Python CSS/Javascript minifier

Squeezeit - Python CSS and Javascript minifier Copyright (C) 2011 Sam Rudge This program is free software: you can redistribute it and/or modify it un

Smudge 152 Apr 03, 2022
Django StatusPage - App to display statuspage for your services

Django StatusPage - App to display statuspage for your services

Gorlik 1 Oct 27, 2021
A Django application that provides country choices for use with forms, flag icons static files, and a country field for models.

Django Countries A Django application that provides country choices for use with forms, flag icons static files, and a country field for models. Insta

Chris Beaven 1.2k Dec 31, 2022
Displaying objects on maps in the Django views and administration site.

DjangoAdminGeomap library The free, open-source DjangoAdminGeomap library is designed to display objects on the map in the Django views and admin site

Vitaly Bogomolov 31 Dec 28, 2022