Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Assertion Consumer Service HTTP-Redirect binding. #71

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
25 changes: 19 additions & 6 deletions src/onelogin/saml2/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
import dm.xmlsec.binding as xmlsec

from onelogin.saml2.settings import OneLogin_Saml2_Settings
from onelogin.saml2.response import OneLogin_Saml2_Response
from onelogin.saml2.response import (
OneLogin_Saml2_Response_Post, OneLogin_Saml2_Response_Redirect)
from onelogin.saml2.errors import OneLogin_Saml2_Error
from onelogin.saml2.logout_response import OneLogin_Saml2_Logout_Response
from onelogin.saml2.constants import OneLogin_Saml2_Constants
Expand Down Expand Up @@ -87,9 +88,22 @@ def process_response(self, request_id=None):
"""
self.__errors = []

if 'post_data' in self.__request_data and 'SAMLResponse' in self.__request_data['post_data']:
# AuthnResponse -- HTTP_POST Binding
response = OneLogin_Saml2_Response(self.__settings, self.__request_data['post_data']['SAMLResponse'])
sp_data = self.get_settings().get_sp_data()
acs_binding = sp_data['assertionConsumerService'].get(
'binding', OneLogin_Saml2_Constants.BINDING_HTTP_POST
)

# finds what attribute to access given the configured binding.
if acs_binding == OneLogin_Saml2_Constants.BINDING_HTTP_REDIRECT:
response_class = OneLogin_Saml2_Response_Redirect
response_attr = 'get_data'
else:
response_class = OneLogin_Saml2_Response_Post
response_attr = 'post_data'

if response_attr in self.__request_data and 'SAMLResponse' in self.__request_data[response_attr]:
response = response_class(
self.__settings, self.__request_data[response_attr]['SAMLResponse'])

if response.is_valid(self.__request_data, request_id):
self.__attributes = response.get_attributes()
Expand All @@ -100,11 +114,10 @@ def process_response(self, request_id=None):
else:
self.__errors.append('invalid_response')
self.__error_reason = response.get_error()

else:
self.__errors.append('invalid_binding')
raise OneLogin_Saml2_Error(
'SAML Response not found, Only supported HTTP_POST Binding',
'SAML Response not found for binding %s' % acs_binding.split(':')[-1],
OneLogin_Saml2_Error.SAML_RESPONSE_NOT_FOUND
)

Expand Down
10 changes: 9 additions & 1 deletion src/onelogin/saml2/authn_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ def __init__(self, settings, force_authn=False, is_passive=False):
if is_passive is True:
is_passive_str = 'IsPassive="true"'

# to keep backwards compatibility, use POST binding by default
# for configurations that didn't specified one, since it
# wasn't required previously.
acs_binding = sp_data['assertionConsumerService'].get(
'binding', OneLogin_Saml2_Constants.BINDING_HTTP_POST
)

requested_authn_context_str = ''
if 'requestedAuthnContext' in security.keys() and security['requestedAuthnContext'] is not False:
if security['requestedAuthnContext'] is True:
Expand All @@ -94,7 +101,7 @@ def __init__(self, settings, force_authn=False, is_passive=False):
%(is_passive_str)s
IssueInstant="%(issue_instant)s"
Destination="%(destination)s"
ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
ProtocolBinding="%(acs_binding)s"
AssertionConsumerServiceURL="%(assertion_url)s">
<saml:Issuer>%(entity_id)s</saml:Issuer>
<samlp:NameIDPolicy
Expand All @@ -113,6 +120,7 @@ def __init__(self, settings, force_authn=False, is_passive=False):
'entity_id': sp_data['entityId'],
'name_id_policy': name_id_policy_format,
'requested_authn_context_str': requested_authn_context_str,
'acs_binding': acs_binding
}

self.__authn_request = request
Expand Down