• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SAML-Toolkits / python3-saml / 9636737938

23 Jun 2024 10:06PM UTC coverage: 95.19%. Remained the same
9636737938

push

github

pitbulk
Adjust format to black

1193 of 1364 branches covered (87.46%)

Branch coverage included in aggregate %.

2181 of 2242 new or added lines in 24 files covered. (97.28%)

2 existing lines in 2 files now uncovered.

6902 of 7140 relevant lines covered (96.67%)

0.97 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.72
/tests/src/OneLogin/saml2_tests/utils_test.py
1
# -*- coding: utf-8 -*-
2

3

4
from base64 import b64decode
1✔
5
import json
1✔
6
from lxml import etree
1✔
7
from os.path import dirname, join, exists
1✔
8
import unittest
1✔
9
import sys
1✔
10
from xml.dom.minidom import parseString
1✔
11

12
from onelogin.saml2 import compat
1✔
13
from onelogin.saml2.constants import OneLogin_Saml2_Constants
1✔
14
from onelogin.saml2.settings import OneLogin_Saml2_Settings
1✔
15
from onelogin.saml2.utils import OneLogin_Saml2_Utils
1✔
16
from onelogin.saml2.xmlparser import fromstring
1✔
17

18

19
class OneLogin_Saml2_Utils_Test(unittest.TestCase):
1✔
20
    data_path = join(dirname(dirname(dirname(dirname(__file__)))), "data")
1✔
21
    settings_path = join(dirname(dirname(dirname(dirname(__file__)))), "settings")
1✔
22

23
    # assertRegexpMatches deprecated on python3
24
    def assertRaisesRegex(self, exception, regexp, msg=None):
1✔
25
        if hasattr(unittest.TestCase, "assertRaisesRegex"):
1!
26
            return super(OneLogin_Saml2_Utils_Test, self).assertRaisesRegex(exception, regexp, msg=msg)
1✔
27
        else:
28
            return self.assertRaisesRegexp(exception, regexp)
×
29

30
    def loadSettingsJSON(self, name="settings1.json"):
1✔
31
        filename = join(self.settings_path, name)
1✔
32
        if exists(filename):
1!
33
            stream = open(filename, "r")
1✔
34
            settings = json.load(stream)
1✔
35
            stream.close()
1✔
36
            return settings
1✔
37
        else:
NEW
38
            raise Exception("Settings json file does not exist")
×
39

40
    def file_contents(self, filename):
1✔
41
        f = open(filename, "r")
1✔
42
        content = f.read()
1✔
43
        f.close()
1✔
44
        return content
1✔
45

46
    def testFormatCert(self):
1✔
47
        """
48
        Tests the format_cert method of the OneLogin_Saml2_Utils
49
        """
50
        settings_info = self.loadSettingsJSON()
1✔
51
        cert = settings_info["idp"]["x509cert"]
1✔
52
        self.assertNotIn("-----BEGIN CERTIFICATE-----", cert)
1✔
53
        self.assertNotIn("-----END CERTIFICATE-----", cert)
1✔
54
        self.assertEqual(len(cert), 860)
1✔
55

56
        formated_cert1 = OneLogin_Saml2_Utils.format_cert(cert)
1✔
57
        self.assertIn("-----BEGIN CERTIFICATE-----", formated_cert1)
1✔
58
        self.assertIn("-----END CERTIFICATE-----", formated_cert1)
1✔
59

60
        formated_cert2 = OneLogin_Saml2_Utils.format_cert(cert, True)
1✔
61
        self.assertEqual(formated_cert1, formated_cert2)
1✔
62

63
        formated_cert3 = OneLogin_Saml2_Utils.format_cert(cert, False)
1✔
64
        self.assertNotIn("-----BEGIN CERTIFICATE-----", formated_cert3)
1✔
65
        self.assertNotIn("-----END CERTIFICATE-----", formated_cert3)
1✔
66
        self.assertEqual(len(formated_cert3), 860)
1✔
67

68
    def testFormatPrivateKey(self):
1✔
69
        """
70
        Tests the format_private_key method of the OneLogin_Saml2_Utils
71
        """
72
        key = "-----BEGIN RSA PRIVATE KEY-----\nMIICXgIBAAKBgQDivbhR7P516x/S3BqKxupQe0LONoliupiBOesCO3SHbDrl3+q9\nIbfnfmE04rNuMcPsIxB161TdDpIesLCn7c8aPHISKOtPlAeTZSnb8QAu7aRjZq3+\nPbrP5uW3TcfCGPtKTytHOge/OlJbo078dVhXQ14d1EDwXJW1rRXuUt4C8QIDAQAB\nAoGAD4/Z4LWVWV6D1qMIp1Gzr0ZmdWTE1SPdZ7Ej8glGnCzPdguCPuzbhGXmIg0V\nJ5D+02wsqws1zd48JSMXXM8zkYZVwQYIPUsNn5FetQpwxDIMPmhHg+QNBgwOnk8J\nK2sIjjLPL7qY7Itv7LT7Gvm5qSOkZ33RCgXcgz+okEIQMYkCQQDzbTOyDL0c5WQV\n6A2k06T/azdhUdGXF9C0+WkWSfNaovmTgRXh1G+jMlr82Snz4p4/STt7P/XtyWzF\n3pkVgZr3AkEA7nPjXwHlttNEMo6AtxHd47nizK2NUN803ElIUT8P9KSCoERmSXq6\n6PDekGNic4ldpsSvOeYCk8MAYoDBy9kvVwJBAMLgX4xg6lzhv7hR5+pWjTb1rIY6\nrCHbrPfU264+UZXz9v2BT/VUznLF81WMvStD9xAPHpFS6R0OLghSZhdzhI0CQQDL\n8Duvfxzrn4b9QlmduV8wLERoT6rEVxKLsPVz316TGrxJvBZLk/cV0SRZE1cZf4uk\nXSWMfEcJ/0Zt+LdG1CqjAkEAqwLSglJ9Dy3HpgMz4vAAyZWzAxvyA1zW0no9GOLc\nPQnYaNUN/Fy2SYtETXTb0CQ9X1rt8ffkFP7ya+5TC83aMg==\n-----END RSA PRIVATE KEY-----\n"
1✔
73
        formated_key = OneLogin_Saml2_Utils.format_private_key(key, True)
1✔
74
        self.assertIn("-----BEGIN RSA PRIVATE KEY-----", formated_key)
1✔
75
        self.assertIn("-----END RSA PRIVATE KEY-----", formated_key)
1✔
76
        self.assertEqual(len(formated_key), 891)
1✔
77

78
        formated_key = OneLogin_Saml2_Utils.format_private_key(key, False)
1✔
79
        self.assertNotIn("-----BEGIN RSA PRIVATE KEY-----", formated_key)
1✔
80
        self.assertNotIn("-----END RSA PRIVATE KEY-----", formated_key)
1✔
81
        self.assertEqual(len(formated_key), 816)
1✔
82

83
        key_2 = "-----BEGIN PRIVATE KEY-----\nMIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAM62buSW9Zgh7CmZ\nouJekK0ac9sgEZkspemjv7SyE6Hbdz+KmUr3C7MI6JuPfVyJbxvMDf3FbgBBK7r5\nyfGgehXwplLMZj8glvV3NkdLMLPWmaw9U5sOzRoym46pVvsEo1PUL2qDK5Wrsm1g\nuY1KIDSHL59NQ7PzDKgm1dxioeXFAgMBAAECgYA/fvRzTReloo3rfWD2Tfv84EpE\nPgaJ2ZghO4Zwl97F8icgIo/R4i760Lq6xgnI+gJiNHz7vcB7XYl0RrRMf3HgbA7z\npJxREmOVltESDHy6lH0TmCdv9xMmHltB+pbGOhqBvuGgFbEOR73lDDV0ln2rEITJ\nA2zjYF+hWe8b0JFeQQJBAOsIIIlHAMngjhCQDD6kla/vce972gCFU7ZeFw16ZMmb\n8W4rGRfQoQWYxSLAFIFsYewSBTccanyYbBNe3njki3ECQQDhJ4cgV6VpTwez4dkp\nU/xCHKoReedAEJhXucTNGpiIqu+TDgIz9aRbrgnUKkS1s06UJhcDRTl/+pCSRRt/\nCA2VAkBkPw4pn1hNwvK1S8t9OJQD+5xcKjZcvIFtKoqonAi7GUGL3OQSDVFw4q1K\n2iSk40aM+06wJ/WfeR+3z2ISrGBxAkAJ20YiF1QpcQlASbHNCl0vs7uKOlDyUAer\nR3mjFPf6e6kzQdi815MTZGIPxK3vWmMlPymgvgYPYTO1A4t5myulAkEA1QioAWcJ\noO26qhUlFRBCR8BMJoVPImV7ndVHE7usHdJvP7V2P9RyuRcMCTVul8RRmyoh/+yG\n4ghMaHo/v0YY5Q==\n-----END PRIVATE KEY-----\n"
1✔
84
        formated_key_2 = OneLogin_Saml2_Utils.format_private_key(key_2, True)
1✔
85
        self.assertIn("-----BEGIN PRIVATE KEY-----", formated_key_2)
1✔
86
        self.assertIn("-----END PRIVATE KEY-----", formated_key_2)
1✔
87
        self.assertEqual(len(formated_key_2), 916)
1✔
88

89
        formated_key_2 = OneLogin_Saml2_Utils.format_private_key(key_2, False)
1✔
90
        self.assertNotIn("-----BEGIN PRIVATE KEY-----", formated_key_2)
1✔
91
        self.assertNotIn("-----END PRIVATE KEY-----", formated_key_2)
1✔
92
        self.assertEqual(len(formated_key_2), 848)
1✔
93

94
        key_3 = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAM62buSW9Zgh7CmZouJekK0ac9sgEZkspemjv7SyE6Hbdz+KmUr3C7MI6JuPfVyJbxvMDf3FbgBBK7r5yfGgehXwplLMZj8glvV3NkdLMLPWmaw9U5sOzRoym46pVvsEo1PUL2qDK5Wrsm1guY1KIDSHL59NQ7PzDKgm1dxioeXFAgMBAAECgYA/fvRzTReloo3rfWD2Tfv84EpEPgaJ2ZghO4Zwl97F8icgIo/R4i760Lq6xgnI+gJiNHz7vcB7XYl0RrRMf3HgbA7zpJxREmOVltESDHy6lH0TmCdv9xMmHltB+pbGOhqBvuGgFbEOR73lDDV0ln2rEITJA2zjYF+hWe8b0JFeQQJBAOsIIIlHAMngjhCQDD6kla/vce972gCFU7ZeFw16ZMmb8W4rGRfQoQWYxSLAFIFsYewSBTccanyYbBNe3njki3ECQQDhJ4cgV6VpTwez4dkpU/xCHKoReedAEJhXucTNGpiIqu+TDgIz9aRbrgnUKkS1s06UJhcDRTl/+pCSRRt/CA2VAkBkPw4pn1hNwvK1S8t9OJQD+5xcKjZcvIFtKoqonAi7GUGL3OQSDVFw4q1K2iSk40aM+06wJ/WfeR+3z2ISrGBxAkAJ20YiF1QpcQlASbHNCl0vs7uKOlDyUAerR3mjFPf6e6kzQdi815MTZGIPxK3vWmMlPymgvgYPYTO1A4t5myulAkEA1QioAWcJoO26qhUlFRBCR8BMJoVPImV7ndVHE7usHdJvP7V2P9RyuRcMCTVul8RRmyoh/+yG4ghMaHo/v0YY5Q=="
1✔
95
        formated_key_3 = OneLogin_Saml2_Utils.format_private_key(key_3, True)
1✔
96
        self.assertIn("-----BEGIN RSA PRIVATE KEY-----", formated_key_3)
1✔
97
        self.assertIn("-----END RSA PRIVATE KEY-----", formated_key_3)
1✔
98
        self.assertEqual(len(formated_key_3), 924)
1✔
99

100
        formated_key_3 = OneLogin_Saml2_Utils.format_private_key(key_3, False)
1✔
101
        self.assertNotIn("-----BEGIN PRIVATE KEY-----", formated_key_3)
1✔
102
        self.assertNotIn("-----END PRIVATE KEY-----", formated_key_3)
1✔
103
        self.assertNotIn("-----BEGIN RSA PRIVATE KEY-----", formated_key_3)
1✔
104
        self.assertNotIn("-----END RSA PRIVATE KEY-----", formated_key_3)
1✔
105
        self.assertEqual(len(formated_key_3), 848)
1✔
106

107
    def testRedirect(self):
1✔
108
        """
109
        Tests the redirect method of the OneLogin_Saml2_Utils
110
        """
111
        request_data = {"http_host": "example.com"}
1✔
112

113
        # Check relative and absolute
114
        hostname = OneLogin_Saml2_Utils.get_self_host(request_data)
1✔
115
        url = "http://%s/example" % hostname
1✔
116
        url2 = "/example"
1✔
117

118
        target_url = OneLogin_Saml2_Utils.redirect(url, {}, request_data)
1✔
119
        target_url2 = OneLogin_Saml2_Utils.redirect(url2, {}, request_data)
1✔
120

121
        self.assertEqual(target_url, target_url2)
1✔
122

123
        # Check that accept http/https and reject other protocols
124
        url3 = "https://%s/example?test=true" % hostname
1✔
125
        url4 = "ftp://%s/example" % hostname
1✔
126

127
        target_url3 = OneLogin_Saml2_Utils.redirect(url3, {}, request_data)
1✔
128
        self.assertIn("test=true", target_url3)
1✔
129
        with self.assertRaises(Exception) as context:
1✔
130
            OneLogin_Saml2_Utils.redirect(url4, {}, request_data)
1✔
131
            exception = context.exception
×
132
            self.assertIn("Redirect to invalid URL", str(exception))
×
133

134
        # Review parameter prefix
135
        parameters1 = {"value1": "a"}
1✔
136

137
        target_url5 = OneLogin_Saml2_Utils.redirect(url, parameters1, request_data)
1✔
138
        self.assertEqual("http://%s/example?value1=a" % hostname, target_url5)
1✔
139

140
        target_url6 = OneLogin_Saml2_Utils.redirect(url3, parameters1, request_data)
1✔
141
        self.assertEqual("https://%s/example?test=true&value1=a" % hostname, target_url6)
1✔
142

143
        # Review parameters
144
        parameters2 = {"alphavalue": "a", "numvaluelist": ["1", "2"], "testing": None}
1✔
145

146
        target_url7 = OneLogin_Saml2_Utils.redirect(url, parameters2, request_data)
1✔
147
        parameters2_decoded = {"alphavalue": "alphavalue=a", "numvaluelist": "numvaluelist[]=1&numvaluelist[]=2", "testing": "testing"}
1✔
148
        parameters2_str = "&".join(parameters2_decoded[x] for x in parameters2)
1✔
149
        self.assertEqual("http://%s/example?%s" % (hostname, parameters2_str), target_url7)
1✔
150

151
        parameters3 = {
1✔
152
            "alphavalue": "a",
153
            "emptynumvaluelist": [],
154
            "numvaluelist": [""],
155
        }
156
        parameters3_decoded = {"alphavalue": "alphavalue=a", "numvaluelist": "numvaluelist[]="}
1✔
157
        parameters3_str = "&".join((parameters3_decoded[x] for x in parameters3.keys() if x in parameters3_decoded))
1✔
158
        target_url8 = OneLogin_Saml2_Utils.redirect(url, parameters3, request_data)
1✔
159
        self.assertEqual("http://%s/example?%s" % (hostname, parameters3_str), target_url8)
1✔
160

161
    def testGetselfhost(self):
1✔
162
        """
163
        Tests the get_self_host method of the OneLogin_Saml2_Utils
164
        """
165
        request_data = {}
1✔
166
        with self.assertRaises(Exception) as context:
1✔
167
            OneLogin_Saml2_Utils.get_self_url_host(request_data)
1✔
168
            exception = context.exception
×
169
            self.assertIn("No hostname defined", str(exception))
×
170

171
        if sys.version_info > (3, 2, 0):
1!
172
            request_data = {"server_name": "example.com"}
1✔
173
            with self.assertWarns(Warning) as context:
1✔
174
                self_host = OneLogin_Saml2_Utils.get_self_host(request_data)
1✔
175

176
            self.assertEqual("example.com", self_host)
1✔
177

178
        request_data = {"http_host": "example.com"}
1✔
179
        self.assertEqual("example.com", OneLogin_Saml2_Utils.get_self_host(request_data))
1✔
180

181
        request_data = {"http_host": "example.com:443"}
1✔
182
        self.assertEqual("example.com:443", OneLogin_Saml2_Utils.get_self_host(request_data))
1✔
183

184
        request_data = {"http_host": "example.com:ok"}
1✔
185
        self.assertEqual("example.com:ok", OneLogin_Saml2_Utils.get_self_host(request_data))
1✔
186

187
    def testisHTTPS(self):
1✔
188
        """
189
        Tests the is_https method of the OneLogin_Saml2_Utils
190
        """
191
        request_data = {"https": "off"}
1✔
192
        self.assertFalse(OneLogin_Saml2_Utils.is_https(request_data))
1✔
193

194
        request_data = {"https": "on"}
1✔
195
        self.assertTrue(OneLogin_Saml2_Utils.is_https(request_data))
1✔
196

197
        request_data = {"server_port": "443"}
1✔
198
        self.assertTrue(OneLogin_Saml2_Utils.is_https(request_data))
1✔
199

200
    def testGetSelfURLhost(self):
1✔
201
        """
202
        Tests the get_self_url_host method of the OneLogin_Saml2_Utils
203
        """
204
        request_data = {"http_host": "example.com"}
1✔
205
        self.assertEqual("http://example.com", OneLogin_Saml2_Utils.get_self_url_host(request_data))
1✔
206

207
        if sys.version_info > (3, 2, 0):
1!
208
            with self.assertWarns(Warning) as context:
1✔
209
                request_data["server_port"] = "80"
1✔
210
                self.assertEqual("http://example.com", OneLogin_Saml2_Utils.get_self_url_host(request_data))
1✔
211

212
            with self.assertWarns(Warning) as context:
1✔
213
                request_data["server_port"] = "81"
1✔
214
                self.assertEqual("http://example.com:81", OneLogin_Saml2_Utils.get_self_url_host(request_data))
1✔
215

216
            with self.assertWarns(Warning) as context:
1✔
217
                request_data["server_port"] = "443"
1✔
218
                self.assertEqual("https://example.com", OneLogin_Saml2_Utils.get_self_url_host(request_data))
1✔
219

220
        del request_data["server_port"]
1✔
221
        request_data["https"] = "on"
1✔
222
        self.assertEqual("https://example.com", OneLogin_Saml2_Utils.get_self_url_host(request_data))
1✔
223

224
        if sys.version_info > (3, 2, 0):
1!
225
            with self.assertWarns(Warning) as context:
1✔
226
                request_data["server_port"] = "444"
1✔
227
                self.assertEqual("https://example.com:444", OneLogin_Saml2_Utils.get_self_url_host(request_data))
1✔
228

229
            with self.assertWarns(Warning) as context:
1✔
230
                request_data["server_port"] = "443"
1✔
231
                request_data["request_uri"] = ""
1✔
232
                self.assertEqual("https://example.com", OneLogin_Saml2_Utils.get_self_url_host(request_data))
1✔
233

234
            with self.assertWarns(Warning) as context:
1✔
235
                request_data["request_uri"] = "/"
1✔
236
                self.assertEqual("https://example.com", OneLogin_Saml2_Utils.get_self_url_host(request_data))
1✔
237

238
            with self.assertWarns(Warning) as context:
1✔
239
                request_data["request_uri"] = "onelogin/"
1✔
240
                self.assertEqual("https://example.com", OneLogin_Saml2_Utils.get_self_url_host(request_data))
1✔
241

242
            with self.assertWarns(Warning) as context:
1✔
243
                request_data["request_uri"] = "/onelogin"
1✔
244
                self.assertEqual("https://example.com", OneLogin_Saml2_Utils.get_self_url_host(request_data))
1✔
245

246
            with self.assertWarns(Warning) as context:
1✔
247
                request_data["request_uri"] = "https://example.com/onelogin/sso"
1✔
248
                self.assertEqual("https://example.com", OneLogin_Saml2_Utils.get_self_url_host(request_data))
1✔
249

250
        request_data2 = {"request_uri": "example.com/onelogin/sso"}
1✔
251
        with self.assertRaises(Exception) as context:
1✔
252
            OneLogin_Saml2_Utils.get_self_url_host(request_data2)
1✔
253
            exception = context.exception
×
254
            self.assertIn("No hostname defined", str(exception))
×
255

256
    def testGetSelfURL(self):
1✔
257
        """
258
        Tests the get_self_url method of the OneLogin_Saml2_Utils
259
        """
260
        request_data = {"http_host": "example.com"}
1✔
261
        url = OneLogin_Saml2_Utils.get_self_url_host(request_data)
1✔
262
        self.assertEqual(url, OneLogin_Saml2_Utils.get_self_url(request_data))
1✔
263

264
        request_data["request_uri"] = ""
1✔
265
        self.assertEqual(url, OneLogin_Saml2_Utils.get_self_url(request_data))
1✔
266

267
        request_data["request_uri"] = "/"
1✔
268
        self.assertEqual(url + "/", OneLogin_Saml2_Utils.get_self_url(request_data))
1✔
269

270
        request_data["request_uri"] = "index.html"
1✔
271
        self.assertEqual(url + "index.html", OneLogin_Saml2_Utils.get_self_url(request_data))
1✔
272

273
        request_data["request_uri"] = "?index.html"
1✔
274
        self.assertEqual(url + "?index.html", OneLogin_Saml2_Utils.get_self_url(request_data))
1✔
275

276
        request_data["request_uri"] = "/index.html"
1✔
277
        self.assertEqual(url + "/index.html", OneLogin_Saml2_Utils.get_self_url(request_data))
1✔
278

279
        request_data["request_uri"] = "/index.html?testing"
1✔
280
        self.assertEqual(url + "/index.html?testing", OneLogin_Saml2_Utils.get_self_url(request_data))
1✔
281

282
        request_data["request_uri"] = "/test/index.html?testing"
1✔
283
        self.assertEqual(url + "/test/index.html?testing", OneLogin_Saml2_Utils.get_self_url(request_data))
1✔
284

285
        request_data["request_uri"] = "https://example.com/testing"
1✔
286
        self.assertEqual(url + "/testing", OneLogin_Saml2_Utils.get_self_url(request_data))
1✔
287

288
    def testGetSelfURLNoQuery(self):
1✔
289
        """
290
        Tests the get_self_url_no_query method of the OneLogin_Saml2_Utils
291
        """
292
        request_data = {"http_host": "example.com", "script_name": "/index.html"}
1✔
293
        url = OneLogin_Saml2_Utils.get_self_url_host(request_data) + request_data["script_name"]
1✔
294
        self.assertEqual(url, OneLogin_Saml2_Utils.get_self_url_no_query(request_data))
1✔
295

296
        request_data["path_info"] = "/test"
1✔
297
        self.assertEqual(url + "/test", OneLogin_Saml2_Utils.get_self_url_no_query(request_data))
1✔
298

299
    def testGetSelfRoutedURLNoQuery(self):
1✔
300
        """
301
        Tests the get_self_routed_url_no_query method of the OneLogin_Saml2_Utils
302
        """
303
        request_data = {"http_host": "example.com", "request_uri": "/example1/route?x=test", "query_string": "?x=test"}
1✔
304
        url = OneLogin_Saml2_Utils.get_self_url_host(request_data) + "/example1/route"
1✔
305
        self.assertEqual(url, OneLogin_Saml2_Utils.get_self_routed_url_no_query(request_data))
1✔
306

307
        request_data_2 = {
1✔
308
            "http_host": "example.com",
309
            "request_uri": "",
310
        }
311
        url_2 = OneLogin_Saml2_Utils.get_self_url_host(request_data_2)
1✔
312
        self.assertEqual(url_2, OneLogin_Saml2_Utils.get_self_routed_url_no_query(request_data_2))
1✔
313

314
        request_data_3 = {
1✔
315
            "http_host": "example.com",
316
        }
317
        url_3 = OneLogin_Saml2_Utils.get_self_url_host(request_data_3)
1✔
318
        self.assertEqual(url_3, OneLogin_Saml2_Utils.get_self_routed_url_no_query(request_data_3))
1✔
319

320
        request_data_4 = {"http_host": "example.com", "request_uri": "/example1/route/test/", "query_string": "?invalid=1"}
1✔
321
        url_4 = OneLogin_Saml2_Utils.get_self_url_host(request_data_4) + "/example1/route/test/"
1✔
322
        self.assertEqual(url_4, OneLogin_Saml2_Utils.get_self_routed_url_no_query(request_data_4))
1✔
323

324
        request_data_5 = {"http_host": "example.com", "request_uri": "/example1/route/test/", "query_string": ""}
1✔
325
        url_5 = OneLogin_Saml2_Utils.get_self_url_host(request_data_5) + "/example1/route/test/"
1✔
326
        self.assertEqual(url_5, OneLogin_Saml2_Utils.get_self_routed_url_no_query(request_data_5))
1✔
327

328
        request_data_6 = {
1✔
329
            "http_host": "example.com",
330
            "request_uri": "/example1/route/test/",
331
        }
332
        url_6 = OneLogin_Saml2_Utils.get_self_url_host(request_data_6) + "/example1/route/test/"
1✔
333
        self.assertEqual(url_6, OneLogin_Saml2_Utils.get_self_routed_url_no_query(request_data_6))
1✔
334

335
    def testGetStatus(self):
1✔
336
        """
337
        Gets the status of a message
338
        """
339
        xml = self.file_contents(join(self.data_path, "responses", "response1.xml.base64"))
1✔
340
        xml = b64decode(xml)
1✔
341
        dom = etree.fromstring(xml)
1✔
342

343
        status = OneLogin_Saml2_Utils.get_status(dom)
1✔
344
        self.assertEqual(OneLogin_Saml2_Constants.STATUS_SUCCESS, status["code"])
1✔
345

346
        xml2 = self.file_contents(join(self.data_path, "responses", "invalids", "status_code_responder.xml.base64"))
1✔
347
        xml2 = b64decode(xml2)
1✔
348
        dom2 = etree.fromstring(xml2)
1✔
349

350
        status2 = OneLogin_Saml2_Utils.get_status(dom2)
1✔
351
        self.assertEqual(OneLogin_Saml2_Constants.STATUS_RESPONDER, status2["code"])
1✔
352
        self.assertEqual("", status2["msg"])
1✔
353

354
        xml3 = self.file_contents(join(self.data_path, "responses", "invalids", "status_code_responer_and_msg.xml.base64"))
1✔
355
        xml3 = b64decode(xml3)
1✔
356
        dom3 = etree.fromstring(xml3)
1✔
357

358
        status3 = OneLogin_Saml2_Utils.get_status(dom3)
1✔
359
        self.assertEqual(OneLogin_Saml2_Constants.STATUS_RESPONDER, status3["code"])
1✔
360
        self.assertEqual("something_is_wrong", status3["msg"])
1✔
361

362
        xml_inv = self.file_contents(join(self.data_path, "responses", "invalids", "no_status.xml.base64"))
1✔
363
        xml_inv = b64decode(xml_inv)
1✔
364
        dom_inv = etree.fromstring(xml_inv)
1✔
365

366
        with self.assertRaisesRegex(Exception, "Missing Status on response"):
1✔
367
            OneLogin_Saml2_Utils.get_status(dom_inv)
1✔
368

369
        xml_inv2 = self.file_contents(join(self.data_path, "responses", "invalids", "no_status_code.xml.base64"))
1✔
370
        xml_inv2 = b64decode(xml_inv2)
1✔
371
        dom_inv2 = etree.fromstring(xml_inv2)
1✔
372

373
        with self.assertRaisesRegex(Exception, "Missing Status Code on response"):
1✔
374
            OneLogin_Saml2_Utils.get_status(dom_inv2)
1✔
375

376
    def testParseDuration(self):
1✔
377
        """
378
        Tests the parse_duration method of the OneLogin_Saml2_Utils
379
        """
380
        duration = "PT1393462294S"
1✔
381
        timestamp = 1393876825
1✔
382

383
        parsed_duration = OneLogin_Saml2_Utils.parse_duration(duration, timestamp)
1✔
384
        self.assertEqual(2787339119, parsed_duration)
1✔
385

386
        parsed_duration_2 = OneLogin_Saml2_Utils.parse_duration(duration)
1✔
387
        self.assertTrue(parsed_duration_2 > parsed_duration)
1✔
388

389
        invalid_duration = "PT1Y"
1✔
390
        with self.assertRaises(Exception) as context:
1✔
391
            OneLogin_Saml2_Utils.parse_duration(invalid_duration)
1✔
392
            exception = context.exception
×
393
            self.assertIn("Unrecognised ISO 8601 date format", str(exception))
×
394

395
        new_duration = "P1Y1M"
1✔
396
        parsed_duration_4 = OneLogin_Saml2_Utils.parse_duration(new_duration, timestamp)
1✔
397
        self.assertEqual(1428091225, parsed_duration_4)
1✔
398

399
        neg_duration = "-P14M"
1✔
400
        parsed_duration_5 = OneLogin_Saml2_Utils.parse_duration(neg_duration, timestamp)
1✔
401
        self.assertEqual(1357243225, parsed_duration_5)
1✔
402

403
    def testParseSAML2Time(self):
1✔
404
        """
405
        Tests the parse_SAML_to_time method of the OneLogin_Saml2_Utils
406
        """
407
        time = 1386650371
1✔
408
        saml_time = "2013-12-10T04:39:31Z"
1✔
409
        self.assertEqual(time, OneLogin_Saml2_Utils.parse_SAML_to_time(saml_time))
1✔
410
        with self.assertRaises(Exception) as context:
1✔
411
            OneLogin_Saml2_Utils.parse_SAML_to_time("invalidSAMLTime")
1✔
412
            exception = context.exception
×
413
            self.assertIn("does not match format", str(exception))
×
414

415
        # Now test if toolkit supports miliseconds
416
        saml_time2 = "2013-12-10T04:39:31.120Z"
1✔
417
        self.assertEqual(time, OneLogin_Saml2_Utils.parse_SAML_to_time(saml_time2))
1✔
418

419
        # Now test if toolkit supports microseconds
420
        saml_time3 = "2013-12-10T04:39:31.120240Z"
1✔
421
        self.assertEqual(time, OneLogin_Saml2_Utils.parse_SAML_to_time(saml_time3))
1✔
422

423
        # Now test if toolkit supports nanoseconds
424
        saml_time4 = "2013-12-10T04:39:31.120240360Z"
1✔
425
        self.assertEqual(time, OneLogin_Saml2_Utils.parse_SAML_to_time(saml_time4))
1✔
426

427
    def testParseTime2SAML(self):
1✔
428
        """
429
        Tests the parse_time_to_SAML method of the OneLogin_Saml2_Utils
430
        """
431
        time = 1386650371
1✔
432
        saml_time = "2013-12-10T04:39:31Z"
1✔
433
        self.assertEqual(saml_time, OneLogin_Saml2_Utils.parse_time_to_SAML(time))
1✔
434
        with self.assertRaises(Exception) as context:
1✔
435
            OneLogin_Saml2_Utils.parse_time_to_SAML("invalidtime")
1✔
436
            exception = context.exception
×
437
            self.assertIn("could not convert string to float", str(exception))
×
438

439
    def testGetExpireTime(self):
1✔
440
        """
441
        Tests the get_expire_time method of the OneLogin_Saml2_Utils
442
        """
443
        self.assertEqual(None, OneLogin_Saml2_Utils.get_expire_time())
1✔
444
        self.assertNotEqual(None, OneLogin_Saml2_Utils.get_expire_time("PT360000S"))
1✔
445

446
        self.assertEqual("1291955971", OneLogin_Saml2_Utils.get_expire_time("PT360000S", "2010-12-10T04:39:31Z"))
1✔
447
        self.assertEqual("1291955971", OneLogin_Saml2_Utils.get_expire_time("PT360000S", 1291955971))
1✔
448

449
        self.assertNotEqual("3311642371", OneLogin_Saml2_Utils.get_expire_time("PT360000S", "2074-12-10T04:39:31Z"))
1✔
450
        self.assertNotEqual("3311642371", OneLogin_Saml2_Utils.get_expire_time("PT360000S", 1418186371))
1✔
451

452
    def _generate_name_id_element(self, name_qualifier):
1✔
453
        name_id_value = "value"
1✔
454
        entity_id = "sp-entity-id"
1✔
455
        name_id_format = "name-id-format"
1✔
456

457
        raw_name_id = OneLogin_Saml2_Utils.generate_name_id(
1✔
458
            name_id_value,
459
            entity_id,
460
            name_id_format,
461
            nq=name_qualifier,
462
        )
463
        parser = etree.XMLParser(recover=True)
1✔
464
        return etree.fromstring(raw_name_id, parser)
1✔
465

466
    def testNameidGenerationIncludesNameQualifierAttribute(self):
1✔
467
        """
468
        Tests the inclusion of NameQualifier in the generateNameId method of the OneLogin_Saml2_Utils
469
        """
470
        idp_name_qualifier = "idp-name-qualifier"
1✔
471
        idp_name_qualifier_attribute = ("NameQualifier", idp_name_qualifier)
1✔
472

473
        name_id = self._generate_name_id_element(idp_name_qualifier)
1✔
474

475
        self.assertIn(idp_name_qualifier_attribute, name_id.attrib.items())
1✔
476

477
    def testNameidGenerationDoesNotIncludeNameQualifierAttribute(self):
1✔
478
        """
479
        Tests the (not) inclusion of NameQualifier in the generateNameId method of the OneLogin_Saml2_Utils
480
        """
481
        idp_name_qualifier = None
1✔
482
        not_expected_attribute = "NameQualifier"
1✔
483

484
        name_id = self._generate_name_id_element(idp_name_qualifier)
1✔
485

486
        self.assertNotIn(not_expected_attribute, name_id.attrib.keys())
1✔
487

488
    def testGenerateNameIdWithoutFormat(self):
1✔
489
        """
490
        Tests the generateNameId method of the OneLogin_Saml2_Utils
491
        """
492
        name_id_value = "ONELOGIN_ce998811003f4e60f8b07a311dc641621379cfde"
1✔
493
        name_id_format = None
1✔
494

495
        name_id = OneLogin_Saml2_Utils.generate_name_id(name_id_value, None, name_id_format)
1✔
496
        expected_name_id = "<saml:NameID>ONELOGIN_ce998811003f4e60f8b07a311dc641621379cfde</saml:NameID>"
1✔
497
        self.assertEqual(name_id, expected_name_id)
1✔
498

499
    def testGenerateNameIdWithSPNameQualifier(self):
1✔
500
        """
501
        Tests the generateNameId method of the OneLogin_Saml2_Utils
502
        """
503
        name_id_value = "ONELOGIN_ce998811003f4e60f8b07a311dc641621379cfde"
1✔
504
        entity_id = "http://stuff.com/endpoints/metadata.php"
1✔
505
        name_id_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
1✔
506

507
        name_id = OneLogin_Saml2_Utils.generate_name_id(name_id_value, entity_id, name_id_format)
1✔
508
        expected_name_id = '<saml:NameID SPNameQualifier="http://stuff.com/endpoints/metadata.php" Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">ONELOGIN_ce998811003f4e60f8b07a311dc641621379cfde</saml:NameID>'
1✔
509
        self.assertEqual(expected_name_id, name_id)
1✔
510

511
        settings_info = self.loadSettingsJSON()
1✔
512
        x509cert = settings_info["idp"]["x509cert"]
1✔
513
        key = OneLogin_Saml2_Utils.format_cert(x509cert)
1✔
514

515
        name_id_enc = OneLogin_Saml2_Utils.generate_name_id(name_id_value, entity_id, name_id_format, key)
1✔
516
        expected_name_id_enc = '<saml:EncryptedID><xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Type="http://www.w3.org/2001/04/xmlenc#Element">\n<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>\n<dsig:KeyInfo xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">\n<xenc:EncryptedKey>\n<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"/>\n<xenc:CipherData>\n<xenc:CipherValue>'
1✔
517
        self.assertIn(expected_name_id_enc, name_id_enc)
1✔
518

519
    def testGenerateNameIdWithoutSPNameQualifier(self):
1✔
520
        """
521
        Tests the generateNameId method of the OneLogin_Saml2_Utils
522
        """
523
        name_id_value = "ONELOGIN_ce998811003f4e60f8b07a311dc641621379cfde"
1✔
524
        name_id_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
1✔
525

526
        name_id = OneLogin_Saml2_Utils.generate_name_id(name_id_value, None, name_id_format)
1✔
527
        expected_name_id = '<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">ONELOGIN_ce998811003f4e60f8b07a311dc641621379cfde</saml:NameID>'
1✔
528
        self.assertEqual(expected_name_id, name_id)
1✔
529

530
        settings_info = self.loadSettingsJSON()
1✔
531
        x509cert = settings_info["idp"]["x509cert"]
1✔
532
        key = OneLogin_Saml2_Utils.format_cert(x509cert)
1✔
533

534
        name_id_enc = OneLogin_Saml2_Utils.generate_name_id(name_id_value, None, name_id_format, key)
1✔
535
        expected_name_id_enc = '<saml:EncryptedID><xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Type="http://www.w3.org/2001/04/xmlenc#Element">\n<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>\n<dsig:KeyInfo xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">\n<xenc:EncryptedKey>\n<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"/>\n<xenc:CipherData>\n<xenc:CipherValue>'
1✔
536
        self.assertIn(expected_name_id_enc, name_id_enc)
1✔
537

538
    def testCalculateX509Fingerprint(self):
1✔
539
        """
540
        Tests the calculateX509Fingerprint method of the OneLogin_Saml2_Utils
541
        """
542
        settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())
1✔
543
        cert_path = settings.get_cert_path()
1✔
544

545
        key = self.file_contents(cert_path + "sp.key")
1✔
546
        cert = self.file_contents(cert_path + "sp.crt")
1✔
547

548
        self.assertEqual(None, OneLogin_Saml2_Utils.calculate_x509_fingerprint(key))
1✔
549
        self.assertEqual("afe71c28ef740bc87425be13a2263d37971da1f9", OneLogin_Saml2_Utils.calculate_x509_fingerprint(cert))
1✔
550
        self.assertEqual("afe71c28ef740bc87425be13a2263d37971da1f9", OneLogin_Saml2_Utils.calculate_x509_fingerprint(cert, "sha1"))
1✔
551

552
        self.assertEqual("c51cfa06c7a49767f6eab18238eae1c56708e29264da3d11f538a12cd2c357ba", OneLogin_Saml2_Utils.calculate_x509_fingerprint(cert, "sha256"))
1✔
553

554
        self.assertEqual("bc5826e6f9429247254bae5e3c650e6968a36a62d23075eb168134978d88600559c10830c28711b2c29c7947c0c2eb1d", OneLogin_Saml2_Utils.calculate_x509_fingerprint(cert, "sha384"))
1✔
555

556
        self.assertEqual(
1✔
557
            "3db29251b97559c67988ea0754cb0573fc409b6f75d89282d57cfb75089539b0bbdb2dcd9ec6e032549ecbc466439d5992e18db2cf5494ca2fe1b2e16f348dff",
558
            OneLogin_Saml2_Utils.calculate_x509_fingerprint(cert, "sha512"),
559
        )
560

561
    def testDeleteLocalSession(self):
1✔
562
        """
563
        Tests the delete_local_session method of the OneLogin_Saml2_Utils
564
        """
565
        global local_session_test
566
        local_session_test = 1
1✔
567

568
        OneLogin_Saml2_Utils.delete_local_session()
1✔
569
        self.assertEqual(1, local_session_test)
1✔
570

571
        dscb = lambda: self.session_cear()
1✔
572
        OneLogin_Saml2_Utils.delete_local_session(dscb)
1✔
573
        self.assertEqual(0, local_session_test)
1✔
574

575
    def session_cear(self):
1✔
576
        """
577
        Auxiliar method to test the delete_local_session method of the OneLogin_Saml2_Utils
578
        """
579
        global local_session_test
580
        local_session_test = 0
1✔
581

582
    def testFormatFingerPrint(self):
1✔
583
        """
584
        Tests the format_finger_print method of the OneLogin_Saml2_Utils
585
        """
586
        finger_print_1 = "AF:E7:1C:28:EF:74:0B:C8:74:25:BE:13:A2:26:3D:37:97:1D:A1:F9"
1✔
587
        self.assertEqual("afe71c28ef740bc87425be13a2263d37971da1f9", OneLogin_Saml2_Utils.format_finger_print(finger_print_1))
1✔
588

589
        finger_print_2 = "afe71c28ef740bc87425be13a2263d37971da1f9"
1✔
590
        self.assertEqual("afe71c28ef740bc87425be13a2263d37971da1f9", OneLogin_Saml2_Utils.format_finger_print(finger_print_2))
1✔
591

592
    def testDecryptElement(self):
1✔
593
        """
594
        Tests the decrypt_element method of the OneLogin_Saml2_Utils
595
        """
596
        settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())
1✔
597

598
        key = settings.get_sp_key()
1✔
599

600
        xml_nameid_enc = b64decode(self.file_contents(join(self.data_path, "responses", "response_encrypted_nameid.xml.base64")))
1✔
601
        dom_nameid_enc = etree.fromstring(xml_nameid_enc)
1✔
602
        encrypted_nameid_nodes = dom_nameid_enc.find(".//saml:EncryptedID", namespaces=OneLogin_Saml2_Constants.NSMAP)
1✔
603
        encrypted_data = encrypted_nameid_nodes[0]
1✔
604
        decrypted_nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key)
1✔
605
        self.assertEqual("saml:NameID", decrypted_nameid.tag)
1✔
606
        self.assertEqual("2de11defd199f8d5bb63f9b7deb265ba5c675c10", decrypted_nameid.text)
1✔
607

608
        xml_assertion_enc = b64decode(self.file_contents(join(self.data_path, "responses", "valid_encrypted_assertion_encrypted_nameid.xml.base64")))
1✔
609
        dom_assertion_enc = etree.fromstring(xml_assertion_enc)
1✔
610
        encrypted_assertion_enc_nodes = dom_assertion_enc.find(".//saml:EncryptedAssertion", namespaces=OneLogin_Saml2_Constants.NSMAP)
1✔
611
        encrypted_data_assert = encrypted_assertion_enc_nodes[0]
1✔
612

613
        decrypted_assertion = OneLogin_Saml2_Utils.decrypt_element(encrypted_data_assert, key)
1✔
614
        self.assertEqual("{%s}Assertion" % OneLogin_Saml2_Constants.NS_SAML, decrypted_assertion.tag)
1✔
615
        self.assertEqual("_6fe189b1c241827773902f2b1d3a843418206a5c97", decrypted_assertion.get("ID"))
1✔
616

617
        encrypted_nameid_nodes = decrypted_assertion.xpath("./saml:Subject/saml:EncryptedID", namespaces=OneLogin_Saml2_Constants.NSMAP)
1✔
618
        encrypted_data = encrypted_nameid_nodes[0][0]
1✔
619
        decrypted_nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key)
1✔
620
        self.assertEqual("{%s}NameID" % OneLogin_Saml2_Constants.NS_SAML, decrypted_nameid.tag)
1✔
621
        self.assertEqual("457bdb600de717891c77647b0806ce59c089d5b8", decrypted_nameid.text)
1✔
622

623
        key_2_file_name = join(self.data_path, "misc", "sp2.key")
1✔
624
        f = open(key_2_file_name, "r")
1✔
625
        key2 = f.read()
1✔
626
        f.close()
1✔
627

628
        # sp.key and sp2.key are equivalent we should be able to decrypt the nameID again
629
        decrypted_nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key2)
1✔
630
        self.assertIn("{%s}NameID" % (OneLogin_Saml2_Constants.NS_SAML), decrypted_nameid.tag)
1✔
631
        self.assertEqual("457bdb600de717891c77647b0806ce59c089d5b8", decrypted_nameid.text)
1✔
632

633
        key_3_file_name = join(self.data_path, "misc", "sp3.key")
1✔
634
        f = open(key_3_file_name, "r")
1✔
635
        key3 = f.read()
1✔
636
        f.close()
1✔
637

638
        # sp.key and sp3.key are equivalent we should be able to decrypt the nameID again
639
        decrypted_nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key3)
1✔
640
        self.assertIn("{%s}NameID" % (OneLogin_Saml2_Constants.NS_SAML), decrypted_nameid.tag)
1✔
641
        self.assertEqual("457bdb600de717891c77647b0806ce59c089d5b8", decrypted_nameid.text)
1✔
642

643
        key_4_file_name = join(self.data_path, "misc", "sp4.key")
1✔
644
        f = open(key_4_file_name, "r")
1✔
645
        key4 = f.read()
1✔
646
        f.close()
1✔
647

648
        with self.assertRaisesRegex(Exception, "(1, 'failed to decrypt')"):
1✔
649
            OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key4)
1✔
650

651
        xml_nameid_enc_2 = b64decode(self.file_contents(join(self.data_path, "responses", "invalids", "encrypted_nameID_without_EncMethod.xml.base64")))
1✔
652
        dom_nameid_enc_2 = parseString(xml_nameid_enc_2)
1✔
653
        encrypted_nameid_nodes_2 = dom_nameid_enc_2.getElementsByTagName("saml:EncryptedID")
1✔
654
        encrypted_data_2 = encrypted_nameid_nodes_2[0].firstChild
1✔
655

656
        with self.assertRaisesRegex(Exception, "(1, 'failed to decrypt')"):
1✔
657
            OneLogin_Saml2_Utils.decrypt_element(encrypted_data_2, key)
1✔
658

659
        xml_nameid_enc_3 = b64decode(self.file_contents(join(self.data_path, "responses", "invalids", "encrypted_nameID_without_keyinfo.xml.base64")))
1✔
660
        dom_nameid_enc_3 = parseString(xml_nameid_enc_3)
1✔
661
        encrypted_nameid_nodes_3 = dom_nameid_enc_3.getElementsByTagName("saml:EncryptedID")
1✔
662
        encrypted_data_3 = encrypted_nameid_nodes_3[0].firstChild
1✔
663

664
        with self.assertRaisesRegex(Exception, "(1, 'failed to decrypt')"):
1✔
665
            OneLogin_Saml2_Utils.decrypt_element(encrypted_data_3, key)
1✔
666

667
    def testDecryptElementInplace(self):
1✔
668
        """
669
        Tests the decrypt_element method of the OneLogin_Saml2_Utils with inplace=True
670
        """
671
        settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())
1✔
672

673
        key = settings.get_sp_key()
1✔
674

675
        xml_nameid_enc = b64decode(self.file_contents(join(self.data_path, "responses", "response_encrypted_nameid.xml.base64")))
1✔
676
        dom = fromstring(xml_nameid_enc)
1✔
677
        encrypted_node = dom.xpath("//saml:EncryptedID/xenc:EncryptedData", namespaces=OneLogin_Saml2_Constants.NSMAP)[0]
1✔
678

679
        # can be decrypted twice when copy the node first
680
        for _ in range(2):
1✔
681
            decrypted_nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_node, key, inplace=False)
1✔
682
            self.assertIn("NameID", decrypted_nameid.tag)
1✔
683
            self.assertEqual("2de11defd199f8d5bb63f9b7deb265ba5c675c10", decrypted_nameid.text)
1✔
684

685
        # can only be decrypted once in place
686
        decrypted_nameid = OneLogin_Saml2_Utils.decrypt_element(encrypted_node, key, inplace=True)
1✔
687
        self.assertIn("NameID", decrypted_nameid.tag)
1✔
688
        self.assertEqual("2de11defd199f8d5bb63f9b7deb265ba5c675c10", decrypted_nameid.text)
1✔
689

690
        # can't be decrypted twice since it has been decrypted inplace
691
        with self.assertRaisesRegex(Exception, "(1, 'failed to decrypt')"):
1✔
692
            OneLogin_Saml2_Utils.decrypt_element(encrypted_node, key, inplace=True)
1✔
693

694
    def testAddSign(self):
1✔
695
        """
696
        Tests the add_sign method of the OneLogin_Saml2_Utils
697
        """
698
        settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())
1✔
699
        key = settings.get_sp_key()
1✔
700
        cert = settings.get_sp_cert()
1✔
701

702
        xml_authn = b64decode(self.file_contents(join(self.data_path, "requests", "authn_request.xml.base64")))
1✔
703
        xml_authn_signed = compat.to_string(OneLogin_Saml2_Utils.add_sign(xml_authn, key, cert))
1✔
704
        self.assertIn("<ds:SignatureValue>", xml_authn_signed)
1✔
705

706
        res = parseString(xml_authn_signed)
1✔
707
        ds_signature = res.firstChild.firstChild.nextSibling.nextSibling.nextSibling
1✔
708
        self.assertIn("ds:Signature", ds_signature.tagName)
1✔
709

710
        xml_authn_dom = parseString(xml_authn)
1✔
711
        xml_authn_signed_2 = compat.to_string(OneLogin_Saml2_Utils.add_sign(xml_authn_dom.toxml(), key, cert))
1✔
712
        self.assertIn("<ds:SignatureValue>", xml_authn_signed_2)
1✔
713
        res_2 = parseString(xml_authn_signed_2)
1✔
714
        ds_signature_2 = res_2.firstChild.firstChild.nextSibling.nextSibling.nextSibling
1✔
715
        self.assertIn("ds:Signature", ds_signature_2.tagName)
1✔
716

717
        xml_authn_signed_3 = compat.to_string(OneLogin_Saml2_Utils.add_sign(xml_authn_dom.firstChild.toxml(), key, cert))
1✔
718
        self.assertIn("<ds:SignatureValue>", xml_authn_signed_3)
1✔
719
        res_3 = parseString(xml_authn_signed_3)
1✔
720
        ds_signature_3 = res_3.firstChild.firstChild.nextSibling.nextSibling.nextSibling
1✔
721
        self.assertIn("ds:Signature", ds_signature_3.tagName)
1✔
722

723
        xml_authn_etree = etree.fromstring(xml_authn)
1✔
724
        xml_authn_signed_4 = compat.to_string(OneLogin_Saml2_Utils.add_sign(xml_authn_etree, key, cert))
1✔
725
        self.assertIn("<ds:SignatureValue>", xml_authn_signed_4)
1✔
726
        res_4 = parseString(xml_authn_signed_4)
1✔
727
        ds_signature_4 = res_4.firstChild.firstChild.nextSibling.nextSibling.nextSibling
1✔
728
        self.assertIn("ds:Signature", ds_signature_4.tagName)
1✔
729

730
        xml_authn_signed_5 = compat.to_string(OneLogin_Saml2_Utils.add_sign(xml_authn_etree, key, cert))
1✔
731
        self.assertIn("<ds:SignatureValue>", xml_authn_signed_5)
1✔
732
        res_5 = parseString(xml_authn_signed_5)
1✔
733
        ds_signature_5 = res_5.firstChild.firstChild.nextSibling.nextSibling.nextSibling.nextSibling
1✔
734
        self.assertIn("ds:Signature", ds_signature_5.tagName)
1✔
735

736
        xml_logout_req = b64decode(self.file_contents(join(self.data_path, "logout_requests", "logout_request.xml.base64")))
1✔
737
        xml_logout_req_signed = compat.to_string(OneLogin_Saml2_Utils.add_sign(xml_logout_req, key, cert))
1✔
738
        self.assertIn("<ds:SignatureValue>", xml_logout_req_signed)
1✔
739
        res_6 = parseString(xml_logout_req_signed)
1✔
740
        ds_signature_6 = res_6.firstChild.firstChild.nextSibling.nextSibling.nextSibling
1✔
741
        self.assertIn("ds:Signature", ds_signature_6.tagName)
1✔
742

743
        xml_logout_res = b64decode(self.file_contents(join(self.data_path, "logout_responses", "logout_response.xml.base64")))
1✔
744
        xml_logout_res_signed = compat.to_string(OneLogin_Saml2_Utils.add_sign(xml_logout_res, key, cert))
1✔
745
        self.assertIn("<ds:SignatureValue>", xml_logout_res_signed)
1✔
746
        res_7 = parseString(xml_logout_res_signed)
1✔
747
        ds_signature_7 = res_7.firstChild.firstChild.nextSibling.nextSibling.nextSibling
1✔
748
        self.assertIn("ds:Signature", ds_signature_7.tagName)
1✔
749

750
        xml_metadata = self.file_contents(join(self.data_path, "metadata", "metadata_settings1.xml"))
1✔
751
        xml_metadata_signed = compat.to_string(OneLogin_Saml2_Utils.add_sign(xml_metadata, key, cert))
1✔
752
        self.assertIn("<ds:SignatureValue>", xml_metadata_signed)
1✔
753
        res_8 = parseString(xml_metadata_signed)
1✔
754
        ds_signature_8 = res_8.firstChild.firstChild.nextSibling
1✔
755
        self.assertIn("ds:Signature", ds_signature_8.tagName)
1✔
756

757
    def testAddSignCheckAlg(self):
1✔
758
        """
759
        Tests the add_sign method of the OneLogin_Saml2_Utils
760
        Case: Review signature & digest algorithm
761
        """
762
        settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())
1✔
763
        key = settings.get_sp_key()
1✔
764
        cert = settings.get_sp_cert()
1✔
765

766
        xml_authn = b64decode(self.file_contents(join(self.data_path, "requests", "authn_request.xml.base64")))
1✔
767
        xml_authn_signed = compat.to_string(OneLogin_Saml2_Utils.add_sign(xml_authn, key, cert))
1✔
768
        self.assertIn("<ds:SignatureValue>", xml_authn_signed)
1✔
769
        self.assertIn('<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>', xml_authn_signed)
1✔
770
        self.assertIn('<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>', xml_authn_signed)
1✔
771

772
        xml_authn_signed_2 = compat.to_string(OneLogin_Saml2_Utils.add_sign(xml_authn, key, cert, False, OneLogin_Saml2_Constants.RSA_SHA256, OneLogin_Saml2_Constants.SHA384))
1✔
773
        self.assertIn("<ds:SignatureValue>", xml_authn_signed_2)
1✔
774
        self.assertIn('<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#sha384"/>', xml_authn_signed_2)
1✔
775
        self.assertIn('<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>', xml_authn_signed_2)
1✔
776

777
        xml_authn_signed_3 = compat.to_string(OneLogin_Saml2_Utils.add_sign(xml_authn, key, cert, False, OneLogin_Saml2_Constants.RSA_SHA384, OneLogin_Saml2_Constants.SHA512))
1✔
778
        self.assertIn("<ds:SignatureValue>", xml_authn_signed_3)
1✔
779
        self.assertIn('<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"/>', xml_authn_signed_3)
1✔
780
        self.assertIn('<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha384"/>', xml_authn_signed_3)
1✔
781

782
    def testValidateSign(self):
1✔
783
        """
784
        Tests the validate_sign method of the OneLogin_Saml2_Utils
785
        """
786
        settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())
1✔
787
        idp_data = settings.get_idp_data()
1✔
788
        cert = idp_data["x509cert"]
1✔
789

790
        settings_2 = OneLogin_Saml2_Settings(self.loadSettingsJSON("settings2.json"))
1✔
791
        idp_data2 = settings_2.get_idp_data()
1✔
792
        cert_2 = idp_data2["x509cert"]
1✔
793
        fingerprint_2 = OneLogin_Saml2_Utils.calculate_x509_fingerprint(cert_2)
1✔
794
        fingerprint_2_256 = OneLogin_Saml2_Utils.calculate_x509_fingerprint(cert_2, "sha256")
1✔
795

796
        try:
1✔
797
            self.assertFalse(OneLogin_Saml2_Utils.validate_sign("", cert))
1✔
798
        except Exception as e:
×
NEW
799
            self.assertEqual("Empty string supplied as input", str(e))
×
800

801
        # expired cert
802
        xml_metadata_signed = self.file_contents(join(self.data_path, "metadata", "signed_metadata_settings1.xml"))
1✔
803
        self.assertTrue(OneLogin_Saml2_Utils.validate_metadata_sign(xml_metadata_signed, cert))
1✔
804
        # expired cert, verified it
805
        self.assertFalse(OneLogin_Saml2_Utils.validate_metadata_sign(xml_metadata_signed, cert, validatecert=True))
1✔
806

807
        xml_metadata_signed_2 = self.file_contents(join(self.data_path, "metadata", "signed_metadata_settings2.xml"))
1✔
808
        self.assertTrue(OneLogin_Saml2_Utils.validate_metadata_sign(xml_metadata_signed_2, cert_2))
1✔
809
        self.assertTrue(OneLogin_Saml2_Utils.validate_metadata_sign(xml_metadata_signed_2, None, fingerprint_2))
1✔
810

811
        xml_response_msg_signed = b64decode(self.file_contents(join(self.data_path, "responses", "signed_message_response.xml.base64")))
1✔
812

813
        # expired cert
814
        self.assertTrue(OneLogin_Saml2_Utils.validate_sign(xml_response_msg_signed, cert))
1✔
815
        # expired cert, verified it
816
        self.assertFalse(OneLogin_Saml2_Utils.validate_sign(xml_response_msg_signed, cert, validatecert=True))
1✔
817

818
        # modified cert
819
        other_cert_path = join(dirname(__file__), "..", "..", "..", "certs")
1✔
820
        f = open(other_cert_path + "/certificate1", "r")
1✔
821
        cert_x = f.read()
1✔
822
        f.close()
1✔
823
        self.assertFalse(OneLogin_Saml2_Utils.validate_sign(xml_response_msg_signed, cert_x))
1✔
824
        self.assertFalse(OneLogin_Saml2_Utils.validate_sign(xml_response_msg_signed, cert_x, validatecert=True))
1✔
825

826
        xml_response_msg_signed_2 = b64decode(self.file_contents(join(self.data_path, "responses", "signed_message_response2.xml.base64")))
1✔
827
        self.assertTrue(OneLogin_Saml2_Utils.validate_sign(xml_response_msg_signed_2, cert_2))
1✔
828
        self.assertTrue(OneLogin_Saml2_Utils.validate_sign(xml_response_msg_signed_2, None, fingerprint_2))
1✔
829
        self.assertTrue(OneLogin_Saml2_Utils.validate_sign(xml_response_msg_signed_2, None, fingerprint_2, "sha1"))
1✔
830
        self.assertTrue(OneLogin_Saml2_Utils.validate_sign(xml_response_msg_signed_2, None, fingerprint_2_256, "sha256"))
1✔
831

832
        xml_response_assert_signed = b64decode(self.file_contents(join(self.data_path, "responses", "signed_assertion_response.xml.base64")))
1✔
833

834
        # expired cert
835
        self.assertTrue(OneLogin_Saml2_Utils.validate_sign(xml_response_assert_signed, cert))
1✔
836
        # expired cert, verified it
837
        self.assertFalse(OneLogin_Saml2_Utils.validate_sign(xml_response_assert_signed, cert, validatecert=True))
1✔
838

839
        xml_response_assert_signed_2 = b64decode(self.file_contents(join(self.data_path, "responses", "signed_assertion_response2.xml.base64")))
1✔
840
        self.assertTrue(OneLogin_Saml2_Utils.validate_sign(xml_response_assert_signed_2, cert_2))
1✔
841
        self.assertTrue(OneLogin_Saml2_Utils.validate_sign(xml_response_assert_signed_2, None, fingerprint_2))
1✔
842

843
        xml_response_double_signed = b64decode(self.file_contents(join(self.data_path, "responses", "double_signed_response.xml.base64")))
1✔
844

845
        # expired cert
846
        self.assertTrue(OneLogin_Saml2_Utils.validate_sign(xml_response_double_signed, cert))
1✔
847
        # expired cert, verified it
848
        self.assertFalse(OneLogin_Saml2_Utils.validate_sign(xml_response_double_signed, cert, validatecert=True))
1✔
849

850
        xml_response_double_signed_2 = b64decode(self.file_contents(join(self.data_path, "responses", "double_signed_response2.xml.base64")))
1✔
851
        self.assertTrue(OneLogin_Saml2_Utils.validate_sign(xml_response_double_signed_2, cert_2))
1✔
852
        self.assertTrue(OneLogin_Saml2_Utils.validate_sign(xml_response_double_signed_2, None, fingerprint_2))
1✔
853

854
        dom = parseString(xml_response_msg_signed_2)
1✔
855
        self.assertTrue(OneLogin_Saml2_Utils.validate_sign(dom.toxml(), cert_2))
1✔
856

857
        dom.firstChild.firstChild.firstChild.nodeValue = "https://idp.example.com/simplesaml/saml2/idp/metadata.php"
1✔
858

859
        dom.firstChild.getAttributeNode("ID").nodeValue = "_34fg27g212d63k1f923845324475802ac0fc24530b"
1✔
860
        # Reference validation failed
861
        self.assertFalse(OneLogin_Saml2_Utils.validate_sign(dom.toxml(), cert_2))
1✔
862

863
        invalid_fingerprint = "afe71c34ef740bc87434be13a2263d31271da1f9"
1✔
864
        # Wrong fingerprint
865
        self.assertFalse(OneLogin_Saml2_Utils.validate_metadata_sign(xml_metadata_signed_2, None, invalid_fingerprint))
1✔
866

867
        dom_2 = parseString(xml_response_double_signed_2)
1✔
868
        self.assertTrue(OneLogin_Saml2_Utils.validate_sign(dom_2.toxml(), cert_2))
1✔
869
        dom_2.firstChild.firstChild.firstChild.nodeValue = "https://example.com/other-idp"
1✔
870
        # Modified message
871
        self.assertFalse(OneLogin_Saml2_Utils.validate_sign(dom_2.toxml(), cert_2))
1✔
872

873
        # Try to validate directly the Assertion
874
        dom_3 = parseString(xml_response_double_signed_2)
1✔
875
        assert_elem_3 = dom_3.firstChild.firstChild.nextSibling.nextSibling.nextSibling
1✔
876
        assert_elem_3.setAttributeNS(OneLogin_Saml2_Constants.NS_SAML, "xmlns:saml", OneLogin_Saml2_Constants.NS_SAML)
1✔
877
        self.assertFalse(OneLogin_Saml2_Utils.validate_sign(assert_elem_3.toxml(), cert_2))
1✔
878

879
        # Wrong scheme
880
        no_signed = b64decode(self.file_contents(join(self.data_path, "responses", "invalids", "no_signature.xml.base64")))
1✔
881
        self.assertFalse(OneLogin_Saml2_Utils.validate_sign(no_signed, cert))
1✔
882

883
        no_key = b64decode(self.file_contents(join(self.data_path, "responses", "invalids", "no_key.xml.base64")))
1✔
884
        self.assertFalse(OneLogin_Saml2_Utils.validate_sign(no_key, cert))
1✔
885

886
        # Signature Wrapping attack
887
        wrapping_attack1 = b64decode(self.file_contents(join(self.data_path, "responses", "invalids", "signature_wrapping_attack.xml.base64")))
1✔
888
        self.assertFalse(OneLogin_Saml2_Utils.validate_sign(wrapping_attack1, cert))
1✔
889

890
    def testNormalizeUrl(self):
1✔
891
        base_url = "https://blah.com/path"
1✔
892
        capital_scheme = "hTTps://blah.com/path"
1✔
893
        capital_domain = "https://blAH.Com/path"
1✔
894
        capital_path = "https://blah.com/PAth"
1✔
895
        capital_all = "HTTPS://BLAH.COM/PATH"
1✔
896

897
        self.assertIn(base_url, OneLogin_Saml2_Utils.normalize_url(capital_scheme))
1✔
898
        self.assertIn(base_url, OneLogin_Saml2_Utils.normalize_url(capital_domain))
1✔
899
        self.assertNotIn(base_url, OneLogin_Saml2_Utils.normalize_url(capital_path))
1✔
900
        self.assertNotIn(base_url, OneLogin_Saml2_Utils.normalize_url(capital_all))
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc