@@ -179,6 +179,159 @@ def test_authn_request(self, context, idp_conf):
179179 req_params = dict (parse_qsl (urlparse (resp .message ).query ))
180180 assert context .state [self .samlbackend .name ]["relay_state" ] == req_params ["RelayState" ]
181181
182+ def test_authn_request_requested_attributes (
183+ self , context , idp_conf , sp_conf
184+ ):
185+ requested_attributes = [
186+ {"friendly_name" : "cn" , "required" : True },
187+ {"friendly_name" : "sn" , "required" : False }
188+ ]
189+
190+ backend = SAMLBackend (
191+ None ,
192+ INTERNAL_ATTRIBUTES ,
193+ {
194+ SAMLBackend .KEY_DYNAMIC_REQUESTED_ATTRIBUTES : requested_attributes ,
195+ "sp_config" : sp_conf
196+ },
197+ "base_url" ,
198+ "saml_backend"
199+ )
200+
201+ with patch .object (
202+ backend .sp ,
203+ "create_authn_request" ,
204+ wraps = backend .sp .create_authn_request
205+ ) as mock :
206+ backend .authn_request (
207+ context ,
208+ idp_conf ["entityid" ],
209+ requested_attributes = ["name" , "surname" ]
210+ )
211+
212+ kwargs = mock .call_args [1 ]
213+ assert "requested_attributes" in kwargs
214+ assert kwargs ["requested_attributes" ] == [
215+ {"friendly_name" : "cn" , "required" : True },
216+ {"friendly_name" : "sn" , "required" : False }
217+ ]
218+
219+ def test_authn_request_requested_attributes_ignore_extra (
220+ self , context , idp_conf , sp_conf
221+ ):
222+ """
223+ Extra internal attributes should be ignored
224+ """
225+ requested_attributes = [
226+ {"friendly_name" : "cn" , "required" : True },
227+ {"friendly_name" : "sn" , "required" : False }
228+ ]
229+
230+ backend = SAMLBackend (
231+ None ,
232+ INTERNAL_ATTRIBUTES ,
233+ {
234+ SAMLBackend .KEY_DYNAMIC_REQUESTED_ATTRIBUTES : requested_attributes ,
235+ "sp_config" : sp_conf
236+ },
237+ "base_url" ,
238+ "saml_backend"
239+ )
240+
241+ with patch .object (
242+ backend .sp ,
243+ "create_authn_request" ,
244+ wraps = backend .sp .create_authn_request
245+ ) as mock :
246+ backend .authn_request (
247+ context ,
248+ idp_conf ["entityid" ],
249+ requested_attributes = ["name" , "surname" , "email" ]
250+ )
251+
252+ kwargs = mock .call_args [1 ]
253+ assert "requested_attributes" in kwargs
254+ assert kwargs ["requested_attributes" ] == [
255+ {"friendly_name" : "cn" , "required" : True },
256+ {"friendly_name" : "sn" , "required" : False }
257+ ]
258+
259+ def test_authn_request_requested_attributes_not_present (
260+ self , context , idp_conf , sp_conf
261+ ):
262+ """
263+ If some requested attributes are not in the requested don't add them to
264+ the request
265+ """
266+ requested_attributes = [
267+ {"friendly_name" : "cn" , "required" : True },
268+ {"friendly_name" : "sn" , "required" : False }
269+ ]
270+
271+ backend = SAMLBackend (
272+ None ,
273+ INTERNAL_ATTRIBUTES ,
274+ {
275+ SAMLBackend .KEY_DYNAMIC_REQUESTED_ATTRIBUTES : requested_attributes ,
276+ "sp_config" : sp_conf
277+ },
278+ "base_url" ,
279+ "saml_backend"
280+ )
281+
282+ with patch .object (
283+ backend .sp ,
284+ "create_authn_request" ,
285+ wraps = backend .sp .create_authn_request
286+ ) as mock :
287+ backend .authn_request (
288+ context ,
289+ idp_conf ["entityid" ],
290+ requested_attributes = ["name" ]
291+ )
292+
293+ kwargs = mock .call_args [1 ]
294+ assert "requested_attributes" in kwargs
295+ assert kwargs ["requested_attributes" ] == [
296+ {"friendly_name" : "cn" , "required" : True },
297+ ]
298+
299+ def test_authn_request_no_requested_attributes (
300+ self , context , idp_conf , sp_conf
301+ ):
302+ """
303+ If none attributes are requested don't add the extention
304+ """
305+ requested_attributes = [
306+ {"friendly_name" : "cn" , "required" : True },
307+ {"friendly_name" : "sn" , "required" : False }
308+ ]
309+
310+ backend = SAMLBackend (
311+ None ,
312+ INTERNAL_ATTRIBUTES ,
313+ {
314+ SAMLBackend .KEY_DYNAMIC_REQUESTED_ATTRIBUTES : requested_attributes ,
315+ "sp_config" : sp_conf
316+ },
317+ "base_url" ,
318+ "saml_backend"
319+ )
320+
321+ with patch .object (
322+ backend .sp ,
323+ "create_authn_request" ,
324+ wraps = backend .sp .create_authn_request
325+ ) as mock :
326+ backend .authn_request (
327+ context ,
328+ idp_conf ["entityid" ],
329+ requested_attributes = ["email" ]
330+ )
331+
332+ kwargs = mock .call_args [1 ]
333+ assert "requested_attributes" not in kwargs
334+
182335 def test_authn_response (self , context , idp_conf , sp_conf ):
183336 response_binding = BINDING_HTTP_REDIRECT
184337 fakesp = FakeSP (SPConfig ().load (sp_conf , metadata_construction = False ))
0 commit comments