Skip to content

Commit 7fc8370

Browse files
committed
Related to PR 83. extract the already encoded value directly from
1 parent 48ca756 commit 7fc8370

6 files changed

Lines changed: 32 additions & 6 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,8 @@ Auxiliary class that contains several methods
925925
* ***add_sign*** Adds signature key and senders certificate to an element (Message or Assertion).
926926
* ***validate_sign*** Validates a signature (Message or Assertion).
927927
* ***validate_binary_sign*** Validates signed bynary data (Used to validate GET Signature).
928+
* ***def get_encoded_parameter*** Return an url encoded get parameter value
929+
* ***extract_raw_query_parameter***
928930

929931
####OneLogin_Saml2_IdPMetadataParser - idp_metadata_parser.py####
930932

demo-bottle/index.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ def prepare_bottle_request(req):
3535
'script_name': req.fullpath,
3636
'get_data': req.query,
3737
'post_data': req.forms,
38+
'query_string': req.query_string,
3839
'https': 'on' if req.urlparts.scheme == 'https' else 'off'
3940
}
4041

demo-django/demo/views.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ def prepare_django_request(request):
2323
'script_name': request.META['PATH_INFO'],
2424
'server_port': request.META['SERVER_PORT'],
2525
'get_data': request.GET.copy(),
26-
'post_data': request.POST.copy()
26+
'post_data': request.POST.copy(),
27+
'query_string': req.query_string
2728
}
2829
return result
2930

demo-flask/index.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ def prepare_flask_request(request):
2828
'server_port': url_data.port,
2929
'script_name': request.path,
3030
'get_data': request.args.copy(),
31-
'post_data': request.form.copy()
31+
'post_data': request.form.copy(),
32+
'query_string': req.query_string
3233
}
3334

3435

src/onelogin/saml2/logout_request.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
from base64 import b64encode, b64decode
1414
from lxml import etree
1515
from defusedxml.lxml import fromstring
16-
from urllib import quote_plus
1716
from xml.dom.minidom import Document
1817

1918
from onelogin.saml2.constants import OneLogin_Saml2_Constants
@@ -317,10 +316,10 @@ def is_valid(self, request_data):
317316
else:
318317
sign_alg = get_data['SigAlg']
319318

320-
signed_query = 'SAMLRequest=%s' % quote_plus(get_data['SAMLRequest'])
319+
signed_query = 'SAMLRequest=%s' % OneLogin_Saml2_Utils.get_encoded_parameter(get_data, 'SAMLRequest')
321320
if 'RelayState' in get_data:
322-
signed_query = '%s&RelayState=%s' % (signed_query, quote_plus(get_data['RelayState']))
323-
signed_query = '%s&SigAlg=%s' % (signed_query, quote_plus(sign_alg))
321+
signed_query = '%s&RelayState=%s' % (signed_query, OneLogin_Saml2_Utils.get_encoded_parameter(get_data, 'RelayState'))
322+
signed_query = '%s&SigAlg=%s' % (signed_query, OneLogin_Saml2_Utils.get_encoded_parameter(get_data, 'SigAlg', OneLogin_Saml2_Constants.RSA_SHA1))
324323

325324
if 'x509cert' not in idp_data or idp_data['x509cert'] is None:
326325
raise Exception('In order to validate the sign on the Logout Request, the x509cert of the IdP is required')

src/onelogin/saml2/utils.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,3 +1127,25 @@ def validate_binary_sign(signed_query, signature, cert=None, algorithm=OneLogin_
11271127
return True
11281128
except Exception:
11291129
return False
1130+
1131+
@staticmethod
1132+
def get_encoded_parameter(get_data, name, default=None):
1133+
"""Return an url encoded get parameter value
1134+
Prefer to extract the original encoded value directly from query_string since url
1135+
encoding is not canonical. The encoding used by ADFS 3.0 is not compatible with
1136+
python's quote_plus (ADFS produces lower case hex numbers and quote_plus produces
1137+
upper case hex numbers)
1138+
"""
1139+
if name not in get_data:
1140+
return quote_plus(default)
1141+
if 'query_string' in get_data:
1142+
return OneLogin_Saml2_Utils.extract_raw_query_parameter(get_data['query_string'], name)
1143+
return quote_plus(get_data[name])
1144+
1145+
@staticmethod
1146+
def extract_raw_query_parameter(query_string, parameter, default=''):
1147+
m = re.search('%s=([^&]+)' % parameter, query_string)
1148+
if m:
1149+
return m.group(1)
1150+
else:
1151+
return default

0 commit comments

Comments
 (0)