django-sqrl-2/README.md

5.1 KiB

SQRL for Django

This package allows for developers to easily create SQRL-aware websites with a few simple steps.

(This document was written for the future. Things that are not yet implemented will be struck out. Non-functional code snippets will be #commented out)

This is a reboot of Miki725's django-sqrl, updated for Python 3.7 and Django 2.2. The vast majority of the code is unchanged, so all credit for this working belongs with them.

Installing

SQRL Package

First step is to install django-sqrl-2 which is easies to do using pip:

$ #python3 -m pip install django-sqrl-2

Django settings

Once installed there are a few required changes in Django settings:

  • Make sure that some required Django apps are used:
INSTALLED_APPS = [
    ...,
    'sqrl',
    'django.contrib.auth',
    'django.contrib.sessions',
    'django.contrib.staticfiles',
    ...
]
  • Make sure that some required Django middleware are used:
MIDDLEWARE_CLASSES = [
    ...
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    ...
]
  • Change AUTHENTICATION_BACKENDS to use SQRL backend vs Django's ModelBackend (default):
AUTHENTICATION_BACKENDS = [
    'sqrl.backends.SQRLModelBackend',
]
  • If you are using Django admin, following are required:

  • Make sure that sqrl is listed before admin in the INSTALLED_APPS. This allows Django to prioritize sqrl templates since django-sqrl overwrites some of them.

INSTALLED_APPS = [
    ...,
    'sqrl',
    'django.contrib.admin',
    ...
]
  • Make sure to add a custom template directory in settings. django-sqrl extends Django admin's base.html which by default causes infinite recursion. To solve that, simply add a custom template directory which allows django-sqrl to explicitly extend from django.contrib.admin base.html template:
import os
import django
TEMPLATE_DIRS = [
    os.path.dirname(django.__file__),
]

URLs

All of SQRL functionality is enabled by adding its URLs to the root URL config:

from django.urls import path, include

urlpatterns = [
    ...
    path('sqrl/', include('sqrl.urls', namespace="sqrl")),
    ...
]

If you use Django admin, the /admin/sqrl_manage endpoint will be available to manage your site's SQRL identities.

Templates

Now that SQRL is installed in your Django project, you can use it on any login page with three simple template tags:

{% load sqrl %}
{% sqrl as sqrl_session %}
{% sqrl_login_dropin sqrl_session "named:redirect" %}

The "named:redirect" is the page that should be redirected to after logging in. Any name that can be resolved by django's reverse function will work. For example, here are the necessary lines needed to resolve "app:main":

  • Main project's urls.py:
urlpatterns = [
    ...
    path("", include('app.urls', namespace="app"))
    ...
]
  • Your app's urls.py:
urlpatterns = [
    ...
    path("", main_view, name="main")
    ...
]
  • Your main_view's template:
...
{% load sqrl %}
{% sqrl as sqrl_session %}
{% sqrl_login_dropin sqrl_session "app:main" %}
...

These three tags will add a simple element to your login page:

A very basic SQRL QR code

If that doesn't suit your fancy, you may build your own template from the following essential tags:

{% load static %}
{% load sqrl %}
{% sqrl as sqrl_session %}

{% if session_sqrl.sqrl_url %}
<a href="{{ sqrl_session.sqrl_url }}">
    <div id="sqrl-qr" data-sqrl="{{ sqrl_session.sqrl_url }}"></div>
</a>
<script>SQRL_NEXT="{{ your desired redirect (not namespace) }}"; SQRL_CHECK_URL="{% sqrl_status_url_script_tag sqrl_session %}"</script>
<script type="application/javascript" src="{% static 'sqrl/sqrl.js' %}"></script>
{% else $}
<p>You are not connected via HTTPS, therefore you may not log in using SQRL.</p>
{% endif %}

Note that the session_sqrl.sqrl_url function will return None if the user connects over an insecure HTTP connection. If you make your own template, please be sure to account for this situation as in the above example.

Management Command

SQRL uses server state to keep track of open SQRL transactions in order to mitigate replay attacks. Since this state will constantly grow if not cleared, django-sqrl provides a helper management command to clear expired states:

$ python3 manage.py clearsqrlnuts

It is recommended to run this command as repeating task. Here is an example configuration for cron:

*/5 * * * * python manage.py clearsqrlnuts >/dev/null 2>&1

Testing

To run the tests, you need to install the testing requirements first:

$ #make install

Then to run the tests, you can use use the Makefile command:

$ #make test