diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 8a4695bc..eef7cec2 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -21,6 +21,7 @@ jobs: - '3.7' - '3.8' - '3.9' + - '3.10' steps: - uses: actions/checkout@v2 diff --git a/README.md b/README.md index 8a1adfee..c4630c05 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@ Implementation of everything OIDC and OAuth2. -idpyoidc is the 2nd layer in the -JwtConnect stack (cryptojwt, idpyoidc) +idpyoidc is the 2nd layer in the JwtConnect stack (cryptojwt, idpyoidc) Please read the [Official Documentation](https://idpyoidc.readthedocs.io/) for getting usage examples and further informations. diff --git a/pyproject.toml b/pyproject.toml index 66152122..c10901b6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta" [metadata] name = "idpyoidc" -version = "1.0.0" +version = "1.0.1" author = "Roland Hedberg" author_email = "roland@catalogix.se" description = "Everything OAuth2 and OIDC" diff --git a/setup.py b/setup.py index 217b6512..2719cb70 100644 --- a/setup.py +++ b/setup.py @@ -50,7 +50,7 @@ def run_tests(self): setup( name="idpyoidc", version=version, - description="Python implementation of OAuth2 and OpenID Connect messages", + description="Python implementation of everything OAuth2 and OpenID Connect", long_description=README, long_description_content_type='text/markdown', author="Roland Hedberg", diff --git a/src/idpyoidc/__init__.py b/src/idpyoidc/__init__.py index 565560c6..8a51d096 100644 --- a/src/idpyoidc/__init__.py +++ b/src/idpyoidc/__init__.py @@ -1,5 +1,5 @@ __author__ = "Roland Hedberg" -__version__ = "1.0.0" +__version__ = "1.0.1" import os from typing import Dict diff --git a/src/idpyoidc/configure.py b/src/idpyoidc/configure.py index 222146d6..bf80e160 100644 --- a/src/idpyoidc/configure.py +++ b/src/idpyoidc/configure.py @@ -3,6 +3,7 @@ from typing import Dict from typing import List from typing import Optional +from typing import Union from idpyoidc.logging import configure_logging from idpyoidc.util import load_config_file @@ -38,6 +39,9 @@ def add_path_to_directory_name(directory_name, base_path): def add_base_path(conf: dict, base_path: str, attributes: List[str], attribute_type: str = "file"): for key, val in conf.items(): + if not val: + continue + if key in attributes: if attribute_type == "file": conf[key] = add_path_to_filename(val, base_path) @@ -168,7 +172,7 @@ def complete_paths(self, conf: Dict, keys: List[str], default_config: Dict, base def format(self, conf, base_path: str, domain: str, port: int, file_attributes: Optional[List[str]] = None, - dir_attributes: Optional[List[str]] = None) -> None: + dir_attributes: Optional[List[str]] = None) -> Union[Dict, str]: """ Formats parts of the configuration. That includes replacing the strings {domain} and {port} with the used domain and port and making references to files and directories absolute @@ -183,11 +187,17 @@ def format(self, conf, base_path: str, domain: str, port: int, """ if isinstance(conf, dict): if file_attributes: - add_base_path(conf, base_path, file_attributes, attribute_type="file") + conf = add_base_path(conf, base_path, file_attributes, attribute_type="file") if dir_attributes: - add_base_path(conf, base_path, dir_attributes, attribute_type="dir") + conf = add_base_path(conf, base_path, dir_attributes, attribute_type="dir") if isinstance(conf, dict): - set_domain_and_port(conf, domain=domain, port=port) + conf = set_domain_and_port(conf, domain=domain, port=port) + elif isinstance(conf, list): + conf = [_conv(v, domain=domain, port=port) for v in conf] + elif isinstance(conf, str): + conf = _conv(conf, domain, port) + + return conf class Configuration(Base): @@ -215,10 +225,24 @@ def __init__(self, self.web_conf = lower_or_upper(self.conf, "webserver") if entity_conf: + skip = [ec["path"] for ec in entity_conf if 'path' in ec] + check = [l[0] for l in skip] + self.extend(conf=self.conf, base_path=base_path, domain=self.domain, port=self.port, entity_conf=entity_conf, file_attributes=self._file_attributes, dir_attributes=self._dir_attributes) + for key, val in conf.items(): + if key in ["logging", "webserver", "domain", "port"]: + continue + + if key in check: + continue + + setattr(self, key, val) + else: + for key, val in conf.items(): + setattr(self, key, val) def create_from_config_file(cls, diff --git a/src/idpyoidc/server/configure.py b/src/idpyoidc/server/configure.py index 8a23a1f3..d5e6b250 100755 --- a/src/idpyoidc/server/configure.py +++ b/src/idpyoidc/server/configure.py @@ -149,7 +149,7 @@ class EntityConfiguration(Base): "endpoint": {}, "httpc_params": {}, "issuer": "", - "keys": None, + "key_conf": None, "session_params": None, "template_dir": None, "token_handler_args": {}, @@ -168,17 +168,17 @@ def __init__( ): conf = copy.deepcopy(conf) - Base.__init__(self, conf, base_path, file_attributes, dir_attributes=dir_attributes) + Base.__init__(self, conf, base_path, file_attributes=file_attributes, + dir_attributes=dir_attributes, domain=domain, port=port) - self.key_conf = conf.get('key_conf') + self.key_conf = conf.get('key_conf', conf.get('keys')) for key in self.parameter.keys(): _val = conf.get(key) if not _val: if key in self.default_config: - _val = copy.deepcopy(self.default_config[key]) - self.format( - _val, + _val = self.format( + copy.deepcopy(self.default_config[key]), base_path=base_path, file_attributes=file_attributes, domain=domain, @@ -189,7 +189,7 @@ def __init__( continue if key not in DEFAULT_EXTENDED_CONF: - logger.warning(f"{key} not seems to be a valid configuration parameter") + logger.warning(f"{key} does not seems to be a valid configuration parameter") elif not _val: logger.warning(f"{key} not configured, using default configuration values") @@ -334,6 +334,10 @@ def __init__( "refresh_token", ], }, + "claims_interface": { + "class": "idpyoidc.server.session.claims.ClaimsInterface", + "kwargs": {} + }, "cookie_handler": { "class": "idpyoidc.server.cookie_handler.CookieHandler", "kwargs": { @@ -462,7 +466,9 @@ def __init__( "jwks_def": { "private_path": "private/token_jwks.json", "read_only": False, - "key_defs": [{"type": "oct", "bytes": "24", "use": ["enc"], "kid": "code"}], + "key_defs": [ + {"type": "oct", "bytes": "24", "use": ["enc"], "kid": "code"} + ], }, "code": {"kwargs": {"lifetime": 600}}, "token": { diff --git a/tests/test_server_00_configure.py b/tests/test_server_00_configure.py index f70a04a9..3d575caf 100644 --- a/tests/test_server_00_configure.py +++ b/tests/test_server_00_configure.py @@ -1,12 +1,11 @@ import json import os -import pytest - from idpyoidc.configure import Configuration from idpyoidc.configure import create_from_config_file from idpyoidc.logging import configure_logging from idpyoidc.server.configure import OPConfiguration +import pytest BASEDIR = os.path.abspath(os.path.dirname(__file__)) @@ -99,7 +98,13 @@ def test_op_configure_default_from_file(): def test_server_configure(): configuration = create_from_config_file( Configuration, - entity_conf=[{"class": OPConfiguration, "attr": "op", "path": ["op", "server_info"]}], + entity_conf=[ + { + "class": OPConfiguration, + "attr": "op", + "path": ["op", "server_info"] + } + ], filename=full_path("srv_config.json"), base_path=BASEDIR, ) diff --git a/tests/test_server_20a_server.py b/tests/test_server_20a_server.py index 6454ff80..cfa136f4 100755 --- a/tests/test_server_20a_server.py +++ b/tests/test_server_20a_server.py @@ -111,7 +111,7 @@ def test_capabilities_default(): "code id_token token", } assert server.endpoint_context.provider_info["request_uri_parameter_supported"] is True - assert server.endpoint_context.jwks_uri == 'https://127.0.0.1:80/static/jwks.json' + assert server.endpoint_context.jwks_uri == 'https://127.0.0.1:443/static/jwks.json' def test_capabilities_subset1():