From 4a7d5c7ead466c348893357155cad62e11b621b3 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Wed, 17 Sep 2014 22:55:48 +0200 Subject: [PATCH] Modify federation storage so that we can store federation relative to the provider model If the content of name_id_qualifier or name_id_sp_name_qualifier is equals to the issuer or service provider entity ID then we store a sentinel value instead, meaning 'same as provider entity ID'. If we change the provider entity, all federations are still correct. --- src/authentic2/idp/saml/saml2_endpoints.py | 9 +++++++- src/authentic2/saml/common.py | 16 +++++++++++++-- .../migrations/0002_ease_federation_migration.py | 24 ++++++++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 src/authentic2/saml/migrations/0002_ease_federation_migration.py diff --git a/src/authentic2/idp/saml/saml2_endpoints.py b/src/authentic2/idp/saml/saml2_endpoints.py index afdc680..f644ba1 100644 --- a/src/authentic2/idp/saml/saml2_endpoints.py +++ b/src/authentic2/idp/saml/saml2_endpoints.py @@ -61,17 +61,17 @@ from authentic2.saml.common import redirect_next, asynchronous_bindings, \ AUTHENTIC_STATUS_CODE_MISSING_NAMEID, \ AUTHENTIC_STATUS_CODE_MISSING_SESSION_INDEX, \ AUTHENTIC_STATUS_CODE_UNKNOWN_SESSION, \ AUTHENTIC_STATUS_CODE_INTERNAL_SERVER_ERROR, \ AUTHENTIC_STATUS_CODE_UNAUTHORIZED, \ send_soap_request, get_saml2_query_request, \ get_saml2_request_message_async_binding, create_saml2_server, \ get_saml2_metadata, get_sp_options_policy, \ - get_entity_id + get_entity_id, AUTHENTIC_SAME_ID_SENTINEL import authentic2.saml.saml2utils as saml2utils from common import kill_django_sessions from authentic2.constants import NONCE_FIELD_NAME from authentic2.idp import signals as idp_signals # from authentic2.idp.models import * from authentic2.utils import (make_url, get_backends as get_idp_backends, @@ -277,16 +277,17 @@ def saml2_add_attribute_values(assertion, attributes): logger.debug("assertion after processing " "%s" % assertion.dump()) def build_assertion(request, login, nid_format='transient', attributes=None): """After a successfully validated authentication request, build an authentication assertion """ + entity_id = get_entity_id(request, reverse(metadata)) now = datetime.datetime.utcnow() logger.info("building assertion at %s" % str(now)) logger.debug('named Id format is %s' % nid_format) # 1 minute ago notBefore = now - datetime.timedelta(0, app_settings.SECONDS_TOLERANCE) # 1 minute in the future notOnOrAfter = now + datetime.timedelta(0, app_settings.SECONDS_TOLERANCE) ssl = 'HTTPS' in request.environ @@ -339,16 +340,22 @@ def build_assertion(request, login, nid_format='transient', attributes=None): logger.debug("fill assertion") fill_assertion(request, login.request, assertion, login.remoteProviderId, nid_format) # Save federation and new session if nid_format == 'persistent': logger.debug("nameID persistent, get or create " "federation") kwargs = nameid2kwargs(login.assertion.subject.nameID) + # if qualifiers can be inferred from providers entityID replace them by + # placeholders + if kwargs.get('name_id_qualifier') == entity_id: + kwargs['name_id_qualifier'] = AUTHENTIC_SAME_ID_SENTINEL + if kwargs.get('name_id_sp_name_qualifier') == login.remoteProviderId: + kwargs['name_id_sp_name_qualifier'] = AUTHENTIC_SAME_ID_SENTINEL service_provider = LibertyServiceProvider.objects \ .get(liberty_provider__entity_id=login.remoteProviderId) federation, new = LibertyFederation.objects.get_or_create( sp=service_provider, user=request.user, **kwargs) if new: logger.info("nameID persistent, new federation") federation.save() diff --git a/src/authentic2/saml/common.py b/src/authentic2/saml/common.py index 41e1f11..a30f44b 100644 --- a/src/authentic2/saml/common.py +++ b/src/authentic2/saml/common.py @@ -25,16 +25,17 @@ from authentic2.saml.models import LibertyFederation, LibertyProvider, \ LIBERTY_SESSION_DUMP_KIND_IDP from authentic2.saml import models from authentic2.saml import saml2utils from authentic2.http_utils import get_url from .. import nonce AUTHENTIC_STATUS_CODE_NS = "http://authentic.entrouvert.org/status_code/" +AUTHENTIC_SAME_ID_SENTINEL = 'urn:authentic.entrouvert.org:same-as-provider-entity-id' AUTHENTIC_STATUS_CODE_UNKNOWN_PROVIDER = AUTHENTIC_STATUS_CODE_NS + \ "UnknownProvider" AUTHENTIC_STATUS_CODE_MISSING_NAMEID= AUTHENTIC_STATUS_CODE_NS + \ "MissingNameID" AUTHENTIC_STATUS_CODE_MISSING_SESSION_INDEX = AUTHENTIC_STATUS_CODE_NS + \ "MissingSessionIndex" AUTHENTIC_STATUS_CODE_UNKNOWN_SESSION = AUTHENTIC_STATUS_CODE_NS + \ "UnknownSession" @@ -229,25 +230,36 @@ MIDDLE_IDENTITY_DUMP = '''