22import os
33
44import pytest
5+ from oidcmsg .message import Message
6+ from oidcmsg .oidc import OpenIDRequest
7+ from oidcmsg .oidc import OpenIDSchema
58
69from oidcendpoint .authn_event import create_authn_event
710from oidcendpoint .endpoint_context import EndpointContext
1619from oidcendpoint .userinfo import claims_match
1720from oidcendpoint .userinfo import collect_user_info
1821from oidcendpoint .userinfo import update_claims
19- from oidcmsg .message import Message
20- from oidcmsg .oidc import OpenIDRequest
21- from oidcmsg .oidc import OpenIDSchema
2222
2323CLAIMS = {
2424 "userinfo" : {
3535 },
3636}
3737
38+ CLAIMS_2 = {
39+ "userinfo" : {
40+ "eduperson_scoped_affiliation" : {"essential" : True },
41+ "nickname" : None ,
42+ "email" : {"essential" : True },
43+ "email_verified" : {"essential" : True },
44+ }
45+ }
46+
3847OIDR = OpenIDRequest (
3948 response_type = "code" ,
4049 client_id = "client1" ,
@@ -138,16 +147,25 @@ def test_custom_scopes():
138147 "eduperson_scoped_affiliation" ,
139148 }
140149
150+ PROVIDER_INFO = {
151+ "claims_supported" : ["auth_time" , "acr" , "given_name" ,
152+ "nickname" ,
153+ "email" ,
154+ "email_verified" ,
155+ "picture" ,
156+ "http://example.info/claims/groups" ,
157+ ]
158+ }
141159
142160def test_update_claims_authn_req_id_token ():
143161 _session_info = {"authn_req" : OIDR }
144- claims = update_claims (_session_info , "id_token" )
162+ claims = update_claims (_session_info , "id_token" , PROVIDER_INFO )
145163 assert set (claims .keys ()) == {"auth_time" , "acr" }
146164
147165
148166def test_update_claims_authn_req_userinfo ():
149167 _session_info = {"authn_req" : OIDR }
150- claims = update_claims (_session_info , "userinfo" )
168+ claims = update_claims (_session_info , "userinfo" , PROVIDER_INFO )
151169 assert set (claims .keys ()) == {
152170 "given_name" ,
153171 "nickname" ,
@@ -160,13 +178,13 @@ def test_update_claims_authn_req_userinfo():
160178
161179def test_update_claims_authzreq_id_token ():
162180 _session_info = {"authn_req" : OIDR }
163- claims = update_claims (_session_info , "id_token" )
181+ claims = update_claims (_session_info , "id_token" , PROVIDER_INFO )
164182 assert set (claims .keys ()) == {"auth_time" , "acr" }
165183
166184
167185def test_update_claims_authzreq_userinfo ():
168186 _session_info = {"authn_req" : OIDR }
169- claims = update_claims (_session_info , "userinfo" )
187+ claims = update_claims (_session_info , "userinfo" , PROVIDER_INFO )
170188 assert set (claims .keys ()) == {
171189 "given_name" ,
172190 "nickname" ,
@@ -262,7 +280,10 @@ def create_endpoint_context(self):
262280 )
263281
264282 def test_collect_user_info (self ):
265- _session_info = {"authn_req" : OIDR }
283+ _req = OIDR .copy ()
284+ _req ["claims" ] = CLAIMS_2
285+
286+ _session_info = {"authn_req" : _req }
266287 session = _session_info .copy ()
267288 session ["sub" ] = "doe"
268289 session ["uid" ] = "diana"
@@ -271,7 +292,6 @@ def test_collect_user_info(self):
271292 res = collect_user_info (self .endpoint_context , session )
272293
273294 assert res == {
274- "given_name" : "Diana" ,
275295 "nickname" : "Dina" ,
276296 "sub" : "doe" ,
277297 "email" : "diana@example.org" ,
@@ -324,3 +344,133 @@ def test_collect_user_info_scope_not_supported(self):
324344 }
325345
326346
347+ class TestCollectUserInfoCustomScopes :
348+ @pytest .fixture (autouse = True )
349+ def create_endpoint_context (self ):
350+ self .endpoint_context = EndpointContext (
351+ {
352+ "userinfo" : {"class" : UserInfo , "kwargs" : {"db" : USERINFO_DB }},
353+ "password" : "we didn't start the fire" ,
354+ "issuer" : "https://example.com/op" ,
355+ "token_expires_in" : 900 ,
356+ "grant_expires_in" : 600 ,
357+ "refresh_token_expires_in" : 86400 ,
358+ "endpoint" : {
359+ "provider_config" : {
360+ "path" : "{}/.well-known/openid-configuration" ,
361+ "class" : ProviderConfiguration ,
362+ "kwargs" : {},
363+ },
364+ "registration" : {
365+ "path" : "{}/registration" ,
366+ "class" : Registration ,
367+ "kwargs" : {},
368+ },
369+ "authorization" : {
370+ "path" : "{}/authorization" ,
371+ "class" : Authorization ,
372+ "kwargs" : {
373+ "response_types_supported" : [
374+ " " .join (x ) for x in RESPONSE_TYPES_SUPPORTED
375+ ],
376+ "response_modes_supported" : ["query" , "fragment" , "form_post" ],
377+ "claims_parameter_supported" : True ,
378+ "request_parameter_supported" : True ,
379+ "request_uri_parameter_supported" : True ,
380+ },
381+ },
382+ },
383+ "add_on" : {
384+ "custom_scopes" : {
385+ "function" : "oidcendpoint.oidc.add_on.custom_scopes.add_custom_scopes" ,
386+ "kwargs" : {
387+ "research_and_scholarship" : [
388+ "name" ,
389+ "given_name" ,
390+ "family_name" ,
391+ "email" ,
392+ "email_verified" ,
393+ "sub" ,
394+ "iss" ,
395+ "eduperson_scoped_affiliation" ,
396+ ]
397+ },
398+ }
399+ },
400+ "jwks" : {
401+ "public_path" : "jwks.json" ,
402+ "key_defs" : KEYDEFS ,
403+ "uri_path" : "static/jwks.json" ,
404+ },
405+ "authentication" : {
406+ "anon" : {
407+ "acr" : INTERNETPROTOCOLPASSWORD ,
408+ "class" : "oidcendpoint.user_authn.user.NoAuthn" ,
409+ "kwargs" : {"user" : "diana" },
410+ }
411+ },
412+ "template_dir" : "template" ,
413+ }
414+ )
415+
416+ def test_collect_user_info (self ):
417+ _session_info = {"authn_req" : OIDR }
418+ session = _session_info .copy ()
419+ session ["sub" ] = "doe"
420+ session ["uid" ] = "diana"
421+ session ["authn_event" ] = create_authn_event ("diana" , "salt" )
422+
423+ res = collect_user_info (self .endpoint_context , session )
424+
425+ assert res == {
426+ 'email' : 'diana@example.org' ,
427+ 'email_verified' : False ,
428+ 'nickname' : 'Dina' ,
429+ 'given_name' : 'Diana' ,
430+ 'sub' : 'doe'
431+ }
432+
433+ def test_collect_user_info_2 (self ):
434+ _req = OIDR .copy ()
435+ _req ["scope" ] = "openid email"
436+ del _req ["claims" ]
437+
438+ _session_info = {"authn_req" : _req }
439+ session = _session_info .copy ()
440+ session ["sub" ] = "doe"
441+ session ["uid" ] = "diana"
442+ session ["authn_event" ] = create_authn_event ("diana" , "salt" )
443+
444+ self .endpoint_context .provider_info ["claims_supported" ].remove ("email" )
445+ self .endpoint_context .provider_info ["claims_supported" ].remove ("email_verified" )
446+
447+ res = collect_user_info (self .endpoint_context , session )
448+
449+ assert res == {
450+ "sub" : "doe" ,
451+ "email" : "diana@example.org" ,
452+ "email_verified" : False ,
453+ }
454+
455+ def test_collect_user_info_scope_not_supported (self ):
456+ _req = OIDR .copy ()
457+ _req ["scope" ] = "openid email address"
458+ del _req ["claims" ]
459+
460+ _session_info = {"authn_req" : _req }
461+ session = _session_info .copy ()
462+ session ["sub" ] = "doe"
463+ session ["uid" ] = "diana"
464+ session ["authn_event" ] = create_authn_event ("diana" , "salt" )
465+
466+ # Scope address not supported
467+ self .endpoint_context .provider_info ["scopes_supported" ] = [
468+ "openid" , "email" , "offline_access"
469+ ]
470+ res = collect_user_info (self .endpoint_context , session )
471+
472+ assert res == {
473+ "sub" : "doe" ,
474+ "email" : "diana@example.org" ,
475+ "email_verified" : False ,
476+ }
0 commit comments