Skip to content

Commit b3ebe02

Browse files
authored
Merge pull request #51 from liquidpele/liquidpele-patch-2
Better error message around us choosing what binding to use
2 parents ed4661b + 9abd86f commit b3ebe02

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

djangosaml2/utils.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
from django.conf import settings
16+
from saml2.s_utils import UnknownSystemEntity
1617

1718

1819
def get_custom_setting(name, default=None):
@@ -33,6 +34,25 @@ def available_idps(config, langpref=None):
3334
return dict([(idp, config.metadata.name(idp, langpref)) for idp in idps])
3435

3536

37+
def get_idp_sso_supported_bindings(idp_entity_id=None, config=None):
38+
"""Returns the list of bindings supported by an IDP
39+
This is not clear in the pysaml2 code, so wrapping it in a util"""
40+
if config is None:
41+
# avoid circular import
42+
from djangosaml2.conf import get_config
43+
config = get_config()
44+
# load metadata store from config
45+
meta = getattr(config, 'metadata', {})
46+
# if idp is None, assume only one exists so just use that
47+
if idp_entity_id is None:
48+
# .keys() returns dict_keys in python3.5+
49+
idp_entity_id = list(available_idps(config).keys()).pop()
50+
try:
51+
return meta.service(idp_entity_id, 'idpsso_descriptor', 'single_sign_on_service').keys()
52+
except UnknownSystemEntity:
53+
return []
54+
55+
3656
def get_location(http_info):
3757
"""Extract the redirect URL from a pysaml2 http_info object"""
3858
assert 'headers' in http_info

djangosaml2/views.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,15 @@ def csrf_exempt(view_func):
4747
from saml2.metadata import entity_descriptor
4848
from saml2.ident import code, decode
4949
from saml2.sigver import MissingKey
50+
from saml2.s_utils import UnsupportedBinding
5051
from saml2.response import StatusError
5152
from saml2.xmldsig import SIG_RSA_SHA1 # support for this is required by spec
5253

5354
from djangosaml2.cache import IdentityCache, OutstandingQueriesCache
5455
from djangosaml2.cache import StateCache
5556
from djangosaml2.conf import get_config
5657
from djangosaml2.signals import post_authenticated
57-
from djangosaml2.utils import get_custom_setting, available_idps, get_location
58+
from djangosaml2.utils import get_custom_setting, available_idps, get_location, get_idp_sso_supported_bindings
5859

5960

6061
logger = logging.getLogger('djangosaml2')
@@ -138,7 +139,28 @@ def login(request,
138139
'came_from': came_from,
139140
})
140141

141-
binding = BINDING_HTTP_POST if getattr(conf, '_sp_authn_requests_signed', False) else BINDING_HTTP_REDIRECT
142+
# choose a binding to try first
143+
sign_requests = getattr(conf, '_sp_authn_requests_signed', False)
144+
binding = BINDING_HTTP_POST if sign_requests else BINDING_HTTP_REDIRECT
145+
logger.debug('Trying binding %s for IDP %s', binding, selected_idp)
146+
147+
# ensure our selected binding is supported by the IDP
148+
supported_bindings = get_idp_sso_supported_bindings(selected_idp, config=conf)
149+
if binding not in supported_bindings:
150+
logger.debug('Binding %s not in IDP %s supported bindings: %s',
151+
binding, selected_idp, supported_bindings)
152+
if binding == BINDING_HTTP_POST:
153+
logger.warning('IDP %s does not support %s, trying %s',
154+
selected_idp, binding, BINDING_HTTP_REDIRECT)
155+
binding = BINDING_HTTP_REDIRECT
156+
else:
157+
logger.warning('IDP %s does not support %s, trying %s',
158+
selected_idp, binding, BINDING_HTTP_POST)
159+
binding = BINDING_HTTP_POST
160+
# if switched binding still not supported, give up
161+
if binding not in supported_bindings:
162+
raise UnsupportedBinding('IDP %s does not support %s or %s',
163+
selected_idp, BINDING_HTTP_POST, BINDING_HTTP_REDIRECT)
142164

143165
client = Saml2Client(conf)
144166
http_response = None
@@ -187,7 +209,7 @@ def login(request,
187209
},
188210
})
189211
else:
190-
raise NotImplementedError('Unsupported binding: %s', binding)
212+
raise UnsupportedBinding('Unsupported binding: %s', binding)
191213

192214
# success, so save the session ID and return our response
193215
logger.debug('Saving the session_id in the OutstandingQueries cache')

0 commit comments

Comments
 (0)