Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/configuration/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -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'`
Expand Down
2 changes: 2 additions & 0 deletions netbox/account/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,12 @@ def get(self, request):
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):
Expand Down
3 changes: 3 additions & 0 deletions netbox/netbox/configuration_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@
# 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'

Expand Down
1 change: 1 addition & 0 deletions netbox/netbox/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@
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)
Expand Down
73 changes: 40 additions & 33 deletions netbox/templates/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,48 +34,55 @@ <h4 class="alert-heading">{% trans "Errors" %}</h4>
{% endif %}

<div class="card card-md">
<div class="card-body">
<h2 class="text-center mb-4">{% trans "Log In" %}</h2>
{% if not login_form_hidden %}
<div class="card-body">
<h2 class="text-center mb-4">{% trans "Log In" %}</h2>

{# Login form #}
<form action="{% url 'login' %}" method="post">
{% csrf_token %}
{# Login form #}
<form action="{% url 'login' %}" method="post">
{% csrf_token %}

{# Set post-login URL #}
{% if 'next' in request.GET %}
<input type="hidden" name="next" value="{{ request.GET.next }}" />
{% elif 'next' in request.POST %}
<input type="hidden" name="next" value="{{ request.POST.next }}" />
{% endif %}
{# Set post-login URL #}
{% if 'next' in request.GET %}
<input type="hidden" name="next" value="{{ request.GET.next }}" />
{% elif 'next' in request.POST %}
<input type="hidden" name="next" value="{{ request.POST.next }}" />
{% endif %}

<div class="form-group mb-3">
<label for="id_username" class="form-label">{{ form.username.label }}</label>
{{ form.username }}
{% for error in form.username.errors %}
<div class="alert alert-danger">{{ error }}</div>
{% endfor %}
</div>
<div class="form-group mb-3">
<label for="id_username" class="form-label">{{ form.username.label }}</label>
{{ form.username }}
{% for error in form.username.errors %}
<div class="alert alert-danger">{{ error }}</div>
{% endfor %}
</div>

<div class="form-group">
<label for="id_password" class="form-label">{{ form.password.label }}</label>
{{ form.password }}
{% for error in form.password.errors %}
<div class="alert alert-danger">{{ error }}</div>
{% endfor %}
</div>
<div class="form-group">
<label for="id_password" class="form-label">{{ form.password.label }}</label>
{{ form.password }}
{% for error in form.password.errors %}
<div class="alert alert-danger">{{ error }}</div>
{% endfor %}
</div>

<div class="form-footer">
<button type="submit" class="btn btn-primary w-100">
{% trans "Sign In" %}
</button>
</div>
</form>
</div>
<div class="form-footer">
<button type="submit" class="btn btn-primary w-100">
{% trans "Sign In" %}
</button>
</div>
</form>
</div>
{% endif %}

{# SSO login #}
{% if auth_backends %}
<div class="hr-text">{% trans "Or" context "Denotes an alternative option" %}</div>
{% 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">
Expand Down