Skip to content

Commit

Permalink
Merge pull request #352 from italia/federation2
Browse files Browse the repository at this point in the history
- Huge cleanups and optimizations 
- adds a default_client_id and the possibility for each trust evaluation handler to use different client ids (experimental due to the LSP Potential requirements)
- aims to remove all the duplicated code and overlapping classes born during the refactoring from 0.7 to 0.9, with the scope to simplify the implementations
- extends the configurations and consolidates the example configuration to provide a more appropriate guidance to the implementers
- removes the deprecation warning about pydantic FieldValidationInfo
  • Loading branch information
peppelinux authored Feb 19, 2025
2 parents ea3a917 + 688557f commit e57606c
Show file tree
Hide file tree
Showing 182 changed files with 5,219 additions and 4,872 deletions.
5 changes: 5 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[flake8]
ignore = D203,E121,E124,E126,E203,E231,E261,E251,E701,F403,F405,E402
exclude = .git,__pycache__,docs/source/conf.py,old,build,dist,*/migrations/*,tests.py,*/tests/*
max-line-length=180
max-complexity = 25
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,14 @@ Please consider the following branches:

### Executing Unit Tests

Once you have activate the virtualenv, unit tests can be executed as show below.
Once you have activate the virtualenv, further dependencies must be installed as show below.

````
pip install -r requirements-dev.txt
````

Therefore the unit tests can be executed as show below.

````
pytest pyeudiw -x
Expand All @@ -131,6 +138,23 @@ you can run the test by passing the mon user and password in this way
PYEUDIW_MONGO_TEST_AUTH_INLINE="satosa:thatpassword@" pytest pyeudiw -x
````

### Executing integration tests

iam-proxy-italia project must be configured and in execution.

Integrations tests checks bot hthe cross device flow and the same device flow.

The cross device flow requires `playwrite` to be installed.

````
cd examples/satosa/integration_tests
playwrite install
PYEUDIW_MONGO_TEST_AUTH_INLINE="satosa:thatpassword@" pytest pyeudiw -x
````



## Authors

Expand Down
6 changes: 3 additions & 3 deletions docs/TRUST.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,18 @@ Some HTTPC parameters are commonly used, have a default value and as an alternat

### Federation

Module `pyeudiw.trust.default.federation` provides a source of trusted entities and metadata based on [OpenID Federation](https://openid.net/specs/openid-federation-1_0.html) that is intended to be applicable to Issuer, Holders and Verifiers. In the specific case of the Verifier (this application), the module can expose verifier metadata at the `.well-known/openid-federation` endpoint.
Module `pyeudiw.trust.handler.federation` provides a source of trusted entities and metadata based on [OpenID Federation](https://openid.net/specs/openid-federation-1_0.html) that is intended to be applicable to Issuer, Holders and Verifiers. In the specific case of the Verifier (this application), the module can expose verifier metadata at the `.well-known/openid-federation` endpoint.

The configuration parameters of the module are the following.


| Parameter | Description | Example Value |
| -------------------------------------------------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------ |
| config.federation.metadata_type | The type of metadata to use for the federation | wallet_relying_party |
| config.federation.metadata_type | The type of metadata to use for the federation | openid_credential_verifier |
| config.federation.authority_hints | The list of authority hints to use for the federation | [http://127.0.0.1:10000] |
| config.federation.trust_anchors | The list of trust anchors to use for the federation | [http://127.0.0.1:10000] |
| config.federation.default_sig_alg | The default signature algorithm to use for the federation | RS256 |
| config.federation.federation_entity_metadata.organization_name | The organization name | Developers Italia SATOSA OpenID4VP backend policy_uri, tos_uri, logo_uri |
| config.federation.federation_entity_metadata.organization_name | The organization name | IAM Proxy Italia OpenID4VP backend policy_uri, tos_uri, logo_uri |
| config.federation.federation_entity_metadata.homepage_uri | The URI of the homepage | https://developers.italia.it |
| config.federation.federation_entity_metadata.policy_uri | The URI of the policy | https://developers.italia.it/policy.html |
| config.federation.federation_entity_metadata.tos_uri | The URI of the TOS | https://developers.italia.it/tos.html |
Expand Down
9 changes: 5 additions & 4 deletions example/satosa/integration_test/commons.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@
)
from pyeudiw.sd_jwt.holder import SDJWTHolder
from pyeudiw.trust.model.trust_source import TrustSourceData
from saml2_sp import saml2_request

from settings import (
from . saml2_sp import saml2_request

from . settings import (
IDP_BASEURL,
CONFIG_DB,
RP_EID,
Expand Down Expand Up @@ -177,8 +178,8 @@ def create_authorize_response(vp_token: str, state: str, response_uri: str) -> s
).content.decode()
rp_ec = decode_jwt_payload(rp_ec_jwt)

assert response_uri == rp_ec["metadata"]["wallet_relying_party"]["response_uris_supported"][0]
encryption_key = rp_ec["metadata"]["wallet_relying_party"]["jwks"]["keys"][1]
# assert response_uri == rp_ec["metadata"]["openid_credential_verifier"]["response_uris"][0]
encryption_key = rp_ec["metadata"]["openid_credential_verifier"]["jwks"]["keys"][1]

response = {
"state": state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from pyeudiw.jwt.utils import decode_jwt_payload

from commons import (
from . commons import (
ISSUER_CONF,
setup_test_db_engine,
apply_trust_settings,
Expand All @@ -18,7 +18,7 @@
extract_saml_attributes,
verify_request_object_jwt
)
from settings import TIMEOUT_S
from . settings import TIMEOUT_S

# put a trust attestation related itself into the storage
# this is then used as trust_chain header parameter in the signed request object
Expand Down Expand Up @@ -92,6 +92,7 @@ def run(playwright: Playwright):
request_object_claims["nonce"],
request_object_claims["client_id"]
)

wallet_response_data = create_authorize_response(
verifiable_presentations,
request_object_claims["state"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from pyeudiw.jwt.utils import decode_jwt_payload

from commons import (
from . commons import (
ISSUER_CONF,
setup_test_db_engine,
apply_trust_settings,
Expand All @@ -15,7 +15,7 @@
extract_saml_attributes,
verify_request_object_jwt
)
from settings import TIMEOUT_S
from . settings import TIMEOUT_S

# put a trust attestation related itself into the storage
# this is then used as trust_chain header parameter in the signed request object
Expand Down
2 changes: 1 addition & 1 deletion example/satosa/integration_test/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@
"sub": RP_EID,
'jwks': {"keys": rp_jwks},
"metadata": {
"wallet_relying_party": {
"openid_credential_verifier": {
'jwks': {"keys": []}
},
"federation_entity": {
Expand Down
148 changes: 76 additions & 72 deletions example/satosa/pyeudiw_backend.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module: pyeudiw.satosa.backend.OpenID4VPBackend
name: OpenID4VP

config:

ui:
static_storage_url: !ENV SATOSA_BASE_STATIC
template_folder: "templates" # project root
Expand All @@ -20,7 +20,6 @@ config:
module: pyeudiw.satosa.default.response_handler
class: ResponseHandler
path: '/response-uri'
entity_configuration: '/.well-known/openid-federation'
status: '/status'
get_response: '/get-response'

Expand Down Expand Up @@ -107,38 +106,108 @@ config:
subject_id_random_value: CHANGEME!

network:
httpc_params:
httpc_params: &httpc_params
connection:
ssl: true
session:
timeout: 6

# private jwk
metadata_jwks: &metadata_jwks
- crv: P-256
d: KzQBowMMoPmSZe7G8QsdEWc1IvR2nsgE8qTOYmMcLtc
kid: dDwPWXz5sCtczj7CJbqgPGJ2qQ83gZ9Sfs-tJyULi6s
use: sig
kty: EC
x: TSO-KOqdnUj5SUuasdlRB2VVFSqtJOxuR5GftUTuBdk
y: ByWgQt1wGBSnF56jQqLdoO1xKUynMY-BHIDB3eXlR7
- kty: RSA
d: QUZsh1NqvpueootsdSjFQz-BUvxwd3Qnzm5qNb-WeOsvt3rWMEv0Q8CZrla2tndHTJhwioo1U4NuQey7znijhZ177bUwPPxSW1r68dEnL2U74nKwwoYeeMdEXnUfZSPxzs7nY6b7vtyCoA-AjiVYFOlgKNAItspv1HxeyGCLhLYhKvS_YoTdAeLuegETU5D6K1xGQIuw0nS13Icjz79Y8jC10TX4FdZwdX-NmuIEDP5-s95V9DMENtVqJAVE3L-wO-NdDilyjyOmAbntgsCzYVGH9U3W_djh4t3qVFCv3r0S-DA2FD3THvlrFi655L0QHR3gu_Fbj3b9Ybtajpue_Q
e: AQAB
use: enc
kid: 9Cquk0X-fNPSdePQIgQcQZtD6J0IjIRrFigW2PPK_-w
n: utqtxbs-jnK0cPsV7aRkkZKA9t4S-WSZa3nCZtYIKDpgLnR_qcpeF0diJZvKOqXmj2cXaKFUE-8uHKAHo7BL7T-Rj2x3vGESh7SG1pE0thDGlXj4yNsg0qNvCXtk703L2H3i1UXwx6nq1uFxD2EcOE4a6qDYBI16Zl71TUZktJwmOejoHl16CPWqDLGo9GUSk_MmHOV20m4wXWkB4qbvpWVY8H6b2a0rB1B1YPOs5ZLYarSYZgjDEg6DMtZ4NgiwZ-4N1aaLwyO-GLwt9Vf-NBKwoxeRyD3zWE2FXRFBbhKGksMrCGnFDsNl5JTlPjaM3kYyImE941ggcuc495m-Fw
p: 2zmGXIMCEHPphw778YjVTar1eycih6fFSJ4I4bl1iq167GqO0PjlOx6CZ1-OdBTVU7HfrYRiUK_BnGRdPDn-DQghwwkB79ZdHWL14wXnpB5y-boHz_LxvjsEqXtuQYcIkidOGaMG68XNT1nM4F9a8UKFr5hHYT5_UIQSwsxlRQ0
q: 2jMFt2iFrdaYabdXuB4QMboVjPvbLA-IVb6_0hSG_-EueGBvgcBxdFGIZaG6kqHqlB7qMsSzdptU0vn6IgmCZnX-Hlt6c5X7JB_q91PZMLTO01pbZ2Bk58GloalCHnw_mjPh0YPviH5jGoWM5RHyl_HDDMI-UeLkzP7ImxGizrM

#This is the configuration for the relaying party metadata
metadata: &metadata
application_type: web

#The following section contains all the algorithms supported for the encryption of response
authorization_encrypted_response_alg: *enc_alg_supported
authorization_encrypted_response_enc: *enc_enc_supported
authorization_signed_response_alg: *sig_alg_supported

#Various informations of the client
client_id: # this field is autopopulated using internal variables base_url and name using the following format: "<base_url>/<name>"
client_name: Name of an example organization
contacts:
- [email protected]
default_acr_values:
- https://www.spid.gov.it/SpidL2
- https://www.spid.gov.it/SpidL3

#The following section contains all the algorithms supported for the encryption of id token response
id_token_encrypted_response_alg: *enc_alg_supported
id_token_encrypted_response_enc: *enc_enc_supported
id_token_signed_response_alg: *sig_alg_supported

# loaded in the __init__
# jwks:

redirect_uris:
# This field is autopopulated using internal variables base_url and name using the following format: <base_url>/<name>/redirect-uri"
request_uris:
# This field is autopopulated using internal variables base_url and name using the following format: <base_url>/<name>/request-uri"

# not necessary according to openid4vp
# default_max_age: 1111
# require_auth_time: true
# subject_type: pairwise

vp_formats:
vc+sd-jwt:
sd-jwt_alg_values:
- ES256
- ES384
kb-jwt_alg_values:
- ES256
- ES384

trust:
direct_trust_sd_jwt_vc:
module: pyeudiw.trust.handler.direct_trust_sd_jwt_vc
class: DirectTrustSdJwtVc
config:
cache_ttl: 0
httpc_params: *httpc_params
jwk_endpoint: /.well-known/jwt-vc-issuer
direct_trust_jar:
module: pyeudiw.trust.handler.direct_trust_jar
class: DirectTrustJar
config:
cache_ttl: 0
httpc_params: *httpc_params
jwk_endpoint: /.well-known/jar-issuer
jwks: *metadata_jwks
federation:
module: pyeudiw.trust.handler.federation
class: FederationHandler
config:
metadata_type: "wallet_relying_party"
httpc_params: *httpc_params
cache_ttl: 0
entity_configuration_exp: 600
metadata_type: "openid_credential_verifier"
metadata: *metadata
authority_hints:
- http://127.0.0.1:8000
trust_anchors:
- public_keys: []
- http://127.0.0.1:8000
- http://127.0.0.1:8000: [] # array of public keys
default_sig_alg: "RS256"
trust_marks: []
federation_entity_metadata:
organization_name: Developers Italia SATOSA OpenID4VP backend
organization_name: IAM Proxy Italia OpenID4VP backend
homepage_uri: https://developers.italia.it
policy_uri: https://developers.italia.it
tos_uri: https://developers.italia.it
Expand Down Expand Up @@ -184,68 +253,3 @@ config:
db_trust_sources_collection: trust_sources
data_ttl: 63072000 # 2 years
# - connection_params:

# private jwk
metadata_jwks: &metadata_jwks
# !ENV PYEUDIW_METADATA_JWKS
- crv: P-256
d: KzQBowMMoPmSZe7G8QsdEWc1IvR2nsgE8qTOYmMcLtc
kid: dDwPWXz5sCtczj7CJbqgPGJ2qQ83gZ9Sfs-tJyULi6s
use: sig
kty: EC
x: TSO-KOqdnUj5SUuasdlRB2VVFSqtJOxuR5GftUTuBdk
y: ByWgQt1wGBSnF56jQqLdoO1xKUynMY-BHIDB3eXlR7
- kty: RSA
d: QUZsh1NqvpueootsdSjFQz-BUvxwd3Qnzm5qNb-WeOsvt3rWMEv0Q8CZrla2tndHTJhwioo1U4NuQey7znijhZ177bUwPPxSW1r68dEnL2U74nKwwoYeeMdEXnUfZSPxzs7nY6b7vtyCoA-AjiVYFOlgKNAItspv1HxeyGCLhLYhKvS_YoTdAeLuegETU5D6K1xGQIuw0nS13Icjz79Y8jC10TX4FdZwdX-NmuIEDP5-s95V9DMENtVqJAVE3L-wO-NdDilyjyOmAbntgsCzYVGH9U3W_djh4t3qVFCv3r0S-DA2FD3THvlrFi655L0QHR3gu_Fbj3b9Ybtajpue_Q
e: AQAB
use: enc
kid: 9Cquk0X-fNPSdePQIgQcQZtD6J0IjIRrFigW2PPK_-w
n: utqtxbs-jnK0cPsV7aRkkZKA9t4S-WSZa3nCZtYIKDpgLnR_qcpeF0diJZvKOqXmj2cXaKFUE-8uHKAHo7BL7T-Rj2x3vGESh7SG1pE0thDGlXj4yNsg0qNvCXtk703L2H3i1UXwx6nq1uFxD2EcOE4a6qDYBI16Zl71TUZktJwmOejoHl16CPWqDLGo9GUSk_MmHOV20m4wXWkB4qbvpWVY8H6b2a0rB1B1YPOs5ZLYarSYZgjDEg6DMtZ4NgiwZ-4N1aaLwyO-GLwt9Vf-NBKwoxeRyD3zWE2FXRFBbhKGksMrCGnFDsNl5JTlPjaM3kYyImE941ggcuc495m-Fw
p: 2zmGXIMCEHPphw778YjVTar1eycih6fFSJ4I4bl1iq167GqO0PjlOx6CZ1-OdBTVU7HfrYRiUK_BnGRdPDn-DQghwwkB79ZdHWL14wXnpB5y-boHz_LxvjsEqXtuQYcIkidOGaMG68XNT1nM4F9a8UKFr5hHYT5_UIQSwsxlRQ0
q: 2jMFt2iFrdaYabdXuB4QMboVjPvbLA-IVb6_0hSG_-EueGBvgcBxdFGIZaG6kqHqlB7qMsSzdptU0vn6IgmCZnX-Hlt6c5X7JB_q91PZMLTO01pbZ2Bk58GloalCHnw_mjPh0YPviH5jGoWM5RHyl_HDDMI-UeLkzP7ImxGizrM

#This is the configuration for the relaying party metadata
metadata:
application_type: web

#The following section contains all the algorithms supported for the encryption of response
authorization_encrypted_response_alg: *enc_alg_supported
authorization_encrypted_response_enc: *enc_enc_supported
authorization_signed_response_alg: *sig_alg_supported

#Various informations of the client
client_id: # this field is autopopulated using internal variables base_url and name using the following format: "<base_url>/<name>"
client_name: Name of an example organization
contacts:
- [email protected]
default_acr_values:
- https://www.spid.gov.it/SpidL2
- https://www.spid.gov.it/SpidL3

default_max_age: 1111

#The following section contains all the algorithms supported for the encryption of id token response
id_token_encrypted_response_alg: *enc_alg_supported
id_token_encrypted_response_enc: *enc_enc_supported
id_token_signed_response_alg: *sig_alg_supported

# loaded in the __init__
# jwks:


redirect_uris:
# This field is autopopulated using internal variables base_url and name using the following format: <base_url>/<name>/redirect-uri"
request_uris:
# This field is autopopulated using internal variables base_url and name using the following format: <base_url>/<name>/request-uri"

require_auth_time: true
subject_type: pairwise

vp_formats:
vc+sd-jwt:
sd-jwt_alg_values:
- ES256
- ES384
kb-jwt_alg_values:
- ES256
- ES384
16 changes: 16 additions & 0 deletions html_linting.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
echo -e '\nHTML linting:'
shopt -s globstar nullglob
for file in `find example -type f | grep html`
do
echo -e "\n$file:"
html_lint.py "$file" | awk -v path="file://$PWD/$file:" '$0=path$0' | sed -e 's/: /:\n\t/';
done

errors=0
for file in "${array[@]}"
do
errors=$((errors + $(html_lint.py "$file" | grep -c 'Error')))
done

echo -e "\nHTML errors: $errors"
if [ "$errors" -gt 0 ]; then exit 1; fi;
24 changes: 7 additions & 17 deletions linting.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,13 @@ autopep8 -r --in-place $SRC
autoflake -r --in-place --remove-unused-variables --expand-star-imports --remove-all-unused-imports $SRC

flake8 $SRC --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 $SRC --max-line-length 120 --count --statistics

# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 $SRC --count --exit-zero --statistics

isort --atomic $SRC

black $SRC

bandit -r -x $SRC/test* $SRC/*

echo -e '\nHTML linting:'
shopt -s globstar nullglob
for file in `find example -type f | grep html`
do
echo -e "\n$file:"
html_lint.py "$file" | awk -v path="file://$PWD/$file:" '$0=path$0' | sed -e 's/: /:\n\t/';
done

errors=0
for file in "${array[@]}"
do
errors=$((errors + $(html_lint.py "$file" | grep -c 'Error')))
done

echo -e "\nHTML errors: $errors"
if [ "$errors" -gt 0 ]; then exit 1; fi;
Loading

0 comments on commit e57606c

Please sign in to comment.