Paperless-ngx: Activate Two-Factor-Authentication (2FA)

How to activate the integrated multi-factor authentication for Paperless-ngx and secure your access. An overview of all configurations for 2FA.

Last updated: Nov 16, 2024

7 mins read
Avatar of Tobias Wupperfeld

Author

Tobias Wupperfeld

Tobias is a seasoned software engineer and the founder of PaperlessZone.

Topics

Paperless-ngx multifactor authentication

Introduction

The web interface of Paperless-ngx only offers a login with a username and password after the default installation.

In 2024, this is not exactly secure. If someone finds out your password, they’re in the system. Won’t happen, you think? It only takes one data breach. A phishing email or a virus that records keyboard input. Or the lack of an encrypted connection over HTTP. Especially when it comes to sensitive documents, additional protection is indispensable.

Since the release of 2.5.0, Paperless-ngx supports the integration of multi-factor authentication through various providers.

Multi-factor or two-factor means that in addition to entering your password, you must confirm the login through another method. For example, by entering a TOTP code that you retrieve via email, SMS, or a smartphone app. To bypass this, an attacker would need simultaneous access to both methods, which is significantly harder.

Step 1: Choose a Provider

Multi-factor authentication is done through an external provider. Paperless-ngx uses a Django backend and supports all Django Allauth providers. You can see a list of all providers here and choose one or more providers.

If you want to host an application for authentication yourself, the OpenID-connect (OIDC) interface is a good option. You can use OIDC with Authelia or Keycloak – two popular open-source software tools. However, the setup requires significantly more technical knowledge. If you’re interested in a tutorial on this, let me know in the comments.

You can set up most third-party providers very easily. I’ll show you the setup with Github here as an example, which is free. The setup with other providers is similar.

This can help you choose the right provider: Find out which providers most of your employees already have an account with.

Step 2: Register the App

First, you register your Paperless app with one of the providers. Then you receive a client ID and a security key (secret) from the provider.

For registration with Github, go to this page and fill out all the required fields. You can set any name for your app.

For the homepage URL, set the URL where your Paperless instance is accessible.

Finally, define the callback URL to which Github redirects after successful login. To do this, add this section to the end of your homepage URL /accounts/github/login/callback/.

register paperless app in github

After you have submitted the form, you can generate a client secret. For the next step, you will need the client secret and the client ID.

Copy client id and secret key for your app

Step 3: Add Environment Variables

Open the directory where you have installed Paperless-ngx and where the Docker Compose configurations are located. Open the file docker-compose.env. I connect to my Linux server via SSH and open the file with the text editor nano:

sudo nano docker-compose.env

At the end of the file, add two variables:

PAPERLESS_APPS: allauth.socialaccount.providers.github
PAPERLESS_SOCIALACCOUNT_PROVIDERS: {"github": {"APPS": [{"provider_id": "github","name": "Github","client_id": "<CLIENT_ID>","secret": "<CLIENT_SECRET>"}]}

Replace the placeholders CLIENT_ID and CLIENT_SECRET with your keys.

Save the file and close the text editor. I do this using the commands CTRL+X followed by Y and ENTER.

To save the settings, you need to restart the Docker containers. Execute the following command:

docker compose down && docker compose up -d

After about a minute, your Paperless instance should be accessible again.

Step 4: Activate Provider in Paperless App

Now, if you navigate to your Paperless instance, you will see two login options: Login with GitHub and the regular login with username and password.

Two login options in Paperless

Log in as usual with your regular access data to your admin account. Access your profile. You will now see a button that allows you to link your account with GitHub.

connect paperless with github in paperless profile

Click on the button and connect your account. Log out of Paperless and your Github account and test if you can log in with Github. This should work without any problems.

For multi-factor authentication to work, you need to add it to your GitHub account. As long as your GitHub session is active, you will remain logged in to your Paperless instance.

Step 5: Disable Regular Login

Open the docker-compose.env file again. Add another variable to the end of the file:

PAPERLESS_DISABLE_REGULAR_LOGIN=true

Save and close the file and restart the Docker containers. When Paperless is back online, the regular login should be gone.

sign in paperless with github

Some Important Limitations

There are two limitations you currently have to live with if you want to use the Paperless MFA integration. Perhaps it will be patched in future updates.

Admin Panel Security Vulnerability

There is currently a security vulnerability that ruins all our previous work. That is the Django admin panel. You can access the Django admin panel via the URL path /admin/. https://paperless.domain.com/admin/

You can still log into the admin panel with your regular access data!

django admin panel login in paperless
django admin panel in paperless

As soon as you are logged in, you can navigate to your Paperless dashboard and have access to all your documents. This means: You can bypass the multi-factor authentication, which is not what we want.

Update: since version 2.8 you can deactivate the admin panel by removing the permission in your user settings:

deactivate the admin panel in user settings

Alternatively, a simple solution to close the security vulnerability is to block the path /admin/ in your web server settings. Where exactly you need to make the settings depends on the web server you are using and where it is installed on your system.

If you are using Nginx as a reverse proxy like I do, you probably have the directory /etc/nginx/sites-available. Here is the configuration for the domain under which my Paperless instance is running.

Go to the directory:

cd /etc/nginx/sites-available

Open the configuration:

sudo nano paperless.domain.com

Add the following code to your server block:

location /admin/ {
return 302 /;
}

What does the code do? As soon as a user calls the path to the admin panel, they are redirected to the root path /. An HTTP status code 302 (temporary redirection) is thrown.

Save and close the file and test for syntax errors with:

sudo nginx -t

If everything is ok, restart Nginx:

sudo systemctl restart nginx

With this, the security vulnerability is closed.

The downside: You can no longer access the Django admin panel. Even if you are logged in.

Registration of Additional Users

A new user can simply register for your app via the login page with their GitHub account. The user then appears in your account under the users’ section.

Theoretically, any visitor to your login page can register. But don’t worry: After registration, the user has no permissions or access to your data.

You must edit the user in the users’ section and assign them permissions. If the user should not be authorized, you can simply delete them.

If you intend to deactivate the registration of new users via your login page, add the variable PAPERLESS_SOCIALACCOUNT_ALLOW_SIGNUPS=False to your configuration and restart the docker containers.

Conclusion

The integration of multi-factor authentication into Paperless is an important step to make your instance more secure against attackers. The integration of Django Allauth providers is simple but comes with some limitations.

There are many more ways to secure your Paperless instance. Most of it is a general server topic and has nothing to do with the Paperless app itself. For example, you could connect a multi-factor authentication via Authelia with your reverse proxy. For every incoming request, an authentication request is sent. The response instructs the reverse proxy to either allow or block the incoming request. Paperless is only loaded after successful authentication.

The paperless managed solution by PaperlessZone

Leave a comment

Your email address won't be published.