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
A music recommendation REST API which makes a machine learning algorithm work with the Django REST Framework

music-recommender-rest-api A music recommendation REST API which makes a machine learning algorithm work with the Django REST Framework How it works T

The Reaper 1 Sep 28, 2021
A prettier way to see Django requests while developing

A prettier way to see Django requests while developing

Adam Hill 35 Dec 02, 2022
This "I P L Team Project" is developed by Prasanta Kumar Mohanty using Python with Django web framework, HTML & CSS.

I-P-L-Team-Project This "I P L Team Project" is developed by Prasanta Kumar Mohanty using Python with Django web framework, HTML & CSS. Screenshots HO

1 Dec 15, 2021
An insecure login and registration website with Django.

An insecure login and registration website with Django.

Luis Quiñones Requelme 1 Dec 05, 2021
This is a Django app that uses numerous Google APIs such as reCAPTURE, maps and waypoints

Django project that uses Googles APIs to auto populate fields, display maps and routes for multiple waypoints

Bobby Stearman 57 Dec 03, 2022
A Django app for working with BTCPayServer

btcpay-django A Django app for working with BTCPayServer Installation pip install btcpay-django Developers Release To cut a release, run bumpversion,

Crawford 3 Nov 20, 2022
Automatic caching and invalidation for Django models through the ORM.

Cache Machine Cache Machine provides automatic caching and invalidation for Django models through the ORM. For full docs, see https://cache-machine.re

846 Nov 26, 2022
Django Livre Bank

Django Livre Bank Projeto final da academia Construdelas. API de um banco fictício com clientes, contas e transações. Integrantes da equipe Bárbara Sa

CecĂ­lia Costa 3 Dec 22, 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
This is a personal django website for forum posts

Django Web Forum This is a personal django website for forum posts It includes login, registration and forum posts with date time. Tech / Framework us

5 May 12, 2022
This is a basic Todo Application API using Django Rest Framework

Todo Application This is a basic Todo Application API using Django Rest Framework. Todo Section - User can View his previously added todo items, creat

Atharva Parkhe 1 Aug 09, 2022
A Django web application that shortens long URLs. This is a demo project to show off my tech abilities.

Django URL Shortener This project is just a complete and production-ready URL shortener web application to show off my tech and coding abilities. Impo

Seyyed Ali Ayati 5 Jan 26, 2022
The friendly PIL fork (Python Imaging Library)

Pillow Python Imaging Library (Fork) Pillow is the friendly PIL fork by Alex Clark and Contributors. PIL is the Python Imaging Library by Fredrik Lund

Pillow 10.4k Jan 03, 2023
Simple tagging for django

django-taggit This is a Jazzband project. By contributing you agree to abide by the Contributor Code of Conduct and follow the guidelines. django-tagg

Jazzband 3k Jan 02, 2023
Probably the best abstract model / admin for your tree based stuff.

django-treenode Probably the best abstract model / admin for your tree based stuff. Features Fast - get ancestors, children, descendants, parent, root

Fabio Caccamo 360 Jan 05, 2023
Money fields for Django forms and models.

django-money A little Django app that uses py-moneyed to add support for Money fields in your models and forms. Django versions supported: 1.11, 2.1,

1.4k Jan 06, 2023
Sistema de tratamento e análise de grandes volumes de dados através de técnicas de Data Science

Sistema de tratamento e análise de grandes volumes de dados através de técnicas de data science Todos os scripts, gráficos e relatórios de todas as at

Arthur Quintanilha Neto 1 Sep 05, 2022
xsendfile etc wrapper

Django Sendfile This is a wrapper around web-server specific methods for sending files to web clients. This is useful when Django needs to check permi

John Montgomery 476 Dec 01, 2022
GameStop clone with Django

GameStop clone with Django This is my side project with GameStop clone Author: HackerApe GitHub Profile: View Profile LinkedIn Profile: View Profile

Dmitriy Shin 2 Dec 26, 2021
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

Yunbo Shi 8 Oct 28, 2022