Skip to content

Commit

Permalink
Merge branch 'rohe:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
mikaelfrykholm authored Dec 6, 2024
2 parents 024ec01 + 757ac61 commit cd70ace
Show file tree
Hide file tree
Showing 25 changed files with 96 additions and 38 deletions.
2 changes: 1 addition & 1 deletion dc4eu_federation/tmp.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"https://127.0.0.1:6000": ["http://dc4eu.example.com/PersonIdentificationData/se", "http://dc4eu.example.com/OpenBadgeCredential/se", "https://refeds.org/category/personalized"]}
{"https://127.0.0.1:5001": {"entity_types": ["federation_entity", "wallet_provider", "device_integrity_service"], "jwks": {"keys": [{"kty": "RSA", "use": "sig", "kid": "N1E0SGRiX0gtVVZmaHZpLWpwRXpNZnE4SnljWVhVVnN5NmNJb2NQa0ctdw", "n": "i580_1_7bWDKSP9aKLxEcKCCqgu3jz4bJyR5FoynOGeiByksIM4wVl5UGr9aCL8rUjzW22zd5iojsqBWAmlGLP6pIhJMiCKuvQFt0bpbk8H6k0J4-iqJ1l_Qr-NL97sEtQWJyoV-GpYIt0i9gNHoLjgkSmfx5jaGqfQLEjV364c76rCZJuiNdu0KRa_tEM_yvvrSc1k-8WMkgE0BJl-gBpTBHkQ2Df8Z4D2L6OLQcF2UDv5kydWOzbC3BWiMPOkMvag1ZN7CYkHFsS1ipQUD2w5bWtJcaDUCPu4XVHyiPS92NkNSfceHxstgzE8lXMBrhECEuOW1g6yfXV43UuClAQ", "e": "AQAB"}, {"kty": "EC", "use": "sig", "kid": "dEpFM3VBUk5qa2RZREJnQXNHZDA3RG1SbkNmZ1lRRzR1dFRMVHM2elhmTQ", "crv": "P-256", "x": "aqQRfOH8xgqDG-lo9kjeCgTyxX-8WD4zv_GyILHg_mk", "y": "KVNu-zFP1858BokTfkHe1NRuKsCbPt2rhi6HXHScs18"}]}}}
2 changes: 1 addition & 1 deletion dc4eu_federation/trust_anchor/static/fed_keys.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"keys": [{"kty": "RSA", "use": "sig", "kid": "ZXFYbDlqWkNzaWd1eDNseTVfWFBNUWRFX3lrQ2Y3b2owaWVMTjNhcnpBMA", "n": "qHE53SwNAYWZfLQufshE5vhJDBzAEgdO762SkGcV59GDx2VZIyoSek3Y8X8_Z6pVGeDovBQCBstwD7X4ZL4ynMsGb_Szphx2dlcvYPHfY4BFJWGoROPzo8VJ-z5CLseHKg_LXL-PxTHziZFBawMJn5vTodRQVJIU_WA5K408WuNgBh_IhkTj37L-fajwExYoPMWu-YMNlUWD8ta_hnHxLE43QZW5shq09LcTj9VcJdWey1i4q_ftHoZsFngML-kA8KBImeiirtCHs6V1eA3LxJ5a_KojK7aPcA9VgvPH1987I4gqHFedtLZkV5dewYt4HGQ4O3YQ8IsX1Nse0ib2Sw", "e": "AQAB"}, {"kty": "EC", "use": "sig", "kid": "Nng1Yy1SMmFoRC1VQ2g4NllXSEU1dEtkY0VkX3pweG5RXzdLMjY1WkJNMA", "crv": "P-256", "x": "yLcidWumqjOPjJI1OcSjgTtqmOfNzC0APWKdRIFik3Y", "y": "8IkDqyQyLHB10Klvz7vJIb6jrlJ_-HDgMGusR_JzckE"}]}
{"keys": [{"kty": "RSA", "use": "sig", "kid": "ZXFYbDlqWkNzaWd1eDNseTVfWFBNUWRFX3lrQ2Y3b2owaWVMTjNhcnpBMA", "e": "AQAB", "n": "qHE53SwNAYWZfLQufshE5vhJDBzAEgdO762SkGcV59GDx2VZIyoSek3Y8X8_Z6pVGeDovBQCBstwD7X4ZL4ynMsGb_Szphx2dlcvYPHfY4BFJWGoROPzo8VJ-z5CLseHKg_LXL-PxTHziZFBawMJn5vTodRQVJIU_WA5K408WuNgBh_IhkTj37L-fajwExYoPMWu-YMNlUWD8ta_hnHxLE43QZW5shq09LcTj9VcJdWey1i4q_ftHoZsFngML-kA8KBImeiirtCHs6V1eA3LxJ5a_KojK7aPcA9VgvPH1987I4gqHFedtLZkV5dewYt4HGQ4O3YQ8IsX1Nse0ib2Sw"}, {"kty": "EC", "use": "sig", "kid": "Nng1Yy1SMmFoRC1VQ2g4NllXSEU1dEtkY0VkX3pweG5RXzdLMjY1WkJNMA", "crv": "P-256", "x": "yLcidWumqjOPjJI1OcSjgTtqmOfNzC0APWKdRIFik3Y", "y": "8IkDqyQyLHB10Klvz7vJIb6jrlJ_-HDgMGusR_JzckE"}]}

This file was deleted.

Empty file.

This file was deleted.

Empty file.

This file was deleted.

Empty file.

This file was deleted.

Empty file.
1 change: 1 addition & 0 deletions dc4eu_federation/trust_mark_issuer/authority_hints
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
https://127.0.0.1:7003
https://127.0.0.1:7003
1 change: 1 addition & 0 deletions dc4eu_federation/trust_mark_issuer/pid_se
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
{"iat": 1721643745, "id": "http://dc4eu.example.com/PersonIdentificationData/se", "sub": "https://127.0.0.1:6001", "exp": 1724235745}
{"iat": 1721722533, "id": "http://dc4eu.example.com/PersonIdentificationData/se", "sub": "https://127.0.0.1:8080", "exp": 1724314533}
{"iat": 1727165463, "id": "http://dc4eu.example.com/PersonIdentificationData/se", "sub": "https://127.0.0.1:8080", "exp": 1729757463}
{"iat": 1730393790, "id": "http://dc4eu.example.com/PersonIdentificationData/se", "sub": "https://127.0.0.1:8080", "exp": 1732985790}
1 change: 1 addition & 0 deletions dc4eu_federation/wallet_provider/authority_hints
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
https://127.0.0.1:7003
https://127.0.0.1:7003
4 changes: 2 additions & 2 deletions edu_federation/openid_provider/conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
"refresh_token"
]
},
"template_dir": "templates",
"template_dir": "openid_provider/templates",
"token_handler_args": {
"jwks_def": {
"private_path": "openid_provider/private/token_jwk.json",
Expand Down Expand Up @@ -177,7 +177,7 @@
}
}
},
"keys": {
"key_conf": {
"private_path": "openid_provider/private/jwks.json",
"key_defs": [
{
Expand Down
4 changes: 3 additions & 1 deletion edu_federation/relying_party_explicit/conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@
"[email protected]"
],
"response_types_supported": [
"code"
"code",
"code id_token",
"id_token"
],
"scope": [
"openid",
Expand Down
6 changes: 2 additions & 4 deletions edu_federation/relying_party_explicit/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,16 +200,14 @@ def finalize(op_identifier, request_args):
_fe = current_app.server["federation_entity"]
op = rp.context.provider_info["issuer"]
trust_anchor = list(_fe.context.trust_chain[op].keys())[0]
trust_chain = _fe.context.trust_chain[op][trust_anchor]
federation_endpoints = {}
trust_chain = _fe.context.trust_chain[op]
trust_path = trust_chain.iss_path
trust_path_expires = timestamp2local(trust_chain.exp)
trust_marks = trust_chain.verified_chain[1]["trust_marks"]
trust_marks = trust_chain.verified_chain[1].get("trust_marks", [])
return render_template('rpe_opresult.html', endpoints=endpoints,
userinfo=res['userinfo'],
access_token=res['token'],
id_token=res["id_token"],
federation_endpoints=federation_endpoints,
trust_path=trust_path,
trust_path_expires=trust_path_expires,
trust_marks=trust_marks,
Expand Down
7 changes: 1 addition & 6 deletions edu_federation/templates/rpe_opresult.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,10 @@ <h4>OpenID Provider Endpoints</h4>
<dd>{{ url }}</dd>
{% endfor %}
<h3>Federation Entity information</h3>
<h4>Trust Path</h4>
<h4>OpenID Provider Trust Path</h4>
{{ trust_path }}
<h4>Trust path expires</h4>
{{ trust_path_expires }}
<h4>Federation Endpoints</h4>
{% for end_point, url in federation_endpoints.items() %}
<dt>{{ end_point }}</dt>
<dd>{{ url }}</dd>
{% endfor %}
<h4>Trust marks</h4>
{{ trust_marks }}
</body>
Expand Down
1 change: 1 addition & 0 deletions edu_federation/trust_mark_issuer/personalized
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@
{"iat": 1726130579, "id": "https://refeds.org/category/personalized", "sub": "https://127.0.0.1:4002", "exp": 1728722579}
{"iat": 1727685941, "id": "https://refeds.org/category/personalized", "sub": "https://127.0.0.1:4010", "exp": 1730277941}
{"iat": 1727686121, "id": "https://refeds.org/category/personalized", "sub": "https://127.0.0.1:4010", "exp": 1730278121}
{"iat": 1730714978, "id": "https://refeds.org/category/personalized", "sub": "https://127.0.0.1:4010", "exp": 1733306978}
25 changes: 17 additions & 8 deletions src/fedservice/appclient/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from json import JSONDecodeError
import logging
import re
from json import JSONDecodeError
from typing import Callable
from typing import Optional
from typing import Union
Expand All @@ -12,12 +12,11 @@
from idpyoidc.client.defaults import SUCCESSFUL
from idpyoidc.client.exception import OidcServiceError
from idpyoidc.client.rp_handler import RPHandler
from idpyoidc.client.service import init_services
from idpyoidc.client.service import REQUEST_INFO
from idpyoidc.client.service import Service
from idpyoidc.client.service import init_services
from idpyoidc.client.service_context import ServiceContext
from idpyoidc.client.util import do_add_ons
from idpyoidc.client.util import get_content_type
from idpyoidc.client.util import get_deserialization_method
from idpyoidc.configure import Configuration
from idpyoidc.context import OidcContext
Expand All @@ -28,8 +27,8 @@

from fedservice.defaults import COMBINED_DEFAULT_OAUTH2_SERVICES
from fedservice.defaults import COMBINED_DEFAULT_OIDC_SERVICES
from fedservice.message import OIDCRPMetadata
from fedservice.message import OauthClientMetadata
from fedservice.message import OIDCRPMetadata

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -153,6 +152,16 @@ def get_metadata(self, entity_type="", *args):
return self.context.claims.get_client_metadata(entity_type=entity_type,
metadata_schema=self.metadata_class)

def get_registration_metadata(self, entity_type="", *args):
if not entity_type:
if self.client_type == "oauth2":
entity_type = "oauth_client"
elif self.client_type == "oidc":
entity_type = "openid_relying_party"

return self.context.claims.get_registration_metadata(entity_type=entity_type,
metadata_schema=self.metadata_class)

def do_request(
self,
request_type: str,
Expand Down Expand Up @@ -315,8 +324,8 @@ def parse_request_response(self, service, reqresp, response_body_type="", state=

if reqresp.status_code in SUCCESSFUL:
logger.debug(f'response_body_type: "{response_body_type}"')
_ctype = get_content_type(reqresp)
_deser_method = get_deserialization_method(_ctype)
_ctype = reqresp.headers.get("content-type")
_deser_method = get_deserialization_method(reqresp)

if _ctype != response_body_type:
logger.warning(f"Not the body type I expected: {_ctype} != {response_body_type}")
Expand All @@ -341,8 +350,8 @@ def parse_request_response(self, service, reqresp, response_body_type="", state=
elif 400 <= reqresp.status_code < 500:
logger.error(f"Error response ({reqresp.status_code}): {reqresp.text}")
# expecting an error response
content_type = get_content_type(reqresp)
_deser_method = get_deserialization_method(content_type)
content_type = reqresp.headers.get("content-type")
_deser_method = get_deserialization_method(reqresp)
if not content_type:
content_type = "application/json"

Expand Down
14 changes: 13 additions & 1 deletion src/fedservice/appclient/oauth2/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ def collect_metadata(self, combo, **kwargs):
metadata.update(combo["federation_entity"].get_metadata())
return metadata

def registration_metadata(self, combo, **kwargs):
metadata = {}
_guise = kwargs.get("client", None)
if _guise is None:
for _guise in self.get_guise(combo):
metadata.update(_guise.registration_metadata())
else:
metadata.update(_guise.registration_metadata())
metadata.update(combo["federation_entity"].registration_metadata())
return metadata

def create_entity_statement(self, request_args: Optional[dict] = None, **kwargs):
"""
Create a self-signed entity statement
Expand All @@ -75,7 +86,8 @@ def create_entity_statement(self, request_args: Optional[dict] = None, **kwargs)

_federation_entity = get_federation_entity(self)
_combo = _federation_entity.upstream_get('unit')
metadata = self.collect_metadata(_combo, **kwargs)
metadata = self.registration_metadata(_combo, **kwargs)
# metadata = self.collect_metadata(_combo, **kwargs)

_keyjar = _federation_entity.get_attribute("keyjar")
_authority_hints = _federation_entity.get_authority_hints()
Expand Down
2 changes: 1 addition & 1 deletion src/fedservice/appclient/oidc/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def create_entity_statement(self, request_args: Optional[dict]= None, **kwargs):

def parse_response(self, info, sformat="", state="", **kwargs):
resp = self.parse_federation_registration_response(info, **kwargs)

logger.debug(f"Registration response: {resp}")
if not resp:
logger.error('Missing or faulty response')
raise ResponseError("Missing or faulty response")
Expand Down
32 changes: 29 additions & 3 deletions src/fedservice/appclient/stand_alone_client_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from idpyoidc.message.oauth2 import is_error_message
from idpyoidc.message.oauth2 import ResponseMessage
from idpyoidc.message.oidc import OpenIDSchema
from idpyoidc.node import topmost_unit
from idpyoidc.transform import create_registration_request
from idpyoidc.util import rndstr

from fedservice import save_trust_chains
Expand Down Expand Up @@ -49,6 +49,20 @@ def load_registration_response(entity, request_args, **kwargs):

class StandAloneClientEntity(ClientEntity):

def _import_keys(self, resp, keyjar, issuer):
if "jwks_uri" in resp:
logger.debug(f"'jwks_uri' in provider info: {resp['jwks_uri']}")
_hp = self.upstream_get("attribute","httpc_params")
if _hp:
if "verify" in _hp and "verify" not in keyjar.httpc_params:
keyjar.httpc_params["verify"] = _hp["verify"]
keyjar.load_keys(issuer, jwks_uri=resp["jwks_uri"])
elif "jwks" in resp:
logger.debug("'jwks' in provider info")
keyjar.load_keys(issuer, jwks=resp["jwks"])
else:
logger.debug("Neither jws or jwks_uri in provider info")

def _collect_metadata(self, federation_entity, context):
_trust_chains = get_verified_trust_chains(self, context.issuer)
if _trust_chains:
Expand All @@ -57,7 +71,9 @@ def _collect_metadata(self, federation_entity, context):
federation_entity.trust_chain_anchor = trust_chain.anchor
# _pi = trust_chain.metadata["openid_relying_party"]
_pi = trust_chain.metadata["openid_provider"]
federation_entity.context.trust_chain[_pi["issuer"]] = trust_chain
context.provider_info = context.metadata = _pi
self._import_keys(_pi, context.keyjar, _pi["issuer"])
return _pi
else:
raise NoTrustedChains(context.issuer)
Expand Down Expand Up @@ -155,10 +171,16 @@ def do_client_registration(
_context.map_preferred_to_registered()

def _get_response_type(self, context, req_args: Optional[dict] = None):
default_response_type = "code"
if req_args:
return req_args.get("response_type", context.claims.get_usage("response_types")[0])
_response_type = req_args.get("response_type")
if _response_type:
return _response_type
else:
return context.claims.get_usage("response_types")[0]
if default_response_type in context.claims.get_usage("response_types"):
return default_response_type
else:
return context.claims.get_usage("response_types")[0]

def _get_response_mode(self, context, response_type, request_args):
if request_args:
Expand Down Expand Up @@ -702,3 +724,7 @@ def close(self, state: str, post_logout_redirect_uri: Optional[str] = "") -> dic

def clear_session(self, state):
self.get_context().cstate.remove_state(state)

def registration_metadata(self):
_context = self.get_context()
return {self.entity_type: create_registration_request(_context.claims.prefer, _context.claims.supports())}
1 change: 1 addition & 0 deletions src/fedservice/appserver/oidc/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def process_request(self, request=None, **kwargs):
# Perform non-federation registration
response_info = self.non_fed_process_request(req, **kwargs)
if "response_args" in response_info:
logger.debug(f"Registration response args: {response_info['response_args']}")
_context = _federation_entity.context

for item in ["jwks", "jwks_uri", "signed_jwks_uri"]:
Expand Down
16 changes: 16 additions & 0 deletions src/fedservice/entity/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,22 @@ def get_function(self, function_name, *args):
except AttributeError:
return None

def registration_metadata(self, entity_type="federation_entity", *args):
_context = self.get_context()
_claims = _context.claims

metadata = _claims.get_server_metadata(endpoints=self.get_all_endpoints())

# remove these from the metadata
for item in ["jwks", "jwks_uri", "signed_jwks_uri"]:
try:
del metadata[item]
except KeyError:
pass

# _issuer = getattr(self.server.context, "trust_mark_server", None)
return {entity_type: metadata}

def get_metadata(self, entity_type="federation_entity", *args):
_context = self.get_context()
_claims = _context.claims
Expand Down
Loading

0 comments on commit cd70ace

Please sign in to comment.