mirror of
https://github.com/sissbruecker/linkding
synced 2024-11-10 06:04:15 +00:00
Add setting and documentation for fixing CSRF errors (#349)
* Add documentation and setting for solving CSRF errors * Improve proxy setup docs * Link to reverse proxy documentation * Fix link
This commit is contained in:
parent
53be77aade
commit
1c3651e91d
6 changed files with 103 additions and 1 deletions
|
@ -4,10 +4,10 @@ LD_CONTAINER_NAME=linkding
|
||||||
LD_HOST_PORT=9090
|
LD_HOST_PORT=9090
|
||||||
# Directory on the host system that should be mounted as data dir into the Docker container
|
# Directory on the host system that should be mounted as data dir into the Docker container
|
||||||
LD_HOST_DATA_DIR=./data
|
LD_HOST_DATA_DIR=./data
|
||||||
|
|
||||||
# Can be used to run linkding under a context path, for example: linkding/
|
# Can be used to run linkding under a context path, for example: linkding/
|
||||||
# Must end with a slash `/`
|
# Must end with a slash `/`
|
||||||
LD_CONTEXT_PATH=
|
LD_CONTEXT_PATH=
|
||||||
|
|
||||||
# Username of the initial superuser to create, leave empty to not create one
|
# Username of the initial superuser to create, leave empty to not create one
|
||||||
LD_SUPERUSER_NAME=
|
LD_SUPERUSER_NAME=
|
||||||
# Password for the initial superuser, leave empty to disable credentials authentication and rely on proxy authentication instead
|
# Password for the initial superuser, leave empty to disable credentials authentication and rely on proxy authentication instead
|
||||||
|
@ -24,3 +24,6 @@ LD_AUTH_PROXY_USERNAME_HEADER=
|
||||||
# The URL that linkding should redirect to after a logout, when using an auth proxy
|
# The URL that linkding should redirect to after a logout, when using an auth proxy
|
||||||
# See docs/Options.md for more details
|
# See docs/Options.md for more details
|
||||||
LD_AUTH_PROXY_LOGOUT_URL=
|
LD_AUTH_PROXY_LOGOUT_URL=
|
||||||
|
# List of trusted origins from which to accept POST requests
|
||||||
|
# See docs/Options.md for more details
|
||||||
|
LD_CSRF_TRUSTED_ORIGINS=
|
||||||
|
|
41
README.md
41
README.md
|
@ -12,6 +12,7 @@
|
||||||
- [Using Docker](#using-docker)
|
- [Using Docker](#using-docker)
|
||||||
- [Using Docker Compose](#using-docker-compose)
|
- [Using Docker Compose](#using-docker-compose)
|
||||||
- [User Setup](#user-setup)
|
- [User Setup](#user-setup)
|
||||||
|
- [Reverse Proxy Setup](#reverse-proxy-setup)
|
||||||
- [Managed Hosting Options](#managed-hosting-options)
|
- [Managed Hosting Options](#managed-hosting-options)
|
||||||
- [Documentation](#documentation)
|
- [Documentation](#documentation)
|
||||||
- [Browser Extension](#browser-extension)
|
- [Browser Extension](#browser-extension)
|
||||||
|
@ -96,6 +97,46 @@ docker-compose exec linkding python manage.py createsuperuser --username=joe --e
|
||||||
|
|
||||||
The command will prompt you for a secure password. After the command has completed you can start using the application by logging into the UI with your credentials.
|
The command will prompt you for a secure password. After the command has completed you can start using the application by logging into the UI with your credentials.
|
||||||
|
|
||||||
|
### Reverse Proxy Setup
|
||||||
|
|
||||||
|
When using a reverse proxy, such as Nginx or Apache, you may need to configure your proxy to correctly forward the `Host` header to linkding, otherwise certain requests, such as login, might fail.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Apache</summary>
|
||||||
|
|
||||||
|
Not tested yet.
|
||||||
|
If you figure out a working setup, feel free to contribute it here.
|
||||||
|
|
||||||
|
In the meanwhile, use the [`LD_CSRF_TRUSTED_ORIGINS` option](docs/Options.md#LD_CSRF_TRUSTED_ORIGINS).
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Caddy 2</summary>
|
||||||
|
|
||||||
|
Caddy does not change the headers by default, and should not need any further configuration.
|
||||||
|
|
||||||
|
If you still run into CSRF issues, please check out the [`LD_CSRF_TRUSTED_ORIGINS` option](docs/Options.md#LD_CSRF_TRUSTED_ORIGINS).
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Nginx</summary>
|
||||||
|
|
||||||
|
Nginx by default rewrites the `Host` header to whatever URL is used in the `proxy_pass` directive.
|
||||||
|
To forward the correct headers to linkding, add the following directives to the location block of your Nginx config:
|
||||||
|
```
|
||||||
|
location /linkding {
|
||||||
|
...
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
Instead of configuring header forwarding in your proxy, you can also configure the URL from which you want to access your linkding instance with the [`LD_CSRF_TRUSTED_ORIGINS` option](docs/Options.md#LD_CSRF_TRUSTED_ORIGINS).
|
||||||
|
|
||||||
### Managed Hosting Options
|
### Managed Hosting Options
|
||||||
|
|
||||||
Self-hosting web applications on your own hardware (unfortunately) still requires a lot of technical know-how, and commitment to maintenance, with regard to keeping everything up-to-date and secure. This can be a huge entry barrier for people who are interested in self-hosting linkding, but lack the technical knowledge to do so. This section is intended to provide alternatives in form of managed hosting solutions. Note that these options are usually commercial offerings, that require paying a (usually monthly) fee for the convenience of being managed by another party. The technical knowledge required to make use of individual options is going to vary, and no guarantees can be made that every option is accessible for everyone. That being said, I hope this section helps in making the application accessible to a wider audience.
|
Self-hosting web applications on your own hardware (unfortunately) still requires a lot of technical know-how, and commitment to maintenance, with regard to keeping everything up-to-date and secure. This can be a huge entry barrier for people who are interested in self-hosting linkding, but lack the technical knowledge to do so. This section is intended to provide alternatives in form of managed hosting solutions. Note that these options are usually commercial offerings, that require paying a (usually monthly) fee for the convenience of being managed by another party. The technical knowledge required to make use of individual options is going to vary, and no guarantees can be made that every option is accessible for everyone. That being said, I hope this section helps in making the application accessible to a wider audience.
|
||||||
|
|
29
bookmarks/tests/test_app_options.py
Normal file
29
bookmarks/tests/test_app_options.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import importlib
|
||||||
|
import os
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
|
||||||
|
class AppOptionsTestCase(TestCase):
|
||||||
|
def setUp(self) -> None:
|
||||||
|
self.settings_module = importlib.import_module('siteroot.settings.base')
|
||||||
|
|
||||||
|
def test_empty_csrf_trusted_origins(self):
|
||||||
|
module = importlib.reload(self.settings_module)
|
||||||
|
|
||||||
|
self.assertFalse(hasattr(module, 'CSRF_TRUSTED_ORIGINS'))
|
||||||
|
|
||||||
|
@mock.patch.dict(os.environ, {'LD_CSRF_TRUSTED_ORIGINS': 'https://linkding.example.com'})
|
||||||
|
def test_single_csrf_trusted_origin(self):
|
||||||
|
module = importlib.reload(self.settings_module)
|
||||||
|
|
||||||
|
self.assertTrue(hasattr(module, 'CSRF_TRUSTED_ORIGINS'))
|
||||||
|
self.assertCountEqual(module.CSRF_TRUSTED_ORIGINS, ['https://linkding.example.com'])
|
||||||
|
|
||||||
|
@mock.patch.dict(os.environ, {'LD_CSRF_TRUSTED_ORIGINS': 'https://linkding.example.com,http://linkding.example.com'})
|
||||||
|
def test_multiple_csrf_trusted_origin(self):
|
||||||
|
module = importlib.reload(self.settings_module)
|
||||||
|
|
||||||
|
self.assertTrue(hasattr(module, 'CSRF_TRUSTED_ORIGINS'))
|
||||||
|
self.assertCountEqual(module.CSRF_TRUSTED_ORIGINS, ['https://linkding.example.com', 'http://linkding.example.com'])
|
|
@ -93,3 +93,18 @@ For example, for Authelia, which passes the `Remote-User` HTTP header, the `LD_A
|
||||||
- `LD_AUTH_PROXY_LOGOUT_URL` - The URL that linkding should redirect to after a logout.
|
- `LD_AUTH_PROXY_LOGOUT_URL` - The URL that linkding should redirect to after a logout.
|
||||||
By default, the logout redirects to the login URL, which means the user will be automatically authenticated again.
|
By default, the logout redirects to the login URL, which means the user will be automatically authenticated again.
|
||||||
Instead, you might want to configure the logout URL of the auth proxy here.
|
Instead, you might want to configure the logout URL of the auth proxy here.
|
||||||
|
|
||||||
|
### `LD_CSRF_TRUSTED_ORIGINS`
|
||||||
|
|
||||||
|
Values: `String` | Default = None
|
||||||
|
|
||||||
|
List of trusted origins / host names to allow for `POST` requests, for example when logging in, or saving bookmarks.
|
||||||
|
For these type of requests, the `Origin` header must match the `Host` header, otherwise the request will fail with a `403` status code, and the message `CSRF verification failed.`
|
||||||
|
|
||||||
|
This option allows to declare a list of trusted origins that will be accepted even if the headers do not match. This can be the case when using a reverse proxy that rewrites the `Host` header, such as Nginx.
|
||||||
|
|
||||||
|
For example, to allow requests to https://linkding.mydomain.com, configure the setting to `https://linkding.mydomain.com`.
|
||||||
|
Note that the setting **must** include the correct protocol (`https` or `http`), and **must not** include the application / context path.
|
||||||
|
Multiple origins can be specified by separating them with a comma (`,`).
|
||||||
|
|
||||||
|
This setting is adopted from the Django framework used by linkding, more information on the setting is available in the [Django documentation](https://docs.djangoproject.com/en/4.0/ref/settings/#std-setting-CSRF_TRUSTED_ORIGINS).
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
# Troubleshooting
|
# Troubleshooting
|
||||||
|
|
||||||
|
## Login fails with `403 CSRF verfication failed`
|
||||||
|
|
||||||
|
This can be the case when using a reverse proxy that rewrites the `Host` header, such as Nginx.
|
||||||
|
Since linkding version 1.15, the application includes a CSRF check that verifies that the `Origin` request header matches the `Host` header.
|
||||||
|
If the `Host` header is modified by the reverse proxy then this check fails.
|
||||||
|
|
||||||
|
To fix this, check the [reverse proxy setup documentation](../README.md#reverse-proxy-setup) on how to configure header forwarding for your proxy server, or alternatively configure the [`LD_CSRF_TRUSTED_ORIGINS` option](Options.md#LD_CSRF_TRUSTED_ORIGINS) to the URL from which you are accessing your linkding instance.
|
||||||
|
|
||||||
## Import fails with `502 Bad Gateway`
|
## Import fails with `502 Bad Gateway`
|
||||||
|
|
||||||
The default timeout for requests is 60 seconds, after which the application server will cancel the request and return the above error.
|
The default timeout for requests is 60 seconds, after which the application server will cancel the request and return the above error.
|
||||||
|
|
|
@ -198,3 +198,9 @@ if LD_ENABLE_AUTH_PROXY:
|
||||||
# Configure logout URL
|
# Configure logout URL
|
||||||
if LD_AUTH_PROXY_LOGOUT_URL:
|
if LD_AUTH_PROXY_LOGOUT_URL:
|
||||||
LOGOUT_REDIRECT_URL = LD_AUTH_PROXY_LOGOUT_URL
|
LOGOUT_REDIRECT_URL = LD_AUTH_PROXY_LOGOUT_URL
|
||||||
|
|
||||||
|
# CSRF trusted origins
|
||||||
|
trusted_origins = os.getenv('LD_CSRF_TRUSTED_ORIGINS', '')
|
||||||
|
if trusted_origins:
|
||||||
|
CSRF_TRUSTED_ORIGINS = trusted_origins.split(',')
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue