2
2
import logging
3
3
4
4
from cryptojwt .exception import Expired
5
+ from cryptojwt .jws .jws import factory
5
6
from cryptojwt .jwt import utc_time_sans_frac
6
7
from idpyoidc import message
7
8
from idpyoidc .exception import MissingRequiredAttribute
@@ -93,29 +94,31 @@ def naming_constraints_deser(val, sformat="json"):
93
94
94
95
SINGLE_OPTIONAL_NAMING_CONSTRAINTS = (Message , False , msg_ser , naming_constraints_deser , False )
95
96
97
+ class InformationalMetadataExtensions (Message ):
98
+ c_param = {
99
+ "organization_name" : SINGLE_OPTIONAL_STRING ,
100
+ "contacts" : OPTIONAL_LIST_OF_STRINGS ,
101
+ "logo_url" : SINGLE_OPTIONAL_STRING ,
102
+ "policy_url" : SINGLE_OPTIONAL_STRING ,
103
+ "homepage_uri" : SINGLE_OPTIONAL_STRING ,
104
+ }
96
105
97
- class FederationEntity (Message ):
106
+ class FederationEntity (InformationalMetadataExtensions ):
98
107
"""Class representing Federation Entity metadata."""
99
- c_param = {
100
- "federation_fetch_endpoint" : SINGLE_REQUIRED_STRING ,
108
+ c_param = InformationalMetadataExtensions .c_param .copy ()
109
+ c_param .update ({
110
+ "federation_fetch_endpoint" : SINGLE_OPTIONAL_STRING ,
101
111
"federation_list_endpoint" : SINGLE_OPTIONAL_STRING ,
102
- # "federation_registration_endpoint": SINGLE_OPTIONAL_STRING, part of OP metadata
103
112
"federation_resolve_endpoint" : SINGLE_OPTIONAL_STRING ,
104
113
"federation_trust_mark_status_endpoint" : SINGLE_OPTIONAL_STRING ,
105
- "federation_trust_mark_list_endpoint" :SINGLE_OPTIONAL_STRING ,
114
+ "federation_trust_mark_list_endpoint" : SINGLE_OPTIONAL_STRING ,
106
115
"federation_trust_mark_endpoint" : SINGLE_OPTIONAL_STRING ,
107
- "federation_historical_keys_endpoint" :SINGLE_OPTIONAL_STRING ,
116
+ "federation_historical_keys_endpoint" : SINGLE_OPTIONAL_STRING ,
108
117
"endpoint_auth_signing_alg_values_supported" : SINGLE_OPTIONAL_JSON ,
109
- "name" : SINGLE_OPTIONAL_STRING ,
110
- "contacts" : OPTIONAL_LIST_OF_STRINGS ,
111
- "policy_url" : SINGLE_OPTIONAL_STRING ,
112
- "homepage_uri" : SINGLE_OPTIONAL_STRING ,
113
- # "federation_trust_marks": SINGLE_OPTIONAL_JSON,
114
- "organization_name" : SINGLE_OPTIONAL_STRING ,
115
118
# If it's a Trust Anchor
116
- "trust_mark_owners" : SINGLE_OPTIONAL_DICT ,
117
- "trust_mark_issuers" : SINGLE_OPTIONAL_DICT ,
118
- }
119
+ # "trust_mark_owners": SINGLE_OPTIONAL_DICT,
120
+ # "trust_mark_issuers": SINGLE_OPTIONAL_DICT,
121
+ })
119
122
120
123
121
124
def federation_entity_deser (val , sformat = "json" ):
@@ -255,6 +258,7 @@ class OPMetadata(ProviderConfigurationResponse):
255
258
"signed_jwks_uri" : SINGLE_OPTIONAL_STRING
256
259
})
257
260
261
+
258
262
class FedASConfigurationResponse (ASConfigurationResponse ):
259
263
c_param = ASConfigurationResponse .c_param .copy ()
260
264
c_param .update ({
@@ -398,6 +402,52 @@ def constrains_deser(val, sformat="json"):
398
402
SINGLE_OPTIONAL_CONSTRAINS = (Message , False , msg_ser , constrains_deser , False )
399
403
400
404
405
+ class TrustMarks (Message ):
406
+ c_param = {}
407
+
408
+ def verify (self , ** kwargs ):
409
+ for _id , spec in self .items ():
410
+ _trust_mark = spec .get ("trust_mark" )
411
+ if _trust_mark :
412
+ _trust_mark_id = spec .get ("trust_mark_id" )
413
+ if _trust_mark_id :
414
+ # Have to peek into the trust mark
415
+ _jws = factory (_trust_mark )
416
+ if not _jws :
417
+ raise ValueError (f"Not a proper signed JWT: { _trust_mark } " )
418
+ _tm_id = _jws .jwt .payload ().get ("trust_mark_id" )
419
+ if _tm_id != _trust_mark_id :
420
+ raise ValueError ("The Trust Mark identifier MUST have the same value as the trust_mark_id "
421
+ "claim" )
422
+ else :
423
+ raise MissingRequiredAttribute ("trust_mark_id" )
424
+ else :
425
+ raise MissingRequiredAttribute ("trust_mark" )
426
+
427
+
428
+ class TrustMarkIssuers (Message ):
429
+ c_param = {}
430
+
431
+ def verify (self , ** kwargs ):
432
+ for owner_id , spec in self .items ():
433
+ if not isinstance (spec , list ):
434
+ raise ValueError ("issuers MUST be a list" )
435
+
436
+
437
+ class TrustMarkOwners (Message ):
438
+
439
+ def verify (self , ** kwargs ):
440
+ # Dictionary of Trust Mark Owner information
441
+ for owner_id , spec in self .items ():
442
+ if "sub" in spec and "jwks" in spec : # If there are other claims ignore them
443
+ continue
444
+ else :
445
+ if "sub" not in spec :
446
+ raise MissingRequiredAttribute ("sub" )
447
+ elif "jwks" not in spec :
448
+ raise MissingRequiredAttribute ("jwks" )
449
+
450
+
401
451
class EntityStatement (JsonWebToken ):
402
452
"""The Entity Statement"""
403
453
c_param = JsonWebToken .c_param .copy ()
@@ -412,10 +462,15 @@ class EntityStatement(JsonWebToken):
412
462
'authority_hints' : OPTIONAL_LIST_OF_STRINGS ,
413
463
'metadata' : SINGLE_OPTIONAL_METADATA ,
414
464
'metadata_policy' : SINGLE_OPTIONAL_METADATA_POLICY ,
465
+ 'metadata_policy_crit' : OPTIONAL_LIST_OF_STRINGS ,
415
466
'constraints' : SINGLE_OPTIONAL_CONSTRAINS ,
416
467
"crit" : OPTIONAL_LIST_OF_STRINGS ,
417
468
"policy_language_crit" : OPTIONAL_LIST_OF_STRINGS ,
418
- 'trust_marks' : OPTIONAL_LIST_OF_STRINGS ,
469
+ "source_endpoint" : SINGLE_OPTIONAL_STRING ,
470
+ 'trust_marks' : SINGLE_OPTIONAL_JSON ,
471
+ 'trust_mark_owners' : SINGLE_OPTIONAL_JSON ,
472
+ 'trust_mark_issuers' : SINGLE_OPTIONAL_JSON ,
473
+ #
419
474
'trust_anchor_id' : SINGLE_OPTIONAL_STRING
420
475
})
421
476
@@ -444,14 +499,24 @@ def verify(self, **kwargs):
444
499
if _crit :
445
500
_metadata_policy .verify (policy_language_crit = _crit , ** kwargs )
446
501
502
+ _trust_mark_issuers = self .get ("trust_mark_issuers" )
503
+ if _trust_mark_issuers :
504
+ _tmi = TrustMarkIssuers (** _trust_mark_issuers )
505
+ _tmi .verify ()
506
+
507
+ _trust_mark_owners = self .get ("trust_mark_owners" )
508
+ if _trust_mark_owners :
509
+ _tmi = TrustMarkOwners (** _trust_mark_owners )
510
+ _tmi .verify ()
511
+
447
512
448
513
class TrustMark (JsonWebToken ):
449
514
c_param = JsonWebToken .c_param .copy ()
450
515
c_param .update ({
451
516
"sub" : SINGLE_REQUIRED_STRING ,
452
517
'iss' : SINGLE_REQUIRED_STRING ,
453
518
'iat' : SINGLE_REQUIRED_INT ,
454
- "id " : SINGLE_REQUIRED_STRING ,
519
+ "trust_mark_id " : SINGLE_REQUIRED_STRING ,
455
520
"logo_uri" : SINGLE_OPTIONAL_STRING ,
456
521
"exp" : SINGLE_OPTIONAL_INT ,
457
522
"ref" : SINGLE_OPTIONAL_STRING ,
@@ -588,19 +653,22 @@ class HistoricalKeysResponse(Message):
588
653
'jwks' : SINGLE_REQUIRED_DICT
589
654
}
590
655
656
+
591
657
class TrustMarkRequest (Message ):
592
658
c_param = {
593
659
"trust_mark_id" : SINGLE_REQUIRED_STRING ,
594
660
"sub" : SINGLE_REQUIRED_STRING
595
661
}
596
662
663
+
597
664
class WhoRequest (Message ):
598
665
c_param = {
599
666
"entity_type" : SINGLE_OPTIONAL_STRING ,
600
667
"credential_type" : SINGLE_OPTIONAL_STRING ,
601
668
"trust_mark_id" : SINGLE_OPTIONAL_STRING
602
669
}
603
670
671
+
604
672
class WhoResponse (Message ):
605
673
c_param = {
606
674
"entities_to_use" : REQUIRED_LIST_OF_STRINGS
0 commit comments