'Map a federated user to a user.
:param idp_id: identity provider id
:param protocol_id: protocol id
:param unique_id: unique id for the user within the IdP
:param display_name: user\'s display name
:returns: dictionary of the mapped User entity'

@MEMOIZE
def shadow_federated_user(self, idp_id, protocol_id, unique_id, display_name):

    user_dict = {}
    try:
        self.shadow_users_api.update_federated_user_display_name(idp_id, protocol_id, unique_id, display_name)
        user_dict = self.shadow_users_api.get_federated_user(idp_id, protocol_id, unique_id)
    except exception.UserNotFound:
        idp = self.federation_api.get_idp(idp_id)
        federated_dict = {'idp_id': idp_id, 'protocol_id': protocol_id, 'unique_id': unique_id, 'display_name': display_name}
        user_dict = self.shadow_users_api.create_federated_user(idp['domain_id'], federated_dict)
    self.shadow_users_api.set_last_active_at(user_dict['id'])
    return user_dict
