Closes: #15842 - Option to hide local login form if SSO is in use (#18924)

Closes: #15842

Branched from #18145 by @tobiasge

Provides a new LOGIN_FORM_HIDDEN setting which allows the administrator to hide the local login form, intended only to be used when SSO is used exclusively for authentication. Note that this means local login will be impossible in the event of SSO provider issues, and can be remedied only through a change to the application config and a restart of the service.


* #15842 - Hide login form

This doesn't implement the full solution proposed in #15842 but enables
administrators to hide the login form when users should only login with a SSO
provider. To prevent a complete lockout when the SSO provider is having
issues the GET parameter `skipsso` can be added to the login URL to show
the form regardless.

* Remove skipsso backdoor

* Add warning

---------

Co-authored-by: Tobias Genannt <tobias.genannt@qbeyond.de>
This commit is contained in:
bctiemann 2025-03-17 13:02:18 -04:00 committed by GitHub
parent 1b4e00aeda
commit f69de12c6d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 57 additions and 33 deletions

View File

@ -186,6 +186,17 @@ The lifetime (in seconds) of the authentication cookie issued to a NetBox user u
---
## LOGIN_FORM_HIDDEN
Default: False
Option to hide the login form when only SSO authentication is in use.
!!! warning
If the SSO provider is unreachable, login to NetBox will be impossible if this option is enabled. The only recourse is to disable it in the local configuration and restart the NetBox service.
---
## LOGOUT_REDIRECT_URL
Default: `'home'`

View File

@ -89,10 +89,12 @@ class LoginView(View):
if request.user.is_authenticated:
logger = logging.getLogger('netbox.auth.login')
return self.redirect_to_next(request, logger)
login_form_hidden = settings.LOGIN_FORM_HIDDEN
return render(request, self.template_name, {
'form': form,
'auth_backends': self.get_auth_backends(request),
'login_form_hidden': login_form_hidden,
})
def post(self, request):

View File

@ -164,6 +164,9 @@ LOGIN_REQUIRED = True
# re-authenticate. (Default: 1209600 [14 days])
LOGIN_TIMEOUT = None
# Hide the login form. Useful when only allowing SSO authentication.
LOGIN_FORM_HIDDEN = False
# The view name or URL to which users are redirected after logging out.
LOGOUT_REDIRECT_URL = 'home'

View File

@ -129,6 +129,7 @@ LOGGING = getattr(configuration, 'LOGGING', {})
LOGIN_PERSISTENCE = getattr(configuration, 'LOGIN_PERSISTENCE', False)
LOGIN_REQUIRED = getattr(configuration, 'LOGIN_REQUIRED', True)
LOGIN_TIMEOUT = getattr(configuration, 'LOGIN_TIMEOUT', None)
LOGIN_FORM_HIDDEN = getattr(configuration, 'LOGIN_FORM_HIDDEN', False)
LOGOUT_REDIRECT_URL = getattr(configuration, 'LOGOUT_REDIRECT_URL', 'home')
MEDIA_ROOT = getattr(configuration, 'MEDIA_ROOT', os.path.join(BASE_DIR, 'media')).rstrip('/')
METRICS_ENABLED = getattr(configuration, 'METRICS_ENABLED', False)

View File

@ -34,6 +34,7 @@
{% endif %}
<div class="card card-md">
{% if not login_form_hidden %}
<div class="card-body">
<h2 class="text-center mb-4">{% trans "Log In" %}</h2>
@ -71,11 +72,17 @@
</div>
</form>
</div>
{% endif %}
{# SSO login #}
{% if auth_backends %}
{% if not login_form_hidden %}
<div class="hr-text">{% trans "Or" context "Denotes an alternative option" %}</div>
{% endif %}
<div class="card-body">
{% if login_form_hidden %}
<h2 class="text-center mb-4">{% trans "Log In" %}</h2>
{% endif %}
<div class="row">
{% for backend in auth_backends %}
<div class="col">