Skip to content

Commit

Permalink
Fix SSO signon for SAML with idp (#10137)
Browse files Browse the repository at this point in the history
* #10135 add idp to saml login

* #10135 add idp to saml login

* #10135 add idp to saml login

* #10135 refactor / cleanup
  • Loading branch information
arthanson committed Sep 20, 2022
1 parent 63c6687 commit 50bd7b9
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 8 deletions.
4 changes: 4 additions & 0 deletions netbox/netbox/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ def get_auth_backend_display(name):
return AUTH_BACKEND_ATTRS.get(name, (name, None))


def get_saml_idps():
return getattr(settings, "SOCIAL_AUTH_SAML_ENABLED_IDPS", {}).keys()


class ObjectPermissionMixin:

def get_all_permissions(self, user_obj, obj=None):
Expand Down
6 changes: 3 additions & 3 deletions netbox/templates/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@

{% if auth_backends %}
<h6 class="mt-4 mb-3">Or use a single sign-on (SSO) provider:</h6>
{% for name, display in auth_backends.items %}
{% for backend in auth_backends %}
<h5>
{% if display.1 %}<i class="mdi mdi-{{ display.1 }}"></i>{% endif %}
<a href="{% url 'social:begin' backend=name %}" class="my-2">{{ display.0 }}</a>
{% if backend.icon_name %}<i class="mdi mdi-{{ backend.icon_name }}"></i>{% endif %}
<a href="{{ backend.url }}" class="my-2">{{ backend.display_name }}</a>
</h5>
{% endfor %}
{% endif %}
Expand Down
28 changes: 23 additions & 5 deletions netbox/users/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.utils.http import url_has_allowed_host_and_scheme
from django.utils.http import url_has_allowed_host_and_scheme, urlencode
from django.views.decorators.debug import sensitive_post_parameters
from django.views.generic import View
from social_core.backends.utils import load_backends

from extras.models import ObjectChange
from extras.tables import ObjectChangeTable
from netbox.authentication import get_auth_backend_display
from netbox.authentication import get_auth_backend_display, get_saml_idps
from netbox.config import get_config
from utilities.forms import ConfirmationForm
from .forms import LoginForm, PasswordChangeForm, TokenForm, UserConfigForm
Expand All @@ -38,16 +38,34 @@ class LoginView(View):
def dispatch(self, *args, **kwargs):
return super().dispatch(*args, **kwargs)

def gen_auth_data(self, name, url):
display_name, icon_name = get_auth_backend_display(name)
return {
'display_name': display_name,
'icon_name': icon_name,
'url': url,
}

def get(self, request):
form = LoginForm(request)

if request.user.is_authenticated:
logger = logging.getLogger('netbox.auth.login')
return self.redirect_to_next(request, logger)

auth_backends = {
name: get_auth_backend_display(name) for name in load_backends(settings.AUTHENTICATION_BACKENDS).keys()
}
auth_backends = []
saml_idps = get_saml_idps()
for name in load_backends(settings.AUTHENTICATION_BACKENDS).keys():
url = reverse('social:begin', args=[name, ])
if name.lower() == 'saml' and saml_idps:
for idp in saml_idps:
params = {'idp': idp}
idp_url = f'{url}?{urlencode(params)}'
data = self.gen_auth_data(name, idp_url)
data['display_name'] = f'{data["display_name"]} ({idp})'
auth_backends.append(data)
else:
auth_backends.append(self.gen_auth_data(name, url))

return render(request, self.template_name, {
'form': form,
Expand Down

0 comments on commit 50bd7b9

Please sign in to comment.