Skip to content

Commit c84a36d

Browse files
committed
Add SP AuthnRequestsSigned validation
- Adds validation check to verify that the eIDAS SP has set the authn_requests_signed to True - Adds tests for the above scenario - Extract `assert_validation_errror` test function for config validation tests
1 parent cbaaa8f commit c84a36d

File tree

3 files changed

+41
-100
lines changed

3 files changed

+41
-100
lines changed

src/saml2/config.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,9 @@ def validate(self):
680680
self.get_application_identifier()),
681681
"entityid MUST be an HTTPS URL pointing to the location of its published "
682682
"metadata":
683-
parse.urlparse(self.entityid).scheme == "https"
683+
parse.urlparse(self.entityid).scheme == "https",
684+
"authn_requests_signed MUST be set to True":
685+
getattr(self, "_sp_authn_requests_signed", None) is True
684686
}
685687

686688
if not all(error_validators.values()):

tests/eidas/sp_conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"sp_type": "public",
3131
"sp_type_in_metadata": False,
3232
"force_authn": True,
33+
"authn_requests_signed": True,
3334
"node_country": "GR",
3435
"application_identifier": "CEF:eIDAS-ref:2.0",
3536
"protocol_version": [1.1, 2.2]

tests/eidas/test_sp.py

Lines changed: 37 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@ def test_protocol_version_in_metadata(self, config):
111111

112112

113113
class TestSPConfig:
114+
@staticmethod
115+
def assert_validation_error(config):
116+
conf = eIDASSPConfig()
117+
conf.load(config)
118+
with pytest.raises(ConfigValidationError):
119+
conf.validate()
120+
114121
@pytest.fixture(scope="function")
115122
def technical_contacts(self, config):
116123
return [
@@ -138,81 +145,45 @@ def config(self):
138145
def test_singlelogout_declared(self, config, raise_error_on_warning):
139146
config["service"]["sp"]["endpoints"]["single_logout_service"] = \
140147
[("https://example.com", BINDING_HTTP_POST)]
141-
conf = eIDASSPConfig()
142-
conf.load(config)
143-
144-
with pytest.raises(ConfigValidationError):
145-
conf.validate()
148+
self.assert_validation_error(config)
146149

147150
def test_artifact_resolution_declared(self, config, raise_error_on_warning):
148151
config["service"]["sp"]["endpoints"]["artifact_resolution_service"] = \
149152
[("https://example.com", BINDING_HTTP_POST)]
150-
conf = eIDASSPConfig()
151-
conf.load(config)
152-
153-
with pytest.raises(ConfigValidationError):
154-
conf.validate()
153+
self.assert_validation_error(config)
155154

156155
def test_manage_nameid_service_declared(self, config, raise_error_on_warning):
157156
config["service"]["sp"]["endpoints"]["manage_name_id_service"] = \
158157
[("https://example.com", BINDING_HTTP_POST)]
159-
conf = eIDASSPConfig()
160-
conf.load(config)
161-
162-
with pytest.raises(ConfigValidationError):
163-
conf.validate()
158+
self.assert_validation_error(config)
164159

165160
def test_no_keydescriptor(self, config):
166161
del config["cert_file"]
167162
del config["encryption_keypairs"]
168-
conf = eIDASSPConfig()
169-
conf.load(config)
170-
171-
with pytest.raises(ConfigValidationError):
172-
conf.validate()
163+
self.assert_validation_error(config)
173164

174165
def test_no_nodecountry(self, config):
175166
del config["service"]["sp"]["node_country"]
176-
conf = eIDASSPConfig()
177-
conf.load(config)
178-
179-
with pytest.raises(ConfigValidationError):
180-
conf.validate()
167+
self.assert_validation_error(config)
181168

182169
def test_nodecountry_wrong_format(self, config):
183170
config["service"]["sp"]["node_country"] = "gr"
184-
conf = eIDASSPConfig()
185-
conf.load(config)
186-
187-
with pytest.raises(ConfigValidationError):
188-
conf.validate()
171+
self.assert_validation_error(config)
189172

190173
def test_no_application_identifier_warning(self, config, raise_error_on_warning):
191174
del config["service"]["sp"]["application_identifier"]
192175

193-
conf = eIDASSPConfig()
194-
conf.load(config)
195-
196-
with pytest.raises(ConfigValidationError):
197-
conf.validate()
176+
self.assert_validation_error(config)
198177

199178
def test_empty_application_identifier_warning(self, config, raise_error_on_warning):
200179
config["service"]["sp"]["application_identifier"] = ""
201180

202-
conf = eIDASSPConfig()
203-
conf.load(config)
204-
205-
with pytest.raises(ConfigValidationError):
206-
conf.validate()
181+
self.assert_validation_error(config)
207182

208183
def test_application_identifier_wrong_format(self, config):
209184
config["service"]["sp"]["application_identifier"] = "TEST:Node.1"
210185

211-
conf = eIDASSPConfig()
212-
conf.load(config)
213-
214-
with pytest.raises(ConfigValidationError):
215-
conf.validate()
186+
self.assert_validation_error(config)
216187

217188
def test_application_identifier_ok_format(self, config, raise_error_on_warning):
218189
conf = eIDASSPConfig()
@@ -222,38 +193,22 @@ def test_application_identifier_ok_format(self, config, raise_error_on_warning):
222193
def test_no_protocol_version_warning(self, config, raise_error_on_warning):
223194
del config["service"]["sp"]["protocol_version"]
224195

225-
conf = eIDASSPConfig()
226-
conf.load(config)
227-
228-
with pytest.raises(ConfigValidationError):
229-
conf.validate()
196+
self.assert_validation_error(config)
230197

231198
def test_empty_protocol_version_warning(self, config, raise_error_on_warning):
232199
config["service"]["sp"]["protocol_version"] = ""
233200

234-
conf = eIDASSPConfig()
235-
conf.load(config)
236-
237-
with pytest.raises(ConfigValidationError):
238-
conf.validate()
201+
self.assert_validation_error(config)
239202

240203
def test_no_organization_info_warning(self, config, raise_error_on_warning):
241204
del config["organization"]
242205

243-
conf = eIDASSPConfig()
244-
conf.load(config)
245-
246-
with pytest.raises(ConfigValidationError):
247-
conf.validate()
206+
self.assert_validation_error(config)
248207

249208
def test_empty_organization_info_warning(self, config, raise_error_on_warning):
250209
config["organization"] = {}
251210

252-
conf = eIDASSPConfig()
253-
conf.load(config)
254-
255-
with pytest.raises(ConfigValidationError):
256-
conf.validate()
211+
self.assert_validation_error(config)
257212

258213
def test_no_technical_contact_person(self,
259214
config,
@@ -262,11 +217,7 @@ def test_no_technical_contact_person(self,
262217
for contact in technical_contacts:
263218
contact["contact_type"] = "other"
264219

265-
conf = eIDASSPConfig()
266-
conf.load(config)
267-
268-
with pytest.raises(ConfigValidationError):
269-
conf.validate()
220+
self.assert_validation_error(config)
270221

271222
def test_technical_contact_person_no_email(self,
272223
config,
@@ -276,11 +227,7 @@ def test_technical_contact_person_no_email(self,
276227
for contact in technical_contacts:
277228
del contact["email_address"]
278229

279-
conf = eIDASSPConfig()
280-
conf.load(config)
281-
282-
with pytest.raises(ConfigValidationError):
283-
conf.validate()
230+
self.assert_validation_error(config)
284231

285232
def test_technical_contact_person_empty_email(self,
286233
config,
@@ -290,11 +237,7 @@ def test_technical_contact_person_empty_email(self,
290237
for contact in technical_contacts:
291238
del contact["email_address"]
292239

293-
conf = eIDASSPConfig()
294-
conf.load(config)
295-
296-
with pytest.raises(ConfigValidationError):
297-
conf.validate()
240+
self.assert_validation_error(config)
298241

299242
def test_no_support_contact_person(self,
300243
config,
@@ -303,11 +246,7 @@ def test_no_support_contact_person(self,
303246
for contact in support_contacts:
304247
contact["contact_type"] = "other"
305248

306-
conf = eIDASSPConfig()
307-
conf.load(config)
308-
309-
with pytest.raises(ConfigValidationError):
310-
conf.validate()
249+
self.assert_validation_error(config)
311250

312251
def test_support_contact_person_no_email(self,
313252
config,
@@ -317,11 +256,7 @@ def test_support_contact_person_no_email(self,
317256
for contact in support_contacts:
318257
del contact["email_address"]
319258

320-
conf = eIDASSPConfig()
321-
conf.load(config)
322-
323-
with pytest.raises(ConfigValidationError):
324-
conf.validate()
259+
self.assert_validation_error(config)
325260

326261
def test_support_contact_person_empty_email(self,
327262
config,
@@ -331,17 +266,20 @@ def test_support_contact_person_empty_email(self,
331266
for contact in support_contacts:
332267
del contact["email_address"]
333268

334-
conf = eIDASSPConfig()
335-
conf.load(config)
336-
337-
with pytest.raises(ConfigValidationError):
338-
conf.validate()
269+
self.assert_validation_error(config)
339270

340271
def test_entityid_no_https(self, config):
341272
config["entityid"] = "urn:mace:example.com:saml:roland:idp"
342273

343-
conf = eIDASSPConfig()
344-
conf.load(config)
274+
self.assert_validation_error(config)
275+
276+
def test_authn_requests_signed_false(self, config):
277+
config["service"]["sp"]["authn_requests_signed"] = False
278+
279+
self.assert_validation_error(config)
280+
281+
def test_authn_requests_signed_unassigned(self, config):
282+
del config["service"]["sp"]["authn_requests_signed"]
283+
284+
self.assert_validation_error(config)
345285

346-
with pytest.raises(ConfigValidationError):
347-
conf.validate()

0 commit comments

Comments
 (0)