Skip to content

Commit e263eaa

Browse files
committed
Partial rework of claims and get_metadata
1 parent aaa8446 commit e263eaa

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+705
-428
lines changed

src/idpyoidc/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
__author__ = "Roland Hedberg"
2-
__version__ = "4.4.0"
2+
__version__ = "5.0.0"
33

44
VERIFIED_CLAIM_PREFIX = "__verified"
55

src/idpyoidc/alg_info.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
from functools import cmp_to_key
2+
import logging
3+
4+
from cryptojwt.jwe import SUPPORTED
5+
from cryptojwt.jws.jws import SIGNER_ALGS
6+
7+
logger = logging.getLogger(__name__)
8+
9+
SIGNING_ALGORITHM_SORT_ORDER = ["RS", "ES", "PS", "HS", "Ed"]
10+
11+
12+
def cmp(a, b):
13+
return (a > b) - (a < b)
14+
15+
16+
def alg_cmp(a, b):
17+
if a == "none":
18+
return 1
19+
elif b == "none":
20+
return -1
21+
22+
_pos1 = SIGNING_ALGORITHM_SORT_ORDER.index(a[0:2])
23+
_pos2 = SIGNING_ALGORITHM_SORT_ORDER.index(b[0:2])
24+
if _pos1 == _pos2:
25+
return (a > b) - (a < b)
26+
elif _pos1 > _pos2:
27+
return 1
28+
else:
29+
return -1
30+
31+
32+
def get_signing_algs():
33+
# Assumes Cryptojwt
34+
_algs = [name for name in list(SIGNER_ALGS.keys()) if name != "none"]
35+
return sorted(_algs, key=cmp_to_key(alg_cmp))
36+
37+
38+
def get_encryption_algs():
39+
return SUPPORTED["alg"]
40+
41+
42+
def get_encryption_encs():
43+
return SUPPORTED["enc"]
44+
45+
46+
def array_or_singleton(claim_spec, values):
47+
if isinstance(claim_spec[0], list):
48+
if isinstance(values, list):
49+
return values
50+
else:
51+
return [values]
52+
else:
53+
if isinstance(values, list):
54+
return values[0]
55+
else: # singleton
56+
return values
57+
58+
59+
def is_subset(a, b):
60+
if isinstance(a, list):
61+
if isinstance(b, list):
62+
return set(b).issubset(set(a))
63+
elif isinstance(b, list):
64+
return a in b
65+
else:
66+
return a == b

src/idpyoidc/claims.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import logging
22
from typing import Callable
3+
from typing import List
34
from typing import Optional
45

56
from cryptojwt import KeyJar
@@ -8,11 +9,14 @@
89

910
from idpyoidc.client.util import get_uri
1011
from idpyoidc.impexp import ImpExp
12+
from idpyoidc.message import Message
13+
from idpyoidc.transform import preferred_to_registered
1114
from idpyoidc.util import add_path
1215
from idpyoidc.util import qualified_name
1316

1417
logger = logging.getLogger(__name__)
1518

19+
1620
def claims_dump(info, exclude_attributes):
1721
return {qualified_name(info.__class__): info.dump(exclude_attributes=exclude_attributes)}
1822

@@ -124,7 +128,7 @@ def _keyjar(self, keyjar=None, conf=None, entity_id=""):
124128

125129
return keyjar, _uri_path
126130

127-
def get_base_url(self, configuration: dict, entity_id: Optional[str]=""):
131+
def get_base_url(self, configuration: dict, entity_id: Optional[str] = ""):
128132
raise NotImplementedError()
129133

130134
def get_id(self, configuration: dict):
@@ -183,6 +187,10 @@ def load_conf(
183187
elif val:
184188
self.set_preference(key, val)
185189

190+
for attr,val in supports.items():
191+
if attr not in self.prefer and val is not None:
192+
self.set_preference(attr,val)
193+
186194
self.verify_rules(supports)
187195
return keyjar
188196

@@ -222,3 +230,53 @@ def get_claim(self, key, default=None):
222230
return default
223231
else:
224232
return _val
233+
234+
def get_endpoint_claims(self, endpoints):
235+
_info = {}
236+
for endp in endpoints:
237+
if endp.endpoint_name:
238+
_info[endp.endpoint_name] = endp.full_path
239+
for arg, claim in [("client_authn_method", "auth_methods"),
240+
("auth_signing_alg_values", "auth_signing_alg_values")]:
241+
_val = getattr(endp, arg, None)
242+
if _val:
243+
# trust_mark_status_endpoint_auth_methods_supported
244+
md_param = f"{endp.endpoint_name}_{claim}"
245+
_info[md_param] = _val
246+
return _info
247+
248+
def get_metadata(self,
249+
entity_type: Optional[str] = "",
250+
endpoints: Optional[list] = None,
251+
metadata_schema: Optional[Message] = None,
252+
extra_claims: Optional[List[str]] = None,
253+
supported: Optional[dict] = None,
254+
**kwargs):
255+
256+
if supported is None:
257+
supported = self.supports()
258+
259+
if not self.use:
260+
self.use = preferred_to_registered(self.prefer, supported=supported)
261+
262+
metadata = self.use
263+
# the claims that can appear in the metadata
264+
if metadata_schema:
265+
attr = list(metadata_schema.c_param.keys())
266+
else:
267+
attr = []
268+
269+
if extra_claims:
270+
attr.extend(extra_claims)
271+
272+
if attr:
273+
metadata = {k: v for k, v in metadata.items() if k in attr}
274+
275+
# collect endpoints
276+
if endpoints:
277+
metadata.update(self.get_endpoint_claims(endpoints))
278+
279+
if entity_type:
280+
return {entity_type: metadata}
281+
else:
282+
return metadata

src/idpyoidc/client/claims/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def get_jwks(self, keyjar):
5858
if (
5959
len(_own_keys) == 1
6060
and isinstance(_own_keys[0], SYMKey)
61-
and self.prefer["client_secret"]
61+
and self.prefer.get("client_secret", None)
6262
):
6363
pass
6464
else:

src/idpyoidc/client/claims/oauth2.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from typing import Optional
22

33
from idpyoidc.client import claims
4-
from idpyoidc.client.claims.transform import create_registration_request
4+
from idpyoidc.transform import create_registration_request
55

66
REGISTER2PREFERRED = {
77
"scope": "scopes_supported",
@@ -26,7 +26,9 @@ class Claims(claims.Claims):
2626
"grant_types_supported": ["authorization_code", "implicit", "refresh_token"],
2727
"token_endpoint_auth_methods_supported": ["none", "client_secret_post", "client_secret_basic"],
2828
# "token_auth_signing_algs_supported": metadata.get_signing_algs(),
29+
"client_id": None,
2930
"client_name": None,
31+
"client_secret": None,
3032
"client_uri": None,
3133
"logo_uri": None,
3234
"scope": None,

src/idpyoidc/client/claims/oauth2resource.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from idpyoidc.client import claims
44
from idpyoidc.message.oauth2 import OAuthProtectedResourceRequest
5-
from idpyoidc.client.claims.transform import array_or_singleton
5+
from idpyoidc.transform import array_or_singleton
66

77
class Claims(claims.Claims):
88
_supports = {

src/idpyoidc/client/claims/oidc.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
import os
33
from typing import Optional
44

5-
from idpyoidc import metadata
5+
from idpyoidc import alg_info
66
from idpyoidc.client import claims as client_claims
7-
from idpyoidc.client.claims.transform import create_registration_request
7+
from idpyoidc.transform import create_registration_request
88
from idpyoidc.message.oidc import RegistrationRequest
99
from idpyoidc.message.oidc import RegistrationResponse
1010

@@ -76,9 +76,9 @@ class Claims(client_claims.Claims):
7676
"encrypt_id_token_supported": None,
7777
# "grant_types_supported": ["authorization_code", "refresh_token"],
7878
"logo_uri": None,
79-
"id_token_signing_alg_values_supported": metadata.get_signing_algs(),
80-
"id_token_encryption_alg_values_supported": metadata.get_encryption_algs(),
81-
"id_token_encryption_enc_values_supported": metadata.get_encryption_encs(),
79+
"id_token_signing_alg_values_supported": alg_info.get_signing_algs(),
80+
"id_token_encryption_alg_values_supported": alg_info.get_encryption_algs(),
81+
"id_token_encryption_enc_values_supported": alg_info.get_encryption_encs(),
8282
"initiate_login_uri": None,
8383
"jwks": None,
8484
"jwks_uri": None,

src/idpyoidc/client/oauth2/access_token.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from idpyoidc.client.service import Service
88
from idpyoidc.message import oauth2
99
from idpyoidc.message.oauth2 import ResponseMessage
10-
from idpyoidc.metadata import get_signing_algs
10+
from idpyoidc.alg_info import get_signing_algs
1111
from idpyoidc.time_util import time_sans_frac
1212

1313
LOGGER = logging.getLogger(__name__)

src/idpyoidc/client/oauth2/add_on/dpop.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from idpyoidc.message import SINGLE_REQUIRED_INT
1717
from idpyoidc.message import SINGLE_REQUIRED_JSON
1818
from idpyoidc.message import SINGLE_REQUIRED_STRING
19-
from idpyoidc.metadata import get_signing_algs
19+
from idpyoidc.alg_info import get_signing_algs
2020
from idpyoidc.time_util import utc_time_sans_frac
2121

2222
logger = logging.getLogger(__name__)

src/idpyoidc/client/oauth2/add_on/jar.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import logging
22
from typing import Optional
33

4-
from idpyoidc import metadata
4+
from idpyoidc import alg_info
55
from idpyoidc.client.request_object import construct_request_parameter
66
from idpyoidc.client.request_object import construct_request_uri
77

@@ -117,8 +117,8 @@ def add_support(
117117
args["request_dir"] = request_dir
118118

119119
if request_object_encryption_enc and request_object_encryption_alg:
120-
if request_object_encryption_enc in metadata.get_encryption_encs():
121-
if request_object_encryption_alg in metadata.get_encryption_algs():
120+
if request_object_encryption_enc in alg_info.get_encryption_encs():
121+
if request_object_encryption_alg in alg_info.get_encryption_algs():
122122
args["request_object_encryption_enc"] = request_object_encryption_enc
123123
args["request_object_encryption_alg"] = request_object_encryption_alg
124124
else:

0 commit comments

Comments
 (0)