Allow to specify redirections on single IdP scenarios
In scenarios where the cloud operators have only a single Identity Provider, we can have a default redirection to remove unnecessary user clicks and improve user experience. Closes-bug: #1784368 Change-Id: I251703dcaeac43174fbcba7e0658c6f92098b2e0
This commit is contained in:
parent
a4443f4be7
commit
7fc8018956
@ -1522,6 +1522,49 @@ Default: ``"credentials"``
|
|||||||
Specifies the default authentication mechanism. When user lands on the login
|
Specifies the default authentication mechanism. When user lands on the login
|
||||||
page, this is the first choice they will see.
|
page, this is the first choice they will see.
|
||||||
|
|
||||||
|
WEBSSO_DEFAULT_REDIRECT
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. versionadded:: 15.0.0(Stein)
|
||||||
|
|
||||||
|
Default: ``False``
|
||||||
|
|
||||||
|
Allows to redirect on login to the IdP provider defined on PROTOCOL and REGION
|
||||||
|
In cases you have a single IdP providing websso, in order to improve user
|
||||||
|
experience, you can redirect on the login page to the IdP directly by
|
||||||
|
specifying WEBSSO_DEFAULT_REDIRECT_PROTOCOL and WEBSSO_DEFAULT_REDIRECT_REGION
|
||||||
|
variables.
|
||||||
|
|
||||||
|
WEBSSO_DEFAULT_REDIRECT_PROTOCOL
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. versionadded:: 15.0.0(Stein)
|
||||||
|
|
||||||
|
Default: ``None``
|
||||||
|
|
||||||
|
Allows to specify the protocol for the IdP to contact if the
|
||||||
|
WEBSSO_DEFAULT_REDIRECT is set to True
|
||||||
|
|
||||||
|
WEBSSO_DEFAULT_REDIRECT_REGION
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. versionadded:: 15.0.0(Stein)
|
||||||
|
|
||||||
|
Default: ``OPENSTACK_KEYSTONE_URL``
|
||||||
|
|
||||||
|
Allows to specify thee region of the IdP to contact if the
|
||||||
|
WEBSSO_DEFAULT_REDIRECT is set to True
|
||||||
|
|
||||||
|
WEBSSO_DEFAULT_REDIRECT_LOGOUT
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. versionadded:: 15.0.0(Stein)
|
||||||
|
|
||||||
|
Default: ``None``
|
||||||
|
|
||||||
|
Allows to specify a callback to the IdP to cleanup the SSO resources.
|
||||||
|
Once the user logs out it will redirect to the IdP log out method.
|
||||||
|
|
||||||
Neutron
|
Neutron
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
@ -1237,4 +1237,33 @@ class OpenStackAuthTestsWebSSO(OpenStackAuthTestsMixin,
|
|||||||
response = self.client.post(url, form_data)
|
response = self.client.post(url, form_data)
|
||||||
self.assertRedirects(response, settings.LOGIN_REDIRECT_URL)
|
self.assertRedirects(response, settings.LOGIN_REDIRECT_URL)
|
||||||
|
|
||||||
|
def test_websso_login_default_redirect(self):
|
||||||
|
origin = 'http://testserver/auth/websso/'
|
||||||
|
protocol = 'oidc'
|
||||||
|
redirect_url = ('%s/auth/OS-FEDERATION/websso/%s?origin=%s' %
|
||||||
|
(settings.OPENSTACK_KEYSTONE_URL, protocol, origin))
|
||||||
|
|
||||||
|
settings.WEBSSO_DEFAULT_REDIRECT = True
|
||||||
|
settings.WEBSSO_DEFAULT_REDIRECT_PROTOCOL = 'oidc'
|
||||||
|
settings.WEBSSO_DEFAULT_REDIRECT_REGION = (
|
||||||
|
settings.OPENSTACK_KEYSTONE_URL)
|
||||||
|
|
||||||
|
url = reverse('login')
|
||||||
|
|
||||||
|
# POST to the page and redirect to keystone.
|
||||||
|
response = self.client.get(url)
|
||||||
|
self.assertRedirects(response, redirect_url, status_code=302,
|
||||||
|
target_status_code=404)
|
||||||
|
|
||||||
|
def test_websso_logout_default_redirect(self):
|
||||||
|
settings.WEBSSO_DEFAULT_REDIRECT = True
|
||||||
|
settings.WEBSSO_DEFAULT_REDIRECT_LOGOUT = 'http://idptest/logout'
|
||||||
|
|
||||||
|
url = reverse('logout')
|
||||||
|
|
||||||
|
# POST to the page and redirect to logout method from idp.
|
||||||
|
response = self.client.get(url)
|
||||||
|
self.assertRedirects(response, settings.WEBSSO_DEFAULT_REDIRECT_LOGOUT,
|
||||||
|
status_code=302, target_status_code=301)
|
||||||
|
|
||||||
load_tests = load_tests_apply_scenarios
|
load_tests = load_tests_apply_scenarios
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
|
from django.views import generic
|
||||||
|
|
||||||
from openstack_auth import utils
|
from openstack_auth import utils
|
||||||
from openstack_auth import views
|
from openstack_auth import views
|
||||||
@ -33,4 +34,8 @@ urlpatterns = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
if utils.is_websso_enabled():
|
if utils.is_websso_enabled():
|
||||||
urlpatterns.append(url(r"^websso/$", views.websso, name='websso'))
|
urlpatterns += [
|
||||||
|
url(r"^websso/$", views.websso, name='websso'),
|
||||||
|
url(r"^error/$",
|
||||||
|
generic.TemplateView.as_view(template_name="403.html"))
|
||||||
|
]
|
||||||
|
@ -38,6 +38,16 @@ def set_session_from_user(request, user):
|
|||||||
request.user = user
|
request.user = user
|
||||||
|
|
||||||
|
|
||||||
|
def unset_session_user_variables(request):
|
||||||
|
request.session['token'] = None
|
||||||
|
request.session['user_id'] = None
|
||||||
|
request.session['region_endpoint'] = None
|
||||||
|
request.session['services_region'] = None
|
||||||
|
# Update the user object cached in the request
|
||||||
|
request._cached_user = None
|
||||||
|
request.user = None
|
||||||
|
|
||||||
|
|
||||||
def create_user_from_token(request, token, endpoint, services_region=None):
|
def create_user_from_token(request, token, endpoint, services_region=None):
|
||||||
# if the region is provided, use that, otherwise use the preferred region
|
# if the region is provided, use that, otherwise use the preferred region
|
||||||
svc_region = services_region or \
|
svc_region = services_region or \
|
||||||
|
@ -146,6 +146,30 @@ def is_websso_enabled():
|
|||||||
return websso_enabled and keystonev3_plus
|
return websso_enabled and keystonev3_plus
|
||||||
|
|
||||||
|
|
||||||
|
def is_websso_default_redirect():
|
||||||
|
"""Checks if the websso default redirect is available.
|
||||||
|
|
||||||
|
As with websso, this is only supported in Keystone version 3.
|
||||||
|
"""
|
||||||
|
websso_default_redirect = getattr(settings,
|
||||||
|
'WEBSSO_DEFAULT_REDIRECT', False)
|
||||||
|
keystonev3_plus = (get_keystone_version() >= 3)
|
||||||
|
return websso_default_redirect and keystonev3_plus
|
||||||
|
|
||||||
|
|
||||||
|
def get_websso_default_redirect_protocol():
|
||||||
|
return getattr(settings, 'WEBSSO_DEFAULT_REDIRECT_PROTOCOL', None)
|
||||||
|
|
||||||
|
|
||||||
|
def get_websso_default_redirect_region():
|
||||||
|
return getattr(settings, 'WEBSSO_DEFAULT_REDIRECT_REGION',
|
||||||
|
settings.OPENSTACK_KEYSTONE_URL)
|
||||||
|
|
||||||
|
|
||||||
|
def get_websso_default_redirect_logout():
|
||||||
|
return getattr(settings, 'WEBSSO_DEFAULT_REDIRECT_LOGOUT', None)
|
||||||
|
|
||||||
|
|
||||||
def build_absolute_uri(request, relative_url):
|
def build_absolute_uri(request, relative_url):
|
||||||
"""Ensure absolute_uri are relative to WEBROOT."""
|
"""Ensure absolute_uri are relative to WEBROOT."""
|
||||||
webroot = getattr(settings, 'WEBROOT', '')
|
webroot = getattr(settings, 'WEBROOT', '')
|
||||||
|
@ -55,6 +55,17 @@ LOG = logging.getLogger(__name__)
|
|||||||
def login(request, template_name=None, extra_context=None, **kwargs):
|
def login(request, template_name=None, extra_context=None, **kwargs):
|
||||||
"""Logs a user in using the :class:`~openstack_auth.forms.Login` form."""
|
"""Logs a user in using the :class:`~openstack_auth.forms.Login` form."""
|
||||||
|
|
||||||
|
# If the user enabled websso and the default redirect
|
||||||
|
# redirect to the default websso url
|
||||||
|
if (request.method == 'GET' and utils.is_websso_enabled and
|
||||||
|
utils.is_websso_default_redirect()):
|
||||||
|
protocol = utils.get_websso_default_redirect_protocol()
|
||||||
|
region = utils.get_websso_default_redirect_region()
|
||||||
|
origin = request.build_absolute_uri('/auth/websso/')
|
||||||
|
url = ('%s/auth/OS-FEDERATION/websso/%s?origin=%s' %
|
||||||
|
(region, protocol, origin))
|
||||||
|
return shortcuts.redirect(url)
|
||||||
|
|
||||||
# If the user enabled websso and selects default protocol
|
# If the user enabled websso and selects default protocol
|
||||||
# from the dropdown, We need to redirect user to the websso url
|
# from the dropdown, We need to redirect user to the websso url
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
@ -151,9 +162,12 @@ def websso(request):
|
|||||||
request.user = auth.authenticate(request=request, auth_url=auth_url,
|
request.user = auth.authenticate(request=request, auth_url=auth_url,
|
||||||
token=token)
|
token=token)
|
||||||
except exceptions.KeystoneAuthException as exc:
|
except exceptions.KeystoneAuthException as exc:
|
||||||
msg = 'Login failed: %s' % six.text_type(exc)
|
if utils.is_websso_default_redirect():
|
||||||
res = django_http.HttpResponseRedirect(settings.LOGIN_URL)
|
res = django_http.HttpResponseRedirect(settings.LOGIN_ERROR)
|
||||||
res.set_cookie('logout_reason', msg, max_age=10)
|
else:
|
||||||
|
msg = 'Login failed: %s' % six.text_type(exc)
|
||||||
|
res = django_http.HttpResponseRedirect(settings.LOGIN_URL)
|
||||||
|
res.set_cookie('logout_reason', msg, max_age=10)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
auth_user.set_session_from_user(request, request.user)
|
auth_user.set_session_from_user(request, request.user)
|
||||||
@ -178,8 +192,15 @@ def logout(request, login_url=None, **kwargs):
|
|||||||
LOG.info(msg)
|
LOG.info(msg)
|
||||||
|
|
||||||
""" Securely logs a user out. """
|
""" Securely logs a user out. """
|
||||||
return django_auth_views.logout_then_login(request, login_url=login_url,
|
if (utils.is_websso_enabled and utils.is_websso_default_redirect() and
|
||||||
**kwargs)
|
utils.get_websso_default_redirect_logout()):
|
||||||
|
auth_user.unset_session_user_variables(request)
|
||||||
|
return django_http.HttpResponseRedirect(
|
||||||
|
utils.get_websso_default_redirect_logout())
|
||||||
|
else:
|
||||||
|
return django_auth_views.logout_then_login(request,
|
||||||
|
login_url=login_url,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -26,6 +26,7 @@ DEBUG = True
|
|||||||
WEBROOT = '/'
|
WEBROOT = '/'
|
||||||
#LOGIN_URL = WEBROOT + 'auth/login/'
|
#LOGIN_URL = WEBROOT + 'auth/login/'
|
||||||
#LOGOUT_URL = WEBROOT + 'auth/logout/'
|
#LOGOUT_URL = WEBROOT + 'auth/logout/'
|
||||||
|
#LOGIN_ERROR = WEBROOT + 'auth/error/'
|
||||||
#
|
#
|
||||||
# LOGIN_REDIRECT_URL can be used as an alternative for
|
# LOGIN_REDIRECT_URL can be used as an alternative for
|
||||||
# HORIZON_CONFIG.user_home, if user_home is not set.
|
# HORIZON_CONFIG.user_home, if user_home is not set.
|
||||||
@ -231,6 +232,21 @@ OPENSTACK_KEYSTONE_DEFAULT_ROLE = "_member_"
|
|||||||
# "acme_saml2": ("acme", "saml2"),
|
# "acme_saml2": ("acme", "saml2"),
|
||||||
#}
|
#}
|
||||||
|
|
||||||
|
# Enables redirection on login to the identity provider defined on
|
||||||
|
# WEBSSO_DEFAULT_REDIRECT_PROTOCOL and WEBSSO_DEFAULT_REDIRECT_REGION
|
||||||
|
#WEBSSO_DEFAULT_REDIRECT = False
|
||||||
|
|
||||||
|
# Specifies the protocol to use for default redirection on login
|
||||||
|
#WEBSSO_DEFAULT_REDIRECT_PROTOCOL = None
|
||||||
|
|
||||||
|
# Specifies the region to which the connection will be established on login
|
||||||
|
#WEBSSO_DEFAULT_REDIRECT_REGION = OPENSTACK_KEYSTONE_URL
|
||||||
|
|
||||||
|
# Enables redirection on logout to the method specified on the identity provider.
|
||||||
|
# Once logout the client will be redirected to the address specified in this
|
||||||
|
# variable.
|
||||||
|
#WEBSSO_DEFAULT_REDIRECT_LOGOUT = None
|
||||||
|
|
||||||
# The Keystone Provider drop down uses Keystone to Keystone federation
|
# The Keystone Provider drop down uses Keystone to Keystone federation
|
||||||
# to switch between Keystone service providers.
|
# to switch between Keystone service providers.
|
||||||
# Set display name for Identity Provider (dropdown display name)
|
# Set display name for Identity Provider (dropdown display name)
|
||||||
|
@ -54,6 +54,7 @@ SITE_BRANDING = 'OpenStack Dashboard'
|
|||||||
WEBROOT = '/'
|
WEBROOT = '/'
|
||||||
LOGIN_URL = None
|
LOGIN_URL = None
|
||||||
LOGOUT_URL = None
|
LOGOUT_URL = None
|
||||||
|
LOGIN_ERROR = None
|
||||||
LOGIN_REDIRECT_URL = None
|
LOGIN_REDIRECT_URL = None
|
||||||
MEDIA_ROOT = None
|
MEDIA_ROOT = None
|
||||||
MEDIA_URL = None
|
MEDIA_URL = None
|
||||||
@ -418,6 +419,8 @@ if LOGIN_URL is None:
|
|||||||
LOGIN_URL = WEBROOT + 'auth/login/'
|
LOGIN_URL = WEBROOT + 'auth/login/'
|
||||||
if LOGOUT_URL is None:
|
if LOGOUT_URL is None:
|
||||||
LOGOUT_URL = WEBROOT + 'auth/logout/'
|
LOGOUT_URL = WEBROOT + 'auth/logout/'
|
||||||
|
if LOGIN_ERROR is None:
|
||||||
|
LOGIN_ERROR = WEBROOT + 'auth/error/'
|
||||||
if LOGIN_REDIRECT_URL is None:
|
if LOGIN_REDIRECT_URL is None:
|
||||||
LOGIN_REDIRECT_URL = WEBROOT
|
LOGIN_REDIRECT_URL = WEBROOT
|
||||||
|
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Adds the possibility to redirect the login to an identity provider by
|
||||||
|
default. For that purpose the following variables have been added,
|
||||||
|
``WEBSSO_DEFAULT_REDIRECT``, ``WEBSSO_DEFAULT_REDIRECT_PROTOCOL``,
|
||||||
|
``WEBSSO_DEFAULT_REDIRECT_REGION`` and ``WEBSSO_DEFAULT_REDIRECT_LOGOUT``.
|
Loading…
x
Reference in New Issue
Block a user