Skip to content

Commit 2f80dbb

Browse files
authored
Merge pull request #148 from chander/chander-saml-redirect-enhancement
User specified hostnames for redirect
2 parents 521089e + 1016cdd commit 2f80dbb

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

README.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,24 @@ If you want to allow several authentication mechanisms in your project
113113
you should set the LOGIN_URL option to another view and put a link in such
114114
view to the ``/saml2/login/`` view.
115115

116+
Handling Post-Login Redirects
117+
-----------------------------
118+
It is often desireable for the client to maintain the URL state (or at least manage it) so that
119+
the URL once authentication has completed is consistent with the desired application state (such
120+
as retaining query parameters, etc.) By default, the HttpRequest objects get_host() method is used
121+
to determine the hostname of the server, and redirect URL's are allowed so long as the destination
122+
host matches the output of get_host(). However, in some cases it becomes desireable for additional
123+
hostnames to be used for the post-login redirect. In such cases, the setting::
124+
125+
SAML_ALLOWED_HOSTS = []
126+
127+
May be set to a list of allowed post-login redirect hostnames (note, the URL components beyond the hostname
128+
may be specified by the client - typically with the ?next= parameter.)
129+
130+
In the absence of a ?next= parameter, the LOGIN_REDIRECT_URL setting will be used (assuming the destination hostname
131+
either matches the output of get_host() or is included in the SAML_ALLOWED_HOSTS setting)
132+
133+
116134
Preferred Logout binding
117135
------------------------
118136
Use the following setting to choose your preferred binding for SP initiated logout requests::

djangosaml2/views.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,16 @@ def login(request,
105105
came_from = settings.LOGIN_REDIRECT_URL
106106

107107
# Ensure the user-originating redirection url is safe.
108-
if not is_safe_url(url=came_from, allowed_hosts={request.get_host()}):
108+
# By setting SAML_ALLOWED_HOSTS in settings.py the user may provide a list of "allowed"
109+
# hostnames for post-login redirects, much like one would specify ALLOWED_HOSTS .
110+
# If this setting is absent, the default is to use the hostname that was used for the current
111+
# request.
112+
saml_allowed_hosts = set(getattr(settings, 'SAML_ALLOWED_HOSTS', [request.get_host()]))
113+
114+
if not is_safe_url(url=came_from, allowed_hosts=saml_allowed_hosts):
109115
came_from = settings.LOGIN_REDIRECT_URL
110116

117+
111118
# if the user is already authenticated that maybe because of two reasons:
112119
# A) He has this URL in two browser windows and in the other one he
113120
# has already initiated the authenticated session.
@@ -348,7 +355,15 @@ def assertion_consumer_service(request,
348355
if not relay_state:
349356
logger.warning('The RelayState parameter exists but is empty')
350357
relay_state = default_relay_state
351-
if not is_safe_url(url=relay_state, allowed_hosts={request.get_host()}):
358+
359+
# Ensure the user-originating redirection url is safe.
360+
# By setting SAML_ALLOWED_HOSTS in settings.py the user may provide a list of "allowed"
361+
# hostnames for post-login redirects, much like one would specify ALLOWED_HOSTS .
362+
# If this setting is absent, the default is to use the hostname that was used for the current
363+
# request.
364+
saml_allowed_hosts = set(getattr(settings, 'SAML_ALLOWED_HOSTS', [request.get_host()]))
365+
366+
if not is_safe_url(url=relay_state, allowed_hosts=saml_allowed_hosts):
352367
relay_state = settings.LOGIN_REDIRECT_URL
353368
logger.debug('Redirecting to the RelayState: %s', relay_state)
354369
return HttpResponseRedirect(relay_state)

0 commit comments

Comments
 (0)