Skip to content

Commit 506b1d0

Browse files
authored
Merge pull request #94 from IdentityPython/read_only_list
Added a class that implements read only of a file.
2 parents f20b465 + 11cbbb3 commit 506b1d0

File tree

9 files changed

+323
-145
lines changed

9 files changed

+323
-145
lines changed

example/flask_op/static/jwks.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"keys": [{"kty": "RSA", "use": "sig", "kid": "bXNmZXROQ3N2dDI2SWY5VlNWTG5yOXZqYlpLenVsalhwUWR5RW9BMHNCaw", "n": "uGVI-b6qr-OTc2knp7bpmDtiCQoWFXZ8mUV-SX0rCMtcc_IRmc_J7AfNEfnYk3dv0cKQK_Dgv3vicoeuf4KQ9ZZY-xI3bnRl9_HnhRpz_cJScDirkNKlsv8aQuYBO_gIiHp8B32YC0nx3BUQV5I6QGEiyG-lZT9PmXsUO1uKPPhny_vtQ6cUpvtuLySBu2ZYpaTDQqCv5Y6EKC49NYWhBB4B6f6TNKCoQTaxA8ZoM3lh7kFbu5DPEXKFAtuNiOtUNP7Ei9KfBtyBYSaZQBY8VkwAm1yKCA2sfv1mBwx0dT53MPJlNkoltf89mv1NM2OJPQAgGE6ygwGS2fyBLAn_bQ", "e": "AQAB"}, {"kty": "EC", "use": "sig", "kid": "U0pLNmFBRE4waDYyZG9ZdjNPb2pTZXAwZzdrbmpZdG0ya3lpaFJwZU9ncw", "crv": "P-256", "x": "DYUyBfiD53SEtUuKLjFCFpIkqyhbmBppAMjOat9qiY0", "y": "-SUSvVeOv7EA84qHLLEkDP24iZree-fomICuA4baeeA"}]}
1+
{"keys": [{"kty": "RSA", "use": "sig", "kid": "bXNmZXROQ3N2dDI2SWY5VlNWTG5yOXZqYlpLenVsalhwUWR5RW9BMHNCaw", "e": "AQAB", "n": "uGVI-b6qr-OTc2knp7bpmDtiCQoWFXZ8mUV-SX0rCMtcc_IRmc_J7AfNEfnYk3dv0cKQK_Dgv3vicoeuf4KQ9ZZY-xI3bnRl9_HnhRpz_cJScDirkNKlsv8aQuYBO_gIiHp8B32YC0nx3BUQV5I6QGEiyG-lZT9PmXsUO1uKPPhny_vtQ6cUpvtuLySBu2ZYpaTDQqCv5Y6EKC49NYWhBB4B6f6TNKCoQTaxA8ZoM3lh7kFbu5DPEXKFAtuNiOtUNP7Ei9KfBtyBYSaZQBY8VkwAm1yKCA2sfv1mBwx0dT53MPJlNkoltf89mv1NM2OJPQAgGE6ygwGS2fyBLAn_bQ"}, {"kty": "EC", "use": "sig", "kid": "U0pLNmFBRE4waDYyZG9ZdjNPb2pTZXAwZzdrbmpZdG0ya3lpaFJwZU9ncw", "crv": "P-256", "x": "DYUyBfiD53SEtUuKLjFCFpIkqyhbmBppAMjOat9qiY0", "y": "-SUSvVeOv7EA84qHLLEkDP24iZree-fomICuA4baeeA"}]}

src/idpyoidc/client/claims/__init__.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@ class Claims(claims.Claims):
1616
def get_base_url(self, configuration: dict, entity_id: Optional[str] = ""):
1717
_base = configuration.get("base_url")
1818
if not _base:
19-
if entity_id:
20-
_base = entity_id
21-
else:
22-
_base = configuration.get("client_id")
19+
_base = configuration.get("client_id", configuration.get("entity_id"))
2320

2421
return _base
2522

src/idpyoidc/client/client_auth.py

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -490,27 +490,29 @@ def _get_signing_key(self, algorithm, keyjar, key_types, kid=None):
490490
return signing_key
491491

492492
def _get_audience_and_algorithm(self, context, keyjar, **kwargs):
493-
algorithm = None
494-
495-
# audience for the signed JWT depends on which endpoint
496-
# we're talking to.
497-
if "authn_endpoint" in kwargs and kwargs["authn_endpoint"] in ["token_endpoint"]:
498-
algorithm = context.get_usage("token_endpoint_auth_signing_alg")
499-
if algorithm is None:
500-
_pi = context.provider_info
501-
try:
502-
algs = _pi["token_endpoint_auth_signing_alg_values_supported"]
503-
except KeyError:
504-
algorithm = "RS256" # default
505-
else:
506-
for alg in algs: # pick the first one I support and have keys for
507-
if alg in SIGNER_ALGS and self.get_signing_key_from_keyjar(alg, keyjar):
508-
algorithm = alg
509-
break
510-
511-
audience = context.provider_info.get("token_endpoint")
512-
else:
513-
audience = context.provider_info["issuer"]
493+
algorithm = kwargs.get("algorithm", None)
494+
audience = kwargs.get("audience", None)
495+
496+
if not audience:
497+
# audience for the signed JWT depends on which endpoint
498+
# we're talking to.
499+
if "authn_endpoint" in kwargs and kwargs["authn_endpoint"] in ["token_endpoint"]:
500+
algorithm = context.get_usage("token_endpoint_auth_signing_alg")
501+
if algorithm is None:
502+
_pi = context.provider_info
503+
try:
504+
algs = _pi["token_endpoint_auth_signing_alg_values_supported"]
505+
except KeyError:
506+
algorithm = "RS256" # default
507+
else:
508+
for alg in algs: # pick the first one I support and have keys for
509+
if alg in SIGNER_ALGS and self.get_signing_key_from_keyjar(alg, keyjar):
510+
algorithm = alg
511+
break
512+
513+
audience = context.provider_info.get("token_endpoint")
514+
else:
515+
audience = context.provider_info["issuer"]
514516

515517
if not algorithm:
516518
algorithm = self.choose_algorithm(**kwargs)
@@ -519,6 +521,9 @@ def _get_audience_and_algorithm(self, context, keyjar, **kwargs):
519521
def _construct_client_assertion(self, service, **kwargs):
520522
_context = service.upstream_get("context")
521523
_entity = service.upstream_get("entity")
524+
if _entity is None:
525+
_entity = service.upstream_get("unit")
526+
522527
_keyjar = service.upstream_get("attribute", "keyjar")
523528
audience, algorithm = self._get_audience_and_algorithm(_context, _keyjar, **kwargs)
524529

@@ -527,7 +532,11 @@ def _construct_client_assertion(self, service, **kwargs):
527532
algorithm, _keyjar, _context.kid["sig"], kid=kwargs["kid"]
528533
)
529534
else:
530-
signing_key = self._get_signing_key(algorithm, _keyjar, _context.kid["sig"])
535+
_key_type = _context.kid.get("sig", None)
536+
if _key_type:
537+
signing_key = self._get_signing_key(algorithm, _keyjar, _key_type)
538+
else:
539+
signing_key = self.get_signing_key_from_keyjar(algorithm, _keyjar)
531540

532541
if not signing_key:
533542
raise UnsupportedAlgorithm(algorithm)
@@ -570,7 +579,8 @@ def modify_request(self, request, service, **kwargs):
570579
pass
571580

572581
# If client_id is not required to be present, remove it.
573-
if not request.c_param["client_id"][VREQUIRED]:
582+
_cid_spec = request.c_param.get("client_id", None)
583+
if _cid_spec and not _cid_spec[VREQUIRED]:
574584
try:
575585
del request["client_id"]
576586
except KeyError:

src/idpyoidc/client/service.py

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,28 @@
88
from typing import Union
99
from urllib.parse import urlparse
1010

11-
from cryptojwt.exception import IssuerNotFound
1211
from cryptojwt.jwe.jwe import factory as jwe_factory
1312
from cryptojwt.jws.jws import factory as jws_factory
1413
from cryptojwt.jwt import JWT
15-
from idpyoidc.exception import MissingSigningKey
1614

1715
from idpyoidc.client.exception import Unsupported
16+
from idpyoidc.exception import MissingSigningKey
1817
from idpyoidc.impexp import ImpExp
1918
from idpyoidc.item import DLDict
2019
from idpyoidc.message import Message
21-
from idpyoidc.message.oauth2 import ResponseMessage
2220
from idpyoidc.message.oauth2 import is_error_message
21+
from idpyoidc.message.oauth2 import ResponseMessage
2322
from idpyoidc.util import importer
24-
25-
from ..constant import JOSE_ENCODED
26-
from ..constant import JSON_ENCODED
27-
from ..constant import URL_ENCODED
2823
from .client_auth import client_auth_setup
2924
from .client_auth import method_to_item
3025
from .client_auth import single_authn_setup
3126
from .configure import Configuration
3227
from .exception import ResponseError
3328
from .util import get_http_body
3429
from .util import get_http_url
30+
from ..constant import JOSE_ENCODED
31+
from ..constant import JSON_ENCODED
32+
from ..constant import URL_ENCODED
3533

3634
__author__ = "Roland Hedberg"
3735

@@ -79,7 +77,7 @@ class Service(ImpExp):
7977
_callback_path = {}
8078

8179
def __init__(
82-
self, upstream_get: Callable, conf: Optional[Union[dict, Configuration]] = None, **kwargs
80+
self, upstream_get: Callable, conf: Optional[Union[dict, Configuration]] = None, **kwargs
8381
):
8482
ImpExp.__init__(self)
8583

@@ -333,7 +331,7 @@ def get_endpoint(self):
333331
return self.upstream_get("context").provider_info[self.endpoint_name]
334332

335333
def get_authn_header(
336-
self, request: Union[dict, Message], authn_method: Optional[str] = "", **kwargs
334+
self, request: Union[dict, Message], authn_method: Optional[str] = "", **kwargs
337335
) -> dict:
338336
"""
339337
Construct an authorization specification to be sent in the
@@ -364,12 +362,15 @@ def get_authn_method(self) -> str:
364362
"""
365363
return self.default_authn_method
366364

365+
def get_headers_args(self):
366+
return {}
367+
367368
def get_headers(
368-
self,
369-
request: Union[dict, Message],
370-
http_method: str,
371-
authn_method: Optional[str] = "",
372-
**kwargs,
369+
self,
370+
request: Union[dict, Message],
371+
http_method: str,
372+
authn_method: Optional[str] = "",
373+
**kwargs,
373374
) -> dict:
374375
"""
375376
@@ -404,7 +405,7 @@ def get_headers(
404405
return _headers
405406

406407
def get_request_parameters(
407-
self, request_args=None, method="", request_body_type="", authn_method="", **kwargs
408+
self, request_args=None, method="", request_body_type="", authn_method="", **kwargs
408409
) -> dict:
409410
"""
410411
Builds the request message and constructs the HTTP headers.
@@ -445,6 +446,7 @@ def get_request_parameters(
445446

446447
# Client authentication by usage of the Authorization HTTP header
447448
# or by modifying the request object
449+
_args.update(self.get_headers_args())
448450
_headers = self.get_headers(request, http_method=method, authn_method=authn_method, **_args)
449451

450452
# Find out where to send this request
@@ -506,7 +508,7 @@ def post_parse_response(self, response, **kwargs):
506508
return response
507509

508510
def gather_verify_arguments(
509-
self, response: Optional[Union[dict, Message]] = None, behaviour_args: Optional[dict] = None
511+
self, response: Optional[Union[dict, Message]] = None, behaviour_args: Optional[dict] = None
510512
):
511513
"""
512514
Need to add some information before running verify()
@@ -542,7 +544,7 @@ def _do_jwt(self, info):
542544
def _do_response(self, info, sformat, **kwargs):
543545
_context = self.upstream_get("context")
544546

545-
if isinstance(info, list): # Don't have support for sformat=list
547+
if isinstance(info, list): # Don't have support for sformat=list
546548
return info
547549

548550
try:
@@ -566,13 +568,13 @@ def _do_response(self, info, sformat, **kwargs):
566568
return resp
567569

568570
def parse_response(
569-
self,
570-
info,
571-
sformat: Optional[str] = "",
572-
state: Optional[str] = "",
573-
behaviour_args: Optional[dict] = None,
574-
**kwargs,
575-
) :
571+
self,
572+
info,
573+
sformat: Optional[str] = "",
574+
state: Optional[str] = "",
575+
behaviour_args: Optional[dict] = None,
576+
**kwargs,
577+
):
576578
"""
577579
This the start of a pipeline that will:
578580
@@ -707,12 +709,12 @@ def get_uri(base_url, path, hex):
707709
return f"{base_url}/{path}/{hex}"
708710

709711
def construct_uris(
710-
self,
711-
base_url: str,
712-
hex: bytes,
713-
context: OidcContext,
714-
targets: Optional[List[str]] = None,
715-
response_types: Optional[list] = None,
712+
self,
713+
base_url: str,
714+
hex: bytes,
715+
context: OidcContext,
716+
targets: Optional[List[str]] = None,
717+
response_types: Optional[list] = None,
716718
):
717719
if not targets:
718720
targets = self._callback_path.keys()

0 commit comments

Comments
 (0)