Hello community,

here is the log from the commit of package python-python3-saml for 
openSUSE:Factory checked in at 2019-07-22 17:20:06
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-python3-saml (Old)
 and      /work/SRC/openSUSE:Factory/.python-python3-saml.new.4126 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-python3-saml"

Mon Jul 22 17:20:06 2019 rev:2 rq:717586 version:1.7.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-python3-saml/python-python3-saml.changes  
2019-05-06 13:21:33.800559810 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-python3-saml.new.4126/python-python3-saml.changes
        2019-07-22 17:20:07.573898804 +0200
@@ -1,0 +2,13 @@
+Mon Jul 22 13:05:59 UTC 2019 - Tomáš Chvátal <tchva...@suse.com>
+
+- Update to 1.7.0:
+  * Adjusted acs endpoint to extract NameQualifier and SPNameQualifier from
+    SAMLResponse.
+  * Adjusted single logout service to provide NameQualifier and SPNameQualifier
+    to logout method.
+  * Add getNameIdNameQualifier to Auth and SamlResponse.
+  * Extend logout method from Auth and LogoutRequest constructor to support.
+  * Added get_in_response_to method to Response and LogoutResponse classes
+  * Update defusexml dependency
+
+-------------------------------------------------------------------

Old:
----
  python3-saml-1.6.0.tar.gz

New:
----
  python3-saml-1.7.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-python3-saml.spec ++++++
--- /var/tmp/diff_new_pack.GZjvOr/_old  2019-07-22 17:20:08.893898444 +0200
+++ /var/tmp/diff_new_pack.GZjvOr/_new  2019-07-22 17:20:08.941898430 +0200
@@ -18,13 +18,13 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-python3-saml
-Version:        1.6.0
+Version:        1.7.0
 Release:        0
 Summary:        Python SAML support
 License:        MIT
 Group:          Development/Languages/Python
 URL:            https://github.com/onelogin/python3-saml
-Source:         
https://github.com/onelogin/python3-saml/archive/v%{version}.tar.gz#/python3-saml-%{version}.tar.gz
+Source:         
https://github.com/onelogin/python3-saml/archive/v.%{version}.tar.gz#/python3-saml-%{version}.tar.gz
 Patch0:         bug-testDecryptElement.patch
 BuildRequires:  %{python_module defusedxml >= 0.5.0}
 BuildRequires:  %{python_module freezegun >= 0.3.11}
@@ -50,7 +50,7 @@
 defined by the OASIS Security Services Technical Committee.
 
 %prep
-%setup -q -n python3-saml-%{version}
+%setup -q -n python3-saml-v.%{version}
 %patch0 -p1
 sed -i 's/==/>=/;/dependency_links/d' setup.py
 

++++++ python3-saml-1.6.0.tar.gz -> python3-saml-1.7.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-saml-1.6.0/README.md 
new/python3-saml-v.1.7.0/README.md
--- old/python3-saml-1.6.0/README.md    2019-04-10 00:27:34.000000000 +0200
+++ new/python3-saml-v.1.7.0/README.md  2019-07-02 20:09:38.000000000 +0200
@@ -10,7 +10,7 @@
 Forget those complicated libraries and use the open source library provided
 and supported by OneLogin Inc.
 
-This version supports Python3. There is a separate version that only support 
Python2: [python-saml](https://pypi.python.org/pypi/python-saml)
+This version supports Python3. There is a separate version that only support 
Python2: [python-saml](https://github.com/onelogin/python-saml)
 
 #### Warning ####
 
@@ -100,7 +100,7 @@
 
 The toolkit is hosted on GitHub. You can download it from:
 
- * Lastest release: https://github.com/onelogin/python3-saml/releases/latest
+ * Latest release: https://github.com/onelogin/python3-saml/releases/latest
  * Master repo: https://github.com/onelogin/python3-saml/tree/master
 
 Copy the core of the library ``(src/onelogin/saml2 folder)`` and merge the 
``setup.py`` inside the Python application. (Each application has its structure 
so take your time to locate the Python SAML toolkit in the best place).
@@ -794,17 +794,17 @@
 auth.logout(return_to=target_url)
 ```
 
-Also there are 4 optional parameters that can be set:
+Also there are another 5 optional parameters that can be set:
 
 * ``name_id``: That will be used to build the ``LogoutRequest``. If no 
``name_id`` parameter is set and the auth object processed a
 SAML Response with a ``NameId``, then this ``NameId`` will be used.
 * ``session_index``: ``SessionIndex`` that identifies the session of the user.
 * ``nq``: IDP Name Qualifier.
 * ``name_id_format``: The ``NameID`` Format that will be set in the 
``LogoutRequest``.
+* ``spnq``: The ``NameID SP NameQualifier`` will be set in the 
``LogoutRequest``.
 
 If no ``name_id`` is provided, the ``LogoutRequest`` will contain a ``NameID`` 
with the entity Format.
 If ``name_id`` is provided and no ``name_id_format`` is provided, the 
``NameIDFormat`` of the settings will be used.
-If ``nq`` is provided, the ``SPNameQualifier`` will be also attached to the 
``NameId``.
 
 If a match on the ``LogoutResponse`` ID and the ``LogoutRequest`` ID to be 
sent is required, that ``LogoutRequest`` ID must to be extracted and stored for 
future validation, we can get that ID by:
 
@@ -830,7 +830,12 @@
     return_to = '%sattrs/' % request.host_url      # but set a custom 
RelayState URL
     return redirect(auth.login(return_to))
 elif 'slo' in request.args:                     # SLO action. Will sent a 
Logout Request to IdP
-    return redirect(auth.logout())
+    nameid = request.session['samlNameId']
+    nameid_format = request.session['samlNameIdFormat']
+    nameid_nq = request.session['samlNameIdNameQualifier']
+    nameid_spnq = request.session['samlNameIdSPNameQualifier']
+    session_index = request.session['samlSessionIndex']
+    return redirect(auth.logout(None, nameid, session_index, nameid_nq, 
nameid_format, nameid_spnq))
 elif 'acs' in request.args:                 # Assertion Consumer Service
     auth.process_response()                     # Process the Response of the 
IdP
     errors = auth.get_errors()              # This method receives an array 
with the errors
@@ -839,6 +844,11 @@
             msg = "Not authenticated"           # data retrieved or not (user 
authenticated)
         else:
             request.session['samlUserdata'] = auth.get_attributes()     # 
Retrieves user data
+            request.session['samlNameId'] = auth.get_nameid()
+            request.session['samlNameIdFormat'] = auth.get_nameid_format()
+            request.session['samlNameIdNameQualifier'] = auth.get_nameid_nq()
+            request.session['samlNameIdSPNameQualifier'] = 
auth.get_nameid_spnq()
+            request.session['samlSessionIndex'] = auth.get_session_index()
             self_url = OneLogin_Saml2_Utils.get_self_url(req)
             if 'RelayState' in request.form and self_url != 
request.form['RelayState']:
                 return redirect(auth.redirect_to(request.form['RelayState']))  
 # Redirect if there is a relayState
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-saml-1.6.0/changelog.md 
new/python3-saml-v.1.7.0/changelog.md
--- old/python3-saml-1.6.0/changelog.md 2019-04-10 00:27:34.000000000 +0200
+++ new/python3-saml-v.1.7.0/changelog.md       2019-07-02 20:09:38.000000000 
+0200
@@ -1,4 +1,9 @@
 # python3-saml changelog
+### 1.7.0 (Jul 02, 2019)
+* Adjusted acs endpoint to extract NameQualifier and SPNameQualifier from 
SAMLResponse. Adjusted single logout service to provide NameQualifier and 
SPNameQualifier to logout method. Add getNameIdNameQualifier to Auth and 
SamlResponse. Extend logout method from Auth and LogoutRequest constructor to 
support SPNameQualifier parameter. Align LogoutRequest constructor with SAML 
specs
+* Added get_in_response_to method to Response and LogoutResponse classes
+* Update defusexml dependency
+
 ### 1.6.0 (Apr 10, 2019)
 * Add support for Subjects on AuthNRequests by the new name_id_value_req 
parameter
 * [#127](https://github.com/onelogin/python3-saml/pull/127) Fix for SLO when 
XML specifies encoding
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-saml-1.6.0/demo-django/demo/views.py 
new/python3-saml-v.1.7.0/demo-django/demo/views.py
--- old/python3-saml-1.6.0/demo-django/demo/views.py    2019-04-10 
00:27:34.000000000 +0200
+++ new/python3-saml-v.1.7.0/demo-django/demo/views.py  2019-07-02 
20:09:38.000000000 +0200
@@ -41,26 +41,48 @@
 
     if 'sso' in req['get_data']:
         return HttpResponseRedirect(auth.login())
+        # If AuthNRequest ID need to be stored in order to later validate it, 
do instead
+        # sso_built_url = auth.login()
+        # request.session['AuthNRequestID'] = auth.get_last_request_id()
+        # return HttpResponseRedirect(sso_built_url)
     elif 'sso2' in req['get_data']:
         return_to = OneLogin_Saml2_Utils.get_self_url(req) + reverse('attrs')
         return HttpResponseRedirect(auth.login(return_to))
     elif 'slo' in req['get_data']:
-        name_id = None
-        session_index = None
+        name_id = session_index = name_id_format = name_id_nq = name_id_spnq = 
None
         if 'samlNameId' in request.session:
             name_id = request.session['samlNameId']
         if 'samlSessionIndex' in request.session:
             session_index = request.session['samlSessionIndex']
+        if 'samlNameIdFormat' in request.session:
+            name_id_format = request.session['samlNameIdFormat']
+        if 'samlNameIdNameQualifier' in request.session:
+            name_id_nq = request.session['samlNameIdNameQualifier']
+        if 'samlNameIdSPNameQualifier' in request.session:
+            name_id_spnq = request.session['samlNameIdSPNameQualifier']
 
-        return HttpResponseRedirect(auth.logout(name_id=name_id, 
session_index=session_index))
+        return HttpResponseRedirect(auth.logout(name_id=name_id, 
session_index=session_index, nq=name_id_nq, name_id_format=name_id_format, 
spnq=name_id_spnq))
+        # If LogoutRequest ID need to be stored in order to later validate it, 
do instead
+        # slo_built_url = auth.logout(name_id=name_id, 
session_index=session_index)
+        # request.session['LogoutRequestID'] = auth.get_last_request_id()
+        # return HttpResponseRedirect(slo_built_url)
     elif 'acs' in req['get_data']:
-        auth.process_response()
+        request_id = None
+        if 'AuthNRequestID' in request.session:
+            request_id = request.session['AuthNRequestID']
+
+        auth.process_response(request_id=request_id)
         errors = auth.get_errors()
         not_auth_warn = not auth.is_authenticated()
 
         if not errors:
+            if 'AuthNRequestID' in request.session:
+                del request.session['AuthNRequestID']
             request.session['samlUserdata'] = auth.get_attributes()
             request.session['samlNameId'] = auth.get_nameid()
+            request.session['samlNameIdFormat'] = auth.get_nameid_format()
+            request.session['samlNameIdNameQualifier'] = auth.get_nameid_nq()
+            request.session['samlNameIdSPNameQualifier'] = 
auth.get_nameid_spnq()
             request.session['samlSessionIndex'] = auth.get_session_index()
             if 'RelayState' in req['post_data'] and 
OneLogin_Saml2_Utils.get_self_url(req) != req['post_data']['RelayState']:
                 return 
HttpResponseRedirect(auth.redirect_to(req['post_data']['RelayState']))
@@ -68,8 +90,11 @@
             if auth.get_settings().is_debug_active():
                 error_reason = auth.get_last_error_reason()
     elif 'sls' in req['get_data']:
+        request_id = None
+        if 'LogoutRequestID' in request.session:
+            request_id = request.session['LogoutRequestID']
         dscb = lambda: request.session.flush()
-        url = auth.process_slo(delete_session_cb=dscb)
+        url = auth.process_slo(request_id=request_id, delete_session_cb=dscb)
         errors = auth.get_errors()
         if len(errors) == 0:
             if url is not None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-saml-1.6.0/demo-flask/index.py 
new/python3-saml-v.1.7.0/demo-flask/index.py
--- old/python3-saml-1.6.0/demo-flask/index.py  2019-04-10 00:27:34.000000000 
+0200
+++ new/python3-saml-v.1.7.0/demo-flask/index.py        2019-07-02 
20:09:38.000000000 +0200
@@ -11,7 +11,7 @@
 
 app = Flask(__name__)
 app.config['SECRET_KEY'] = 'onelogindemopytoolkit'
-app.config['SAML_PATH'] = 
os.path.join(os.path.dirname(os.path.dirname(__file__)), 'saml')
+app.config['SAML_PATH'] = 
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'saml')
 
 
 def init_saml_auth(req):
@@ -46,32 +46,52 @@
 
     if 'sso' in request.args:
         return redirect(auth.login())
+        # If AuthNRequest ID need to be stored in order to later validate it, 
do instead
+        # sso_built_url = auth.login()
+        # request.session['AuthNRequestID'] = auth.get_last_request_id()
+        # return redirect(sso_built_url)
     elif 'sso2' in request.args:
         return_to = '%sattrs/' % request.host_url
         return redirect(auth.login(return_to))
     elif 'slo' in request.args:
-        name_id = None
-        session_index = None
+        name_id = session_index = name_id_format = name_id_nq = name_id_spnq = 
None
         if 'samlNameId' in session:
             name_id = session['samlNameId']
         if 'samlSessionIndex' in session:
             session_index = session['samlSessionIndex']
+        if 'samlNameIdFormat' in session:
+            name_id_format = session['samlNameIdFormat']
+        if 'samlNameIdNameQualifier' in session:
+            name_id_nq = session['samlNameIdNameQualifier']
+        if 'samlNameIdSPNameQualifier' in session:
+            name_id_spnq = session['samlNameIdSPNameQualifier']
 
-        return redirect(auth.logout(name_id=name_id, 
session_index=session_index))
+        return redirect(auth.logout(name_id=name_id, 
session_index=session_index, nq=name_id_nq, name_id_format=name_id_format, 
spnq=name_id_spnq))
     elif 'acs' in request.args:
-        auth.process_response()
+        request_id = None
+        if 'AuthNRequestID' in session:
+            request_id = session['AuthNRequestID']
+
+        auth.process_response(request_id=request_id)
         errors = auth.get_errors()
         not_auth_warn = not auth.is_authenticated()
         if len(errors) == 0:
-            session['samlUserdata'] = auth.get_attributes()
+            if 'AuthNRequestID' in session:
+                del session['AuthNRequestID']
             session['samlNameId'] = auth.get_nameid()
+            session['samlNameIdFormat'] = auth.get_nameid_format()
+            session['samlNameIdNameQualifier'] = auth.get_nameid_nq()
+            session['samlNameIdSPNameQualifier'] = auth.get_nameid_spnq()
             session['samlSessionIndex'] = auth.get_session_index()
             self_url = OneLogin_Saml2_Utils.get_self_url(req)
             if 'RelayState' in request.form and self_url != 
request.form['RelayState']:
                 return redirect(auth.redirect_to(request.form['RelayState']))
     elif 'sls' in request.args:
+        request_id = None
+        if 'LogoutRequestID' in session:
+            request_id = session['LogoutRequestID']
         dscb = lambda: session.clear()
-        url = auth.process_slo(delete_session_cb=dscb)
+        url = auth.process_slo(request_id=request_id, delete_session_cb=dscb)
         errors = auth.get_errors()
         if len(errors) == 0:
             if url is not None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-saml-1.6.0/setup.py 
new/python3-saml-v.1.7.0/setup.py
--- old/python3-saml-1.6.0/setup.py     2019-04-10 00:27:34.000000000 +0200
+++ new/python3-saml-v.1.7.0/setup.py   2019-07-02 20:09:38.000000000 +0200
@@ -9,7 +9,7 @@
 
 setup(
     name='python3-saml',
-    version='1.6.0',
+    version='1.7.0',
     description='Onelogin Python Toolkit. Add SAML support to your Python 
software using this library',
     classifiers=[
         'Development Status :: 5 - Production/Stable',
@@ -38,7 +38,7 @@
     install_requires=[
         'isodate>=0.5.0',
         'xmlsec>=0.6.0',
-        'defusedxml==0.5.0'
+        'defusedxml>=0.5.0'
     ],
     
dependency_links=['http://github.com/mehcode/python-xmlsec/tarball/master'],
     extras_require={
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-saml-1.6.0/src/onelogin/saml2/auth.py 
new/python3-saml-v.1.7.0/src/onelogin/saml2/auth.py
--- old/python3-saml-1.6.0/src/onelogin/saml2/auth.py   2019-04-10 
00:27:34.000000000 +0200
+++ new/python3-saml-v.1.7.0/src/onelogin/saml2/auth.py 2019-07-02 
20:09:38.000000000 +0200
@@ -55,6 +55,8 @@
         self.__attributes = dict()
         self.__nameid = None
         self.__nameid_format = None
+        self.__nameid_nq = None
+        self.__nameid_spnq = None
         self.__session_index = None
         self.__session_expiration = None
         self.__authenticated = False
@@ -107,6 +109,8 @@
                 self.__attributes = response.get_attributes()
                 self.__nameid = response.get_nameid()
                 self.__nameid_format = response.get_nameid_format()
+                self.__nameid_nq = response.get_nameid_nq()
+                self.__nameid_spnq = response.get_nameid_spnq()
                 self.__session_index = response.get_session_index()
                 self.__session_expiration = 
response.get_session_not_on_or_after()
                 self.__last_message_id = response.get_id()
@@ -245,6 +249,24 @@
         """
         return self.__nameid_format
 
+    def get_nameid_nq(self):
+        """
+        Returns the nameID NameQualifier of the Assertion.
+
+        :returns: NameID NameQualifier
+        :rtype: string|None
+        """
+        return self.__nameid_nq
+
+    def get_nameid_spnq(self):
+        """
+        Returns the nameID SP NameQualifier of the Assertion.
+
+        :returns: NameID SP NameQualifier
+        :rtype: string|None
+        """
+        return self.__nameid_spnq
+
     def get_session_index(self):
         """
         Returns the SessionIndex from the AuthnStatement.
@@ -366,7 +388,7 @@
             self.add_request_signature(parameters, 
security['signatureAlgorithm'])
         return self.redirect_to(self.get_sso_url(), parameters)
 
-    def logout(self, return_to=None, name_id=None, session_index=None, 
nq=None, name_id_format=None):
+    def logout(self, return_to=None, name_id=None, session_index=None, 
nq=None, name_id_format=None, spnq=None):
         """
         Initiates the SLO process.
 
@@ -385,6 +407,9 @@
         :param name_id_format: The NameID Format that will be set in the 
LogoutRequest.
         :type: string
 
+        :param spnq: SP Name Qualifier
+        :type: string
+
         :returns: Redirection URL
         """
         slo_url = self.get_slo_url()
@@ -405,7 +430,8 @@
             name_id=name_id,
             session_index=session_index,
             nq=nq,
-            name_id_format=name_id_format
+            name_id_format=name_id_format,
+            spnq=spnq
         )
         self.__last_request = logout_request.get_xml()
         self.__last_request_id = logout_request.id
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python3-saml-1.6.0/src/onelogin/saml2/logout_request.py 
new/python3-saml-v.1.7.0/src/onelogin/saml2/logout_request.py
--- old/python3-saml-1.6.0/src/onelogin/saml2/logout_request.py 2019-04-10 
00:27:34.000000000 +0200
+++ new/python3-saml-v.1.7.0/src/onelogin/saml2/logout_request.py       
2019-07-02 20:09:38.000000000 +0200
@@ -25,7 +25,7 @@
 
     """
 
-    def __init__(self, settings, request=None, name_id=None, 
session_index=None, nq=None, name_id_format=None):
+    def __init__(self, settings, request=None, name_id=None, 
session_index=None, nq=None, name_id_format=None, spnq=None):
         """
         Constructs the Logout Request object.
 
@@ -46,6 +46,9 @@
 
         :param name_id_format: The NameID Format that will be set in the 
LogoutRequest.
         :type: string
+
+        :param spnq: SP Name Qualifier
+        :type: string
         """
         self.__settings = settings
         self.__error = None
@@ -75,19 +78,23 @@
                 if not name_id_format and sp_data['NameIDFormat'] != 
OneLogin_Saml2_Constants.NAMEID_UNSPECIFIED:
                     name_id_format = sp_data['NameIDFormat']
             else:
+                name_id = idp_data['entityId']
                 name_id_format = OneLogin_Saml2_Constants.NAMEID_ENTITY
 
-            sp_name_qualifier = None
-            if name_id_format == OneLogin_Saml2_Constants.NAMEID_ENTITY:
-                name_id = idp_data['entityId']
+            # From saml-core-2.0-os 8.3.6, when the entity Format is used:
+            # "The NameQualifier, SPNameQualifier, and SPProvidedID attributes
+            # MUST be omitted.
+            if name_id_format and name_id_format == 
OneLogin_Saml2_Constants.NAMEID_ENTITY:
                 nq = None
-            elif nq is not None:
-                # We only gonna include SPNameQualifier if NameQualifier is 
provided
-                sp_name_qualifier = sp_data['entityId']
+                spnq = None
+
+            # NameID Format UNSPECIFIED omitted
+            if name_id_format and name_id_format == 
OneLogin_Saml2_Constants.NAMEID_UNSPECIFIED:
+                name_id_format = None
 
             name_id_obj = OneLogin_Saml2_Utils.generate_name_id(
                 name_id,
-                sp_name_qualifier,
+                spnq,
                 name_id_format,
                 cert,
                 False,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python3-saml-1.6.0/src/onelogin/saml2/logout_response.py 
new/python3-saml-v.1.7.0/src/onelogin/saml2/logout_response.py
--- old/python3-saml-1.6.0/src/onelogin/saml2/logout_response.py        
2019-04-10 00:27:34.000000000 +0200
+++ new/python3-saml-v.1.7.0/src/onelogin/saml2/logout_response.py      
2019-07-02 20:09:38.000000000 +0200
@@ -95,7 +95,7 @@
                 security = self.__settings.get_security_data()
 
                 # Check if the InResponseTo of the Logout Response matches the 
ID of the Logout Request (requestId) if provided
-                in_response_to = self.document.get('InResponseTo', None)
+                in_response_to = self.get_in_response_to()
                 if request_id is not None and in_response_to and 
in_response_to != request_id:
                     raise OneLogin_Saml2_ValidationError(
                         'The InResponseTo of the Logout Response: %s, does not 
match the ID of the Logout request sent by the SP: %s' % (in_response_to, 
request_id),
@@ -175,6 +175,14 @@
 
         self.__logout_response = logout_response
 
+    def get_in_response_to(self):
+        """
+        Gets the ID of the LogoutRequest which this response is in response to
+        :returns: ID of LogoutRequest this LogoutResponse is in response to or 
None if it is not present
+        :rtype: str
+        """
+        return self.document.get('InResponseTo')
+
     def get_response(self, deflate=True):
         """
         Returns a Logout Response object.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-saml-1.6.0/src/onelogin/saml2/response.py 
new/python3-saml-v.1.7.0/src/onelogin/saml2/response.py
--- old/python3-saml-1.6.0/src/onelogin/saml2/response.py       2019-04-10 
00:27:34.000000000 +0200
+++ new/python3-saml-v.1.7.0/src/onelogin/saml2/response.py     2019-07-02 
20:09:38.000000000 +0200
@@ -122,7 +122,7 @@
                 current_url = 
OneLogin_Saml2_Utils.get_self_url_no_query(request_data)
 
                 # Check if the InResponseTo of the Response matchs the ID of 
the AuthNRequest (requestId) if provided
-                in_response_to = self.document.get('InResponseTo', None)
+                in_response_to = self.get_in_response_to()
                 if in_response_to is not None and request_id is not None:
                     if in_response_to != request_id:
                         raise OneLogin_Saml2_ValidationError(
@@ -387,6 +387,14 @@
         authn_context_nodes = 
self.__query_assertion('/saml:AuthnStatement/saml:AuthnContext/saml:AuthnContextClassRef')
         return [OneLogin_Saml2_XML.element_text(node) for node in 
authn_context_nodes]
 
+    def get_in_response_to(self):
+        """
+        Gets the ID of the request which this response is in response to
+        :returns: ID of AuthNRequest this Response is in response to or None 
if it is not present
+        :rtype: str
+        """
+        return self.document.get('InResponseTo')
+
     def get_issuers(self):
         """
         Gets the issuers (from message and from assertion)
@@ -498,6 +506,32 @@
             nameid_format = nameid_data['Format']
         return nameid_format
 
+    def get_nameid_nq(self):
+        """
+        Gets the NameID NameQualifier provided by the SAML Response from the 
IdP
+
+        :returns: NameID NameQualifier
+        :rtype: string|None
+        """
+        nameid_nq = None
+        nameid_data = self.get_nameid_data()
+        if nameid_data and 'NameQualifier' in nameid_data.keys():
+            nameid_nq = nameid_data['NameQualifier']
+        return nameid_nq
+
+    def get_nameid_spnq(self):
+        """
+        Gets the NameID SP NameQualifier provided by the SAML response from 
the IdP.
+
+        :returns: NameID SP NameQualifier
+        :rtype: string|None
+        """
+        nameid_spnq = None
+        nameid_data = self.get_nameid_data()
+        if nameid_data and 'SPNameQualifier' in nameid_data.keys():
+            nameid_spnq = nameid_data['SPNameQualifier']
+        return nameid_spnq
+
     def get_session_not_on_or_after(self):
         """
         Gets the SessionNotOnOrAfter from the AuthnStatement
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python3-saml-1.6.0/tests/data/metadata/metadata_settings1.xml 
new/python3-saml-v.1.7.0/tests/data/metadata/metadata_settings1.xml
--- old/python3-saml-1.6.0/tests/data/metadata/metadata_settings1.xml   
2019-04-10 00:27:34.000000000 +0200
+++ new/python3-saml-v.1.7.0/tests/data/metadata/metadata_settings1.xml 
2019-07-02 20:09:38.000000000 +0200
@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
 <md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
-                     validUntil="2020-03-05T18:19:11Z"
+                     validUntil="2037-03-05T18:19:11Z"
                      cacheDuration="PT1594475551S"
                      entityID="http://stuff.com/endpoints/metadata.php";>
     <md:SPSSODescriptor AuthnRequestsSigned="false" 
WantAssertionsSigned="false" 
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python3-saml-1.6.0/tests/data/responses/valid_response_with_namequalifier.xml.base64
 
new/python3-saml-v.1.7.0/tests/data/responses/valid_response_with_namequalifier.xml.base64
--- 
old/python3-saml-1.6.0/tests/data/responses/valid_response_with_namequalifier.xml.base64
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/python3-saml-v.1.7.0/tests/data/responses/valid_response_with_namequalifier.xml.base64
  2019-07-02 20:09:38.000000000 +0200
@@ -0,0 +1 @@
+PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c2FtbHA6UmVzcG9uc2UgeG1sbnM6c2FtbHA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgeG1sbnM6c2FtbD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9InBmeDhmZWI5YWNkLTFlODYtYWMxMi05MDIzLTEzYjg0NDc5YjI1YiIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTQtMDItMTlUMDE6Mzc6MDFaIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9waXRidWxrLm5vLWlwLm9yZy9uZXdvbmVsb2dpbi9kZW1vMS9pbmRleC5waHA/YWNzIiBJblJlc3BvbnNlVG89Ik9ORUxPR0lOXzVmZTlkNmU0OTliMmYwOTEzMjA2YWFiM2Y3MTkxNzI5MDQ5YmI4MDciPjxzYW1sOklzc3Vlcj5odHRwOi8vaWRwLmV4YW1wbGUuY29tLzwvc2FtbDpJc3N1ZXI+PGRzOlNpZ25hdHVyZSB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+DQogIDxkczpTaWduZWRJbmZvPjxkczpDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+DQogICAgPGRzOlNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNyc2Etc2hhMSIvPg0KICA8ZHM6UmVmZXJlbmNlIFVSST0iI3BmeDhmZWI5YWNkLTFlODYtYWMxMi05MDIzLTEzYjg0NDc5YjI1YiI+PGRzOlRyYW5zZm9ybXM+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjwvZHM6VHJhbnNmb3Jtcz48ZHM6RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI3NoYTEiLz48ZHM6RGlnZXN0VmFsdWU+NVRWZURYbGQ3YzhURmtybVlDeFpuL2ZHRTRzPTwvZHM6RGlnZXN0VmFsdWU+PC9kczpSZWZlcmVuY2U+PC9kczpTaWduZWRJbmZvPjxkczpTaWduYXR1cmVWYWx1ZT5hZlFaVUE2REpHa0hLNjVMMENBaTJBSDJkOWNwbExuekNPTHBCYm9hUmVmaWdtVC92L0tJZGcyYXpWRzY2Ykk1aFA1NTBNR0c2ZVVzaWJ1N2N3ZytFbG9tejVBalE3dzlGZG8waHdWWWhib3JaSkN2TUxLUzBEWkFzc01XZnZ3RGNUNmhra3UreXFlS2RhZ1BBOTYwQ25YcUMxeHpjMk43WS82dlBCU081bVU9PC9kczpTaWduYXR1cmVWYWx1ZT4NCjxkczpLZXlJbmZvPjxkczpYNTA5RGF0YT48ZHM6WDUwOUNlcnRpZmljYXRlPk1JSUNnVENDQWVvQ0NRQ2JPbHJXRGRYN0ZUQU5CZ2txaGtpRzl3MEJBUVVGQURDQmhERUxNQWtHQTFVRUJoTUNUazh4R0RBV0JnTlZCQWdURDBGdVpISmxZWE1nVTI5c1ltVnlaekVNTUFvR0ExVUVCeE1EUm05dk1SQXdEZ1lEVlFRS0V3ZFZUa2xPUlZSVU1SZ3dGZ1lEVlFRREV3OW1aV2xrWlM1bGNteGhibWN1Ym04eElUQWZCZ2txaGtpRzl3MEJDUUVXRW1GdVpISmxZWE5BZFc1cGJtVjBkQzV1YnpBZUZ3MHdOekEyTVRVeE1qQXhNelZhRncwd056QTRNVFF4TWpBeE16VmFNSUdFTVFzd0NRWURWUVFHRXdKT1R6RVlNQllHQTFVRUNCTVBRVzVrY21WaGN5QlRiMnhpWlhKbk1Rd3dDZ1lEVlFRSEV3TkdiMjh4RURBT0JnTlZCQW9UQjFWT1NVNUZWRlF4R0RBV0JnTlZCQU1URDJabGFXUmxMbVZ5YkdGdVp5NXViekVoTUI4R0NTcUdTSWIzRFFFSkFSWVNZVzVrY21WaGMwQjFibWx1WlhSMExtNXZNSUdmTUEwR0NTcUdTSWIzRFFFQkFRVUFBNEdOQURDQmlRS0JnUURpdmJoUjdQNTE2eC9TM0JxS3h1cFFlMExPTm9saXVwaUJPZXNDTzNTSGJEcmwzK3E5SWJmbmZtRTA0ck51TWNQc0l4QjE2MVRkRHBJZXNMQ243YzhhUEhJU0tPdFBsQWVUWlNuYjhRQXU3YVJqWnEzK1BiclA1dVczVGNmQ0dQdEtUeXRIT2dlL09sSmJvMDc4ZFZoWFExNGQxRUR3WEpXMXJSWHVVdDRDOFFJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0R0JBQ0RWZnA4NkhPYnFZK2U4QlVvV1E5K1ZNUXgxQVNEb2hCandPc2cyV3lrVXFSWEYrZExmY1VIOWRXUjYzQ3RaSUtGRGJTdE5vbVBuUXo3bmJLK29ueWd3QnNwVkVibkh1VWloWnEzWlVkbXVtUXFDdzRVdnMvMVV2cTNvck9vL1dKVmhUeXZMZ0ZWSzJRYXJRNC82N09aZkhkN1IrUE9CWGhvcGhTTXYxWk9vPC9kczpYNTA5Q2VydGlmaWNhdGU+PC9kczpYNTA5RGF0YT48L2RzOktleUluZm8+PC9kczpTaWduYXR1cmU+PHNhbWxwOlN0YXR1cz48c2FtbHA6U3RhdHVzQ29kZSBWYWx1ZT0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnN0YXR1czpTdWNjZXNzIi8+PC9zYW1scDpTdGF0dXM+PHNhbWw6QXNzZXJ0aW9uIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhtbG5zOnhzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIgSUQ9InBmeDQxN2ZiOTc2LTk0NGEtNDNiZi05ZTUyLWZiOWM1OTYxNzYxZiIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTQtMDItMTlUMDE6Mzc6MDFaIj48c2FtbDpJc3N1ZXI+aHR0cDovL2lkcC5leGFtcGxlLmNvbS88L3NhbWw6SXNzdWVyPjxkczpTaWduYXR1cmUgeG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPg0KICA8ZHM6U2lnbmVkSW5mbz48ZHM6Q2Fub25pY2FsaXphdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPg0KICAgIDxkczpTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjcnNhLXNoYTEiLz4NCiAgPGRzOlJlZmVyZW5jZSBVUkk9IiNwZng0MTdmYjk3Ni05NDRhLTQzYmYtOWU1Mi1mYjljNTk2MTc2MWYiPjxkczpUcmFuc2Zvcm1zPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjZW52ZWxvcGVkLXNpZ25hdHVyZSIvPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48L2RzOlRyYW5zZm9ybXM+PGRzOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNzaGExIi8+PGRzOkRpZ2VzdFZhbHVlPmxSbTJ3UW13ZGhmZVZuMDFaS1Ewb05CN1JqQT08L2RzOkRpZ2VzdFZhbHVlPjwvZHM6UmVmZXJlbmNlPjwvZHM6U2lnbmVkSW5mbz48ZHM6U2lnbmF0dXJlVmFsdWU+aktwQUNmMWkxR0FMSWQ5Y0liQlFsTkJQMVhpZDhhYXFKOUxyTkFIZ1lpR2VIc0NscldVUkZJREprOGI0T3RmdHdXTGZKeXBXbXgwWm15M2hpTTJyVHBIbDBLMGVqSFNsOS9Ed0pabkNEQW1CS1lhZ0ZFR0xxWXYwaXI0Y2lYaForTkdXSDY1czhBRlVibjU2SytaS3lpMFkwMWc4TmVqaS92OTNlZFZ6ZTZnPTwvZHM6U2lnbmF0dXJlVmFsdWU+DQo8ZHM6S2V5SW5mbz48ZHM6WDUwOURhdGE+PGRzOlg1MDlDZXJ0aWZpY2F0ZT5NSUlDZ1RDQ0Flb0NDUUNiT2xyV0RkWDdGVEFOQmdrcWhraUc5dzBCQVFVRkFEQ0JoREVMTUFrR0ExVUVCaE1DVGs4eEdEQVdCZ05WQkFnVEQwRnVaSEpsWVhNZ1UyOXNZbVZ5WnpFTU1Bb0dBMVVFQnhNRFJtOXZNUkF3RGdZRFZRUUtFd2RWVGtsT1JWUlVNUmd3RmdZRFZRUURFdzltWldsa1pTNWxjbXhoYm1jdWJtOHhJVEFmQmdrcWhraUc5dzBCQ1FFV0VtRnVaSEpsWVhOQWRXNXBibVYwZEM1dWJ6QWVGdzB3TnpBMk1UVXhNakF4TXpWYUZ3MHdOekE0TVRReE1qQXhNelZhTUlHRU1Rc3dDUVlEVlFRR0V3Sk9UekVZTUJZR0ExVUVDQk1QUVc1a2NtVmhjeUJUYjJ4aVpYSm5NUXd3Q2dZRFZRUUhFd05HYjI4eEVEQU9CZ05WQkFvVEIxVk9TVTVGVkZReEdEQVdCZ05WQkFNVEQyWmxhV1JsTG1WeWJHRnVaeTV1YnpFaE1COEdDU3FHU0liM0RRRUpBUllTWVc1a2NtVmhjMEIxYm1sdVpYUjBMbTV2TUlHZk1BMEdDU3FHU0liM0RRRUJBUVVBQTRHTkFEQ0JpUUtCZ1FEaXZiaFI3UDUxNngvUzNCcUt4dXBRZTBMT05vbGl1cGlCT2VzQ08zU0hiRHJsMytxOUliZm5mbUUwNHJOdU1jUHNJeEIxNjFUZERwSWVzTENuN2M4YVBISVNLT3RQbEFlVFpTbmI4UUF1N2FSalpxMytQYnJQNXVXM1RjZkNHUHRLVHl0SE9nZS9PbEpibzA3OGRWaFhRMTRkMUVEd1hKVzFyUlh1VXQ0QzhRSURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNEdCQUNEVmZwODZIT2JxWStlOEJVb1dROStWTVF4MUFTRG9oQmp3T3NnMld5a1VxUlhGK2RMZmNVSDlkV1I2M0N0WklLRkRiU3ROb21QblF6N25iSytvbnlnd0JzcFZFYm5IdVVpaFpxM1pVZG11bVFxQ3c0VXZzLzFVdnEzb3JPby9XSlZoVHl2TGdGVksyUWFyUTQvNjdPWmZIZDdSK1BPQlhob3BoU012MVpPbzwvZHM6WDUwOUNlcnRpZmljYXRlPjwvZHM6WDUwOURhdGE+PC9kczpLZXlJbmZvPjwvZHM6U2lnbmF0dXJlPjxzYW1sOlN1YmplY3Q+PHNhbWw6TmFtZUlEIE5hbWVRdWFsaWZpZXI9Imh0dHBzOi8vdGVzdC5leGFtcGxlLmNvbS9zYW1sL21ldGFkYXRhIiBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjEuMTpuYW1laWQtZm9ybWF0OmVtYWlsQWRkcmVzcyI+NDkyODgyNjE1YWNmMzFjODA5NmI2MjcyNDVkNzZhZTUzMDM2YzA5MDwvc2FtbDpOYW1lSUQ+PHNhbWw6U3ViamVjdENvbmZpcm1hdGlvbiBNZXRob2Q9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpjbTpiZWFyZXIiPjxzYW1sOlN1YmplY3RDb25maXJtYXRpb25EYXRhIE5vdE9uT3JBZnRlcj0iMjA1NC0wOC0yM1QwNjo1NzowMVoiIFJlY2lwaWVudD0iaHR0cHM6Ly9waXRidWxrLm5vLWlwLm9yZy9uZXdvbmVsb2dpbi9kZW1vMS9pbmRleC5waHA/YWNzIiBJblJlc3BvbnNlVG89Ik9ORUxPR0lOXzVmZTlkNmU0OTliMmYwOTEzMjA2YWFiM2Y3MTkxNzI5MDQ5YmI4MDciLz48L3NhbWw6U3ViamVjdENvbmZpcm1hdGlvbj48L3NhbWw6U3ViamVjdD48c2FtbDpDb25kaXRpb25zIE5vdEJlZm9yZT0iMjAxNC0wMi0xOVQwMTozNjozMVoiIE5vdE9uT3JBZnRlcj0iMjA1NC0wOC0yM1QwNjo1NzowMVoiPjxzYW1sOkF1ZGllbmNlUmVzdHJpY3Rpb24+PHNhbWw6QXVkaWVuY2U+aHR0cDovL3N0dWZmLmNvbS9lbmRwb2ludHMvbWV0YWRhdGEucGhwPC9zYW1sOkF1ZGllbmNlPjwvc2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPjwvc2FtbDpDb25kaXRpb25zPjxzYW1sOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAxNC0wMi0xOVQwMTozNzowMVoiIFNlc3Npb25Ob3RPbk9yQWZ0ZXI9IjIwNTQtMDItMTlUMDk6Mzc6MDFaIiBTZXNzaW9uSW5kZXg9Il82MjczZDc3YjhjZGUwYzMzM2VjNzlkMjJhOWZhMDAwM2I5ZmUyZDc1Y2IiPjxzYW1sOkF1dGhuQ29udGV4dD48c2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZDwvc2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj48L3NhbWw6QXV0aG5Db250ZXh0Pjwvc2FtbDpBdXRoblN0YXRlbWVudD48c2FtbDpBdHRyaWJ1dGVTdGF0ZW1lbnQ+PHNhbWw6QXR0cmlidXRlIE5hbWU9InVpZCIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDpiYXNpYyI+PHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+c21hcnRpbjwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJtYWlsIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OmJhc2ljIj48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6c3RyaW5nIj5zbWFydGluQHlhY28uZXM8L3NhbWw6QXR0cmlidXRlVmFsdWU+PC9zYW1sOkF0dHJpYnV0ZT48c2FtbDpBdHRyaWJ1dGUgTmFtZT0iY24iIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6YmFzaWMiPjxzYW1sOkF0dHJpYnV0ZVZhbHVlIHhzaTp0eXBlPSJ4czpzdHJpbmciPlNpeHRvMzwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJzbiIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDpiYXNpYyI+PHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+TWFydGluMjwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJlZHVQZXJzb25BZmZpbGlhdGlvbiIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDpiYXNpYyI+PHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+dXNlcjwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6c3RyaW5nIj5hZG1pbjwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjwvc2FtbDpBdHRyaWJ1dGVTdGF0ZW1lbnQ+PC9zYW1sOkFzc2VydGlvbj48L3NhbWxwOlJlc3BvbnNlPg==
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python3-saml-1.6.0/tests/src/OneLogin/saml2_tests/auth_test.py 
new/python3-saml-v.1.7.0/tests/src/OneLogin/saml2_tests/auth_test.py
--- old/python3-saml-1.6.0/tests/src/OneLogin/saml2_tests/auth_test.py  
2019-04-10 00:27:34.000000000 +0200
+++ new/python3-saml-v.1.7.0/tests/src/OneLogin/saml2_tests/auth_test.py        
2019-07-02 20:09:38.000000000 +0200
@@ -227,6 +227,9 @@
         self.assertEqual(auth.get_attribute('mail'), attributes['mail'])
         session_index = auth.get_session_index()
         self.assertEqual('_6273d77b8cde0c333ec79d22a9fa0003b9fe2d75cb', 
session_index)
+        
self.assertEqual("urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", 
auth.get_nameid_format())
+        self.assertIsNone(auth.get_nameid_nq())
+        self.assertEqual("http://stuff.com/endpoints/metadata.php";, 
auth.get_nameid_spnq())
 
     def testRedirectTo(self):
         """
@@ -993,6 +996,70 @@
         self.assertTrue(auth.is_authenticated())
         
self.assertEqual("urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified", 
auth.get_nameid_format())
 
+    def testGetNameIdNameQualifier(self):
+        """
+        Tests the get_nameid_nq method of the OneLogin_Saml2_Auth
+        """
+        settings = self.loadSettingsJSON()
+        message = self.file_contents(join(self.data_path, 'responses', 
'valid_response_with_namequalifier.xml.base64'))
+        request_data = self.get_request()
+        request_data['post_data'] = {
+            'SAMLResponse': message
+        }
+        auth = OneLogin_Saml2_Auth(request_data, old_settings=settings)
+        self.assertIsNone(auth.get_nameid_nq())
+        auth.process_response()
+        self.assertTrue(auth.is_authenticated())
+        self.assertEqual("https://test.example.com/saml/metadata";, 
auth.get_nameid_nq())
+
+    def testGetNameIdNameQualifier2(self):
+        """
+        Tests the get_nameid_nq method of the OneLogin_Saml2_Auth
+        """
+        settings = self.loadSettingsJSON()
+        message = self.file_contents(join(self.data_path, 'responses', 
'valid_response.xml.base64'))
+        request_data = self.get_request()
+        request_data['post_data'] = {
+            'SAMLResponse': message
+        }
+        auth = OneLogin_Saml2_Auth(request_data, old_settings=settings)
+        self.assertIsNone(auth.get_nameid_nq())
+        auth.process_response()
+        self.assertTrue(auth.is_authenticated())
+        self.assertIsNone(auth.get_nameid_nq())
+
+    def testGetNameIdSPNameQualifier(self):
+        """
+        Tests the get_nameid_spnq method of the OneLogin_Saml2_Auth
+        """
+        settings = self.loadSettingsJSON()
+        message = self.file_contents(join(self.data_path, 'responses', 
'valid_response_with_namequalifier.xml.base64'))
+        request_data = self.get_request()
+        request_data['post_data'] = {
+            'SAMLResponse': message
+        }
+        auth = OneLogin_Saml2_Auth(request_data, old_settings=settings)
+        self.assertIsNone(auth.get_nameid_spnq())
+        auth.process_response()
+        self.assertTrue(auth.is_authenticated())
+        self.assertIsNone(auth.get_nameid_spnq())
+
+    def testGetNameIdSPNameQualifier2(self):
+        """
+        Tests the get_nameid_spnq method of the OneLogin_Saml2_Auth
+        """
+        settings = self.loadSettingsJSON()
+        message = self.file_contents(join(self.data_path, 'responses', 
'valid_response.xml.base64'))
+        request_data = self.get_request()
+        request_data['post_data'] = {
+            'SAMLResponse': message
+        }
+        auth = OneLogin_Saml2_Auth(request_data, old_settings=settings)
+        self.assertIsNone(auth.get_nameid_spnq())
+        auth.process_response()
+        self.assertTrue(auth.is_authenticated())
+        self.assertEqual("http://stuff.com/endpoints/metadata.php";, 
auth.get_nameid_spnq())
+
     def testBuildRequestSignature(self):
         """
         Tests the build_request_signature method of the OneLogin_Saml2_Auth
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python3-saml-1.6.0/tests/src/OneLogin/saml2_tests/logout_request_test.py 
new/python3-saml-v.1.7.0/tests/src/OneLogin/saml2_tests/logout_request_test.py
--- 
old/python3-saml-1.6.0/tests/src/OneLogin/saml2_tests/logout_request_test.py    
    2019-04-10 00:27:34.000000000 +0200
+++ 
new/python3-saml-v.1.7.0/tests/src/OneLogin/saml2_tests/logout_request_test.py  
    2019-07-02 20:09:38.000000000 +0200
@@ -215,7 +215,6 @@
         expected_name_id_data = {
             'Format': 'urn:oasis:names:tc:SAML:2.0:nameid-format:emailAddress',
             'NameQualifier': idp_data['entityId'],
-            'SPNameQualifier': 'http://stuff.com/endpoints/metadata.php',
             'Value': 'ONELOGIN_9c86c4542ab9d6fce07f2f7fd335287b9b3cdf69'
         }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python3-saml-1.6.0/tests/src/OneLogin/saml2_tests/response_test.py 
new/python3-saml-v.1.7.0/tests/src/OneLogin/saml2_tests/response_test.py
--- old/python3-saml-1.6.0/tests/src/OneLogin/saml2_tests/response_test.py      
2019-04-10 00:27:34.000000000 +0200
+++ new/python3-saml-v.1.7.0/tests/src/OneLogin/saml2_tests/response_test.py    
2019-07-02 20:09:38.000000000 +0200
@@ -75,8 +75,8 @@
 
         xml = self.file_contents(join(self.data_path, 'responses', 
'signed_message_response.xml.base64'))
         response = OneLogin_Saml2_Response(settings, xml)
-        prety_xml = self.file_contents(join(self.data_path, 'responses', 
'pretty_signed_message_response.xml'))
-        self.assertEqual(etree.tostring(response.get_xml_document(), 
encoding='unicode', pretty_print=True), prety_xml)
+        pretty_xml = self.file_contents(join(self.data_path, 'responses', 
'pretty_signed_message_response.xml'))
+        self.assertEqual(etree.tostring(response.get_xml_document(), 
encoding='unicode', pretty_print=True), pretty_xml)
 
         xml_2 = self.file_contents(join(self.data_path, 'responses', 
'valid_encrypted_assertion.xml.base64'))
         response_2 = OneLogin_Saml2_Response(settings, xml_2)
@@ -293,6 +293,74 @@
         with self.assertRaisesRegex(Exception, 'An empty NameID value found'):
             response_17.get_nameid_format()
 
+    def testReturnNameIdNameQualifier(self):
+        """
+        Tests the get_nameid_nq method of the OneLogin_Saml2_Response
+        """
+        json_settings = self.loadSettingsJSON()
+        json_settings['strict'] = False
+        settings = OneLogin_Saml2_Settings(json_settings)
+        xml = self.file_contents(join(self.data_path, 'responses', 
'response1.xml.base64'))
+        response = OneLogin_Saml2_Response(settings, xml)
+        self.assertIsNone(response.get_nameid_nq())
+
+        xml_2 = self.file_contents(join(self.data_path, 'responses', 
'response_encrypted_nameid.xml.base64'))
+        response_2 = OneLogin_Saml2_Response(settings, xml_2)
+        self.assertIsNone(response_2.get_nameid_nq())
+
+        xml_3 = self.file_contents(join(self.data_path, 'responses', 
'valid_encrypted_assertion.xml.base64'))
+        response_3 = OneLogin_Saml2_Response(settings, xml_3)
+        self.assertIsNone(response_3.get_nameid_nq())
+
+        xml_4 = self.file_contents(join(self.data_path, 'responses', 
'valid_response.xml.base64'))
+        response_4 = OneLogin_Saml2_Response(settings, xml_4)
+        self.assertIsNone(response_4.get_nameid_nq())
+
+        xml_5 = self.file_contents(join(self.data_path, 'responses', 
'valid_response_with_namequalifier.xml.base64'))
+        response_5 = OneLogin_Saml2_Response(settings, xml_5)
+        self.assertEqual('https://test.example.com/saml/metadata', 
response_5.get_nameid_nq())
+
+        json_settings['strict'] = True
+        settings = OneLogin_Saml2_Settings(json_settings)
+        xml_6 = self.file_contents(join(self.data_path, 'responses', 
'invalids', 'no_nameid.xml.base64'))
+        response_6 = OneLogin_Saml2_Response(settings, xml_6)
+        with self.assertRaisesRegex(Exception, 'NameID not found in the 
assertion of the Response'):
+            response_6.get_nameid_nq()
+
+    def testReturnNameIdNameSPQualifier(self):
+        """
+        Tests the get_nameid_spnq method of the OneLogin_Saml2_Response
+        """
+        json_settings = self.loadSettingsJSON()
+        json_settings['strict'] = False
+        settings = OneLogin_Saml2_Settings(json_settings)
+        xml = self.file_contents(join(self.data_path, 'responses', 
'response1.xml.base64'))
+        response = OneLogin_Saml2_Response(settings, xml)
+        self.assertIsNone(response.get_nameid_spnq())
+
+        xml_2 = self.file_contents(join(self.data_path, 'responses', 
'response_encrypted_nameid.xml.base64'))
+        response_2 = OneLogin_Saml2_Response(settings, xml_2)
+        self.assertEqual("http://stuff.com/endpoints/metadata.php";, 
response_2.get_nameid_spnq())
+
+        xml_3 = self.file_contents(join(self.data_path, 'responses', 
'valid_encrypted_assertion.xml.base64'))
+        response_3 = OneLogin_Saml2_Response(settings, xml_3)
+        self.assertEqual("http://stuff.com/endpoints/metadata.php";, 
response_3.get_nameid_spnq())
+
+        xml_4 = self.file_contents(join(self.data_path, 'responses', 
'valid_response.xml.base64'))
+        response_4 = OneLogin_Saml2_Response(settings, xml_4)
+        self.assertEqual("http://stuff.com/endpoints/metadata.php";, 
response_4.get_nameid_spnq())
+
+        xml_5 = self.file_contents(join(self.data_path, 'responses', 
'valid_response_with_namequalifier.xml.base64'))
+        response_5 = OneLogin_Saml2_Response(settings, xml_5)
+        self.assertIsNone(response_5.get_nameid_spnq())
+
+        json_settings['strict'] = True
+        settings = OneLogin_Saml2_Settings(json_settings)
+        xml_6 = self.file_contents(join(self.data_path, 'responses', 
'invalids', 'no_nameid.xml.base64'))
+        response_6 = OneLogin_Saml2_Response(settings, xml_6)
+        with self.assertRaisesRegex(Exception, 'NameID not found in the 
assertion of the Response'):
+            response_6.get_nameid_spnq()
+
     def testGetNameIdData(self):
         """
         Tests the get_nameid_data method of the OneLogin_Saml2_Response
@@ -407,7 +475,7 @@
         settings = OneLogin_Saml2_Settings(json_settings)
         response_13 = OneLogin_Saml2_Response(settings, xml_6)
         nameid_data_13 = response_13.get_nameid_data()
-        nameid_data_13 = self.assertEqual(expected_nameid_data_5, 
nameid_data_13)
+        self.assertEqual(expected_nameid_data_5, nameid_data_13)
 
         json_settings['strict'] = False
         json_settings['security']['wantNameId'] = False
@@ -685,6 +753,22 @@
         response_3 = OneLogin_Saml2_Response(settings, xml_3)
         self.assertEqual(2696012228, response_3.get_session_not_on_or_after())
 
+    def testGetInResponseTo(self):
+        """
+        Tests the retrieval of the InResponseTo attribute
+        """
+
+        settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())
+
+        # Response without an InResponseTo element should return None
+        xml = self.file_contents(join(self.data_path, 'responses', 
'response1.xml.base64'))
+        response = OneLogin_Saml2_Response(settings, xml)
+        self.assertIsNone(response.get_in_response_to())
+
+        xml_3 = self.file_contents(join(self.data_path, 'responses', 
'valid_encrypted_assertion.xml.base64'))
+        response_3 = OneLogin_Saml2_Response(settings, xml_3)
+        self.assertEqual('ONELOGIN_be60b8caf8e9d19b7a3551b244f116c947ff247d', 
response_3.get_in_response_to())
+
     def testIsInvalidXML(self):
         """
         Tests the is_valid method of the OneLogin_Saml2_Response


Reply via email to