Feature: automatic sso redirect (#7168)

This commit is contained in:
shamoon 2024-07-08 15:38:23 -07:00 committed by GitHub
parent ada283441c
commit c03aa03ac2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 54 additions and 13 deletions

View File

@ -687,4 +687,5 @@ More details about configuration option for various providers can be found in th
### Disabling Regular Login
Once external auth is set up, 'regular' login can be disabled with the [PAPERLESS_DISABLE_REGULAR_LOGIN](configuration.md#PAPERLESS_DISABLE_REGULAR_LOGIN) setting.
Once external auth is set up, 'regular' login can be disabled with the [PAPERLESS_DISABLE_REGULAR_LOGIN](configuration.md#PAPERLESS_DISABLE_REGULAR_LOGIN) setting and / or users can be automatically
redirected with the [PAPERLESS_REDIRECT_LOGIN_TO_SSO](configuration.md#PAPERLESS_REDIRECT_LOGIN_TO_SSO) setting.

View File

@ -596,6 +596,14 @@ system. See the corresponding
: Disables the regular frontend username / password login, i.e. once you have setup SSO. Note that this setting does not disable the Django admin login. To prevent logins directly to Django, consider blocking `/admin/` in your [web server or reverse proxy configuration](https://github.com/paperless-ngx/paperless-ngx/wiki/Using-a-Reverse-Proxy-with-Paperless-ngx).
You can optionally also automatically redirect users to the SSO login with [PAPERLESS_REDIRECT_LOGIN_TO_SSO](#PAPERLESS_REDIRECT_LOGIN_TO_SSO)
Defaults to False
#### ['PAPERLESS_REDIRECT_LOGIN_TO_SSO=<bool>`](#PAPERLESS_REDIRECT_LOGIN_TO_SSO) {#PAPERLESS_REDIRECT_LOGIN_TO_SSO}
: When this setting is enabled users will automatically be redirected (using javascript) to the first SSO provider login. You may still want to disable the frontend login form for clarity.
Defaults to False
#### [`PAPERLESS_ACCOUNT_SESSION_REMEMBER=<bool>`](#PAPERLESS_ACCOUNT_SESSION_REMEMBER) {#PAPERLESS_ACCOUNT_SESSION_REMEMBER}

View File

@ -21,6 +21,7 @@ def settings(request):
"EMAIL_ENABLED": django_settings.EMAIL_HOST != "localhost"
or django_settings.EMAIL_HOST_USER != "",
"DISABLE_REGULAR_LOGIN": django_settings.DISABLE_REGULAR_LOGIN,
"REDIRECT_LOGIN_TO_SSO": django_settings.REDIRECT_LOGIN_TO_SSO,
"ACCOUNT_ALLOW_SIGNUPS": django_settings.ACCOUNT_ALLOW_SIGNUPS,
"domain": getattr(django_settings, "PAPERLESS_URL", request.get_host()),
"APP_TITLE": app_title,

View File

@ -49,16 +49,28 @@
{% if provider.id == "openid" %}
{% for brand in provider.get_brands %}
{% provider_login_url provider openid=brand.openid_url process=process as href %}
<li class="d-grid mt-3"><a class="btn btn-secondary" href="{{ href }}">{{ brand.name }}</a></li>
<li class="d-grid mt-3"><a class="btn btn-secondary oidc-url" href="{{ href }}">{{ brand.name }}</a></li>
{% endfor %}
{% else %}
{% provider_login_url provider process=process scope=scope auth_params=auth_params as href %}
<li class="d-grid mt-3">
<form class="d-grid" method="POST" action="{{ href }}">
{% csrf_token %}
<button type="submit" class="btn btn-secondary">{{ provider.name }}</button>
</form>
</li>
{% provider_login_url provider process=process scope=scope auth_params=auth_params as href %}
<li class="d-grid mt-3">
<form id="social-login" class="d-grid" method="POST" action="{{ href }}">
{% csrf_token %}
<button type="submit" class="btn btn-secondary">{{ provider.name }}</button>
</form>
</li>
{% if REDIRECT_LOGIN_TO_SSO and forloop.counter0 == 0 and request.GET.loggedout != '1' %}
<script type="text/javascript">
const form = document.getElementById('social-login');
if (form) {
form.submit();
} else {
if (document.getElementsByClassName('oidc-url').length > 0) {
document.getElementsByClassName('oidc-url')[0].click();
}
}
</script>
{% endif %}
{% endif %}
{% endfor %}
</ul>

View File

@ -18,7 +18,7 @@
<body class="text-center">
<div class="position-absolute top-50 start-50 translate-middle">
<form class="form-accounts" method="post">
<form class="form-accounts" id="form-account" method="post">
{% csrf_token %}
{% if not APP_LOGO and not APP_TITLE %}
{% include "paperless-ngx/snippets/svg_logo.html" with extra_attrs="width='300' class='logo mb-4'" %}

View File

@ -12,4 +12,13 @@
<div class="d-grid mt-3">
<button class="btn btn-lg btn-primary" type="submit">{% translate "Continue" %}</button>
</div>
{% if REDIRECT_LOGIN_TO_SSO %}
<script type="text/javascript">
const form = document.getElementById('form-account');
if (form) {
form.submit();
}
</script>
{% endif %}
{% endblock form_content %}

View File

@ -369,7 +369,10 @@ def _parse_base_paths() -> tuple[str, str, str, str, str]:
base_url = (script_name or "") + "/"
login_url = base_url + "accounts/login/"
login_redirect_url = base_url + "dashboard"
logout_redirect_url = os.getenv("PAPERLESS_LOGOUT_REDIRECT_URL", base_url)
logout_redirect_url = os.getenv(
"PAPERLESS_LOGOUT_REDIRECT_URL",
login_url + "?loggedout=1",
)
return script_name, base_url, login_url, login_redirect_url, logout_redirect_url
@ -460,6 +463,7 @@ SOCIALACCOUNT_PROVIDERS = json.loads(
ACCOUNT_EMAIL_SUBJECT_PREFIX = "[Paperless-ngx] "
DISABLE_REGULAR_LOGIN = __get_boolean("PAPERLESS_DISABLE_REGULAR_LOGIN")
REDIRECT_LOGIN_TO_SSO = __get_boolean("PAPERLESS_REDIRECT_LOGIN_TO_SSO")
AUTO_LOGIN_USERNAME = os.getenv("PAPERLESS_AUTO_LOGIN_USERNAME")

View File

@ -410,7 +410,10 @@ class TestPathSettings(TestCase):
self.assertEqual("/", base_paths[1]) # BASE_URL
self.assertEqual("/accounts/login/", base_paths[2]) # LOGIN_URL
self.assertEqual("/dashboard", base_paths[3]) # LOGIN_REDIRECT_URL
self.assertEqual("/", base_paths[4]) # LOGOUT_REDIRECT_URL
self.assertEqual(
"/accounts/login/?loggedout=1",
base_paths[4],
) # LOGOUT_REDIRECT_URL
@mock.patch("os.environ", {"PAPERLESS_FORCE_SCRIPT_NAME": "/paperless"})
def test_subpath(self):
@ -427,7 +430,10 @@ class TestPathSettings(TestCase):
self.assertEqual("/paperless/", base_paths[1]) # BASE_URL
self.assertEqual("/paperless/accounts/login/", base_paths[2]) # LOGIN_URL
self.assertEqual("/paperless/dashboard", base_paths[3]) # LOGIN_REDIRECT_URL
self.assertEqual("/paperless/", base_paths[4]) # LOGOUT_REDIRECT_URL
self.assertEqual(
"/paperless/accounts/login/?loggedout=1",
base_paths[4],
) # LOGOUT_REDIRECT_URL
@mock.patch(
"os.environ",