Merge pull request #34 from proconnect-gouv/add-siret-mapping
This commit is contained in:
@@ -7,6 +7,7 @@ and this project adheres to
|
||||
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
- map SAML entity IDs to SIRET (#34)
|
||||
- include ACR claim in ID token only if requested (#32)
|
||||
|
||||
## [1.0.8] - 2025-09-10
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ services:
|
||||
#OIDC_PROVIDER: https://oidc2fer-staging.beta.numerique.gouv.fr
|
||||
OIDC_CLIENT_ID: oidc-test-client
|
||||
OIDC_CLIENT_SECRET: oidc-test-secret
|
||||
OIDC_SCOPES: openid,uid,given_name,usual_name,email
|
||||
OIDC_SCOPES: openid,uid,given_name,usual_name,email,siret
|
||||
extra_hosts:
|
||||
- "oidc2fer.127.0.0.1.nip.io:host-gateway"
|
||||
|
||||
|
||||
@@ -36,6 +36,10 @@ satosa:
|
||||
"token_endpoint_auth_method": "client_secret_post"
|
||||
}
|
||||
}
|
||||
SIRET_MAP: |-
|
||||
{
|
||||
"https://test-idp.federation.renater.fr/idp/shibboleth": "12345678200010"
|
||||
}
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
|
||||
@@ -24,6 +24,94 @@ satosa:
|
||||
|
||||
OIDC_DB_URI: { secretKeyRef: { name: redis.redis.libre.sh, key: url } }
|
||||
|
||||
# As provided by RENATER on 2025-09-19
|
||||
SIRET_MAP: |-
|
||||
{
|
||||
"https://shibboleth.grenoble-inp.fr/idp/shibboleth": "19381912500017",
|
||||
"https://identites.ensea.fr/idp/shibboleth": "19951376300011",
|
||||
"https://idp.ent.dauphine.fr/idp/shibboleth": "19754692200018",
|
||||
"https://idp.univ-lyon2.fr/idp/shibboleth": "19691775100014",
|
||||
"https://shibboleth.insa-rouen.fr/idp/shibboleth": "19760165100023",
|
||||
"https://idp1.univ-fcomte.fr/idp/shibboleth": "19251215000363",
|
||||
"https://idp.univ-tours.fr/idp/shibboleth": "19370800500478",
|
||||
"https://apps.univ-lr.fr/idp/shibboleth": "19170032700015",
|
||||
"https://shib.mines-albi.fr/idp/shibboleth": "19811200500022",
|
||||
"https://federation.upf.pf/idp/shibboleth": "19987001500013",
|
||||
"https://federation.utbm.fr/idp/shibboleth": "19900356700013",
|
||||
"urn:mace:cru.fr:federation:univ-paris1.fr": "19751717000019",
|
||||
"https://idp.sciencespobordeaux.fr/idp/shibboleth": "19330192600039",
|
||||
"https://vip.espci.fr/saml2/idp/metadata.php": "20000068500012",
|
||||
"urn:mace:cru.fr:federation:univ-nantes.fr": "13002974700016",
|
||||
"https://shibboleth.univ-corse.fr/idp/shibboleth": "19202664900264",
|
||||
"https://srv-fii.insa-toulouse.fr/idp/shibboleth": "19310152400018",
|
||||
"urn:mace:cru.fr:federation:univ-rouen.fr": "19761904200017",
|
||||
"https://ident-shib.ensc-rennes.fr/idp/shibboleth": "19350077400016",
|
||||
"urn:mace:cru.fr:federation:unilim.fr": "19870669900321",
|
||||
"https://idp.inha.fr/idp/shibboleth": "19754688000018",
|
||||
"https://federation.unimes.fr/idp/shibboleth": "13000375900029",
|
||||
"urn:mace:cru.fr:federation:univ-rennes1.fr": "13003051300019",
|
||||
"urn:mace:cru.fr:federation:univ-ubs.fr": "19561718800600",
|
||||
"https://idp.univ-orleans.fr/idp/shibboleth": "19450855200016",
|
||||
"https://shibboleth.univ-savoie.fr/idp/shibboleth": "19730858800015",
|
||||
"https://idp.cirad.fr/idp/shibboleth": "33159627000016",
|
||||
"https://sso.ird.fr/idp/shibboleth": "18000602500159",
|
||||
"https://idp.ensma.fr/idp/shibboleth": "19860073600021",
|
||||
"https://idp.renater.fr/idp/shibboleth": "18008947600055",
|
||||
"https://idp.inp-toulouse.fr/idp/shibboleth": "19311381800127",
|
||||
"https://idp.unistra.fr/idp/shibboleth": "13000545700010",
|
||||
"https://idp1.agroparistech.fr/idp/shibboleth": "13000285000134",
|
||||
"https://janus.cnrs.fr/idp": "18008901303720",
|
||||
"https://federation.umontpellier.fr/idp/shibboleth": "13002979600013",
|
||||
"https://idp.sciencespo-lyon.fr/idp/shibboleth": "19690173000024",
|
||||
"https://shibboleth.univ-grenoble-alpes.fr/idp/shibboleth": "13002608100013",
|
||||
"https://idp.bnu.fr/idp/shibboleth": "18004406700015",
|
||||
"https://ruhnu.univ-tlse2.fr/idp/shibboleth": "19311383400017",
|
||||
"https://idp2.amue.fr/idp/shibboleth": "18004312700083",
|
||||
"https://idpv3.univ-amu.fr/idp/shibboleth": "13001533200013",
|
||||
"https://idp-ng.univ-st-etienne.fr/idp/shibboleth": "93850168100010",
|
||||
"https://identities.univ-jfc.fr/idp/prod": "19811201300018",
|
||||
"https://idp3.univ-lorraine.fr/idp/shibboleth": "13001550600012",
|
||||
"https://idp.univ-lemans.fr/idp/shibboleth": "19720916600010",
|
||||
"https://idp.univ-lille.fr/idp/shibboleth": "13002975400012",
|
||||
"https://idp.univ-tln.fr/idp/shibboleth": "19830766200017",
|
||||
"https://idp.uca.fr/idp/shibboleth": "13002806100013",
|
||||
"https://shibboleth3.utt.fr/idp/shibboleth": "19101060200032",
|
||||
"https://idp3.ut-capitole.fr/idp/shibboleth": "19311382600013",
|
||||
"https://idp.imt-atlantique.fr/idp/shibboleth": "18009202500121",
|
||||
"https://shib.univ-lehavre.fr/idp/shibboleth": "19762762300097",
|
||||
"https://idp2.univ-paris8.fr/idp/shibboleth": "19931827000014",
|
||||
"https://shib2.unc.nc/idp/shibboleth": "13000322100012",
|
||||
"https://upnidp2.parisnanterre.fr/idp/shibboleth": "19921204400010",
|
||||
"https://idp.ensfea.fr/idp/shibboleth": "19310143300012",
|
||||
"https://idp.univ-eiffel.fr/idp/shibboleth": "13002612300013",
|
||||
"https://idp.insa-rennes.fr/idp/shibboleth": "19350097200016",
|
||||
"https://idp.univ-tlse3.fr/idp/shibboleth": "93827139200012",
|
||||
"https://idp.universite-paris-saclay.fr/idp": "13002602400054",
|
||||
"https://shibboleth.ens2m.fr/idp/shibboleth": "19250082500026",
|
||||
"https://sso-ciation-saclay.centralesupelec.fr/idp/shibboleth": "13002076100016",
|
||||
"https://federation.ens.psl.eu/idp/shibboleth": "19753459700012",
|
||||
"https://authentification.inrae.fr/saml/metadata/idp": "18007003901803",
|
||||
"https://idp.ensam.eu/idp/shibboleth": "19753472000010",
|
||||
"https://idp1.ens-paris-saclay.fr/idp/shibboleth": "19940607500036",
|
||||
"https://idp2.emse.fr/idp/shibboleth": "18009202500105",
|
||||
"https://idp-septa.onisep.fr/idp/shibboleth": "18004302800653",
|
||||
"https://papangue.vetagro-sup.fr/idp/shibboleth": "13000858400018",
|
||||
"https://multipass.imt-nord-europe.fr/idp/shibboleth": "18009202500139",
|
||||
"https://idp4.unicaen.fr/idp/shibboleth": "19141408500016",
|
||||
"https://sso.bordeaux-inp.fr/idp/shibboleth": "13000635600013",
|
||||
"https://auth.uttop.fr/saml/metadata": "19650048200019",
|
||||
"https://idp.univ-cotedazur.fr/idp/shibboleth": "13002566100013",
|
||||
"https://idp2.brgm.fr/idp/shibboleth": "58205614900120",
|
||||
"https://idp.crous-reims.fr/idp/shibboleth": "18510200100012",
|
||||
"https://idp.univ-avignon.fr/idp/shibboleth": "19840685200204",
|
||||
"https://idp-genci.renater.fr/idp/shibboleth": "49468697500041",
|
||||
"https://auth.sso.vet-alfort.fr/saml/metadata": "19940608300014",
|
||||
"https://idp.univ-perp.fr/idp/shibboleth": "19660437500010",
|
||||
"https://idp.institut-agro.fr/idp": "13000279300011",
|
||||
"https://prod-idp.inria.fr": "18008904700013",
|
||||
"https://idp.ec-nantes.fr/idp/shibboleth": "19440100600011"
|
||||
}
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
host: renater.agentconnect.gouv.fr
|
||||
|
||||
@@ -24,6 +24,11 @@ satosa:
|
||||
|
||||
OIDC_DB_URI: { secretKeyRef: { name: redis.redis.libre.sh, key: url } }
|
||||
|
||||
SIRET_MAP: |-
|
||||
{
|
||||
"https://test-idp.federation.renater.fr/idp/shibboleth": "12345678200010"
|
||||
}
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
host: oidc2fer-staging.beta.numerique.gouv.fr
|
||||
|
||||
@@ -31,3 +31,6 @@ attributes:
|
||||
uid:
|
||||
openid:
|
||||
- uid
|
||||
siret:
|
||||
openid:
|
||||
- siret
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
from .entity_id_to_siret_mapper import EntityIdToSiretMapper
|
||||
@@ -0,0 +1,23 @@
|
||||
import json
|
||||
import logging
|
||||
|
||||
from satosa.micro_services.base import ResponseMicroService
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EntityIdToSiretMapper(ResponseMicroService):
|
||||
def __init__(self, config, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.attribute = config.get("attribute", "siret")
|
||||
self.mapping = json.loads(config.get("mapping_json", "{}"))
|
||||
|
||||
def process(self, context, data):
|
||||
entity_id = data.auth_info.issuer
|
||||
if entity_id in self.mapping:
|
||||
siret = self.mapping[entity_id]
|
||||
logger.info("Mapping entity ID %s to SIRET %s", entity_id, siret)
|
||||
data.attributes[self.attribute] = siret
|
||||
else:
|
||||
logger.warning("No SIRET mapping found for entity ID %s", entity_id)
|
||||
return super().process(context, data)
|
||||
@@ -43,6 +43,7 @@ config:
|
||||
- uid
|
||||
- given_name
|
||||
- usual_name
|
||||
- siret
|
||||
|
||||
# Set code/token lifetimes as short as possible
|
||||
authorization_code_lifetime: 60
|
||||
@@ -56,3 +57,5 @@ config:
|
||||
- given_name
|
||||
usual_name:
|
||||
- usual_name
|
||||
siret:
|
||||
- siret
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
module: oidc2fer.attribute_generators.EntityIdToSiretMapper
|
||||
name: EntityIdToSiretMapper
|
||||
config:
|
||||
attribute: siret
|
||||
mapping_json: !ENV SIRET_MAP
|
||||
@@ -17,6 +17,7 @@ MICRO_SERVICES:
|
||||
- plugins/microservices/primary_identifier.yaml
|
||||
- plugins/microservices/static_attributes.yaml
|
||||
- plugins/microservices/attribute_processor.yaml
|
||||
- plugins/microservices/siret_mapping.yaml
|
||||
LOGGING:
|
||||
# All the logging configuration is done in the Gunicorn config, this is just
|
||||
# here to avoid overwriting it with the default SATOSA config
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import json
|
||||
|
||||
from satosa.context import Context
|
||||
from satosa.internal import AuthenticationInformation, InternalData
|
||||
|
||||
from oidc2fer.attribute_generators import EntityIdToSiretMapper
|
||||
|
||||
|
||||
class TestEntityIdToSiretMapper:
|
||||
def create_mapper(self):
|
||||
mapper = EntityIdToSiretMapper(
|
||||
config={
|
||||
"attribute": "siret",
|
||||
"mapping_json": json.dumps(
|
||||
{
|
||||
"https://idp.example.fr": "12345678200010",
|
||||
}
|
||||
),
|
||||
},
|
||||
name="siret_mapper",
|
||||
base_url="https://satosa.example.com",
|
||||
)
|
||||
mapper.next = lambda ctx, data: data
|
||||
return mapper
|
||||
|
||||
def test_sets_siret_for_known_entityid(self):
|
||||
mapper = self.create_mapper()
|
||||
resp = InternalData(
|
||||
auth_info=AuthenticationInformation(issuer="https://idp.example.fr")
|
||||
)
|
||||
ctx = Context()
|
||||
mapper.process(ctx, resp)
|
||||
assert resp.attributes["siret"] == "12345678200010"
|
||||
|
||||
def test_does_not_set_siret_for_unknown_entityid(self):
|
||||
mapper = self.create_mapper()
|
||||
resp = InternalData(
|
||||
auth_info=AuthenticationInformation(issuer="https://unknown.example.fr")
|
||||
)
|
||||
ctx = Context()
|
||||
mapper.process(ctx, resp)
|
||||
assert "siret" not in resp.attributes
|
||||
@@ -49,6 +49,7 @@ def oidc_to_renater(
|
||||
"email": expected_email,
|
||||
"given_name": expected_given_name,
|
||||
"usual_name": expected_usual_name,
|
||||
"siret": "12345678200010",
|
||||
}.items() <= userinfo.items()
|
||||
return id_token
|
||||
|
||||
@@ -102,6 +103,7 @@ def pro_connect_to_renater(
|
||||
"email": expected_email,
|
||||
"given_name": expected_given_name,
|
||||
"usual_name": expected_usual_name,
|
||||
"siret": "12345678200010",
|
||||
}.items() <= result.items()
|
||||
return result
|
||||
|
||||
|
||||
Reference in New Issue
Block a user