diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/DelegatedSurrogateAuthenticationPostProcessor.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/DelegatedSurrogateAuthenticationPostProcessor.java
index 9f7f5db104730ab9cdf3d28993c56f96800f7ac1..bfdc73ae9a22bf0728ab70a73237032eb4fe0a23 100644
--- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/DelegatedSurrogateAuthenticationPostProcessor.java
+++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/DelegatedSurrogateAuthenticationPostProcessor.java
@@ -45,11 +45,12 @@ import org.apereo.cas.authentication.principal.ClientCredential;
 import org.apereo.cas.authentication.surrogate.SurrogateAuthenticationService;
 import org.apereo.cas.services.ServicesManager;
 import org.apereo.cas.web.support.WebUtils;
+import org.pac4j.core.context.JEEContext;
+import org.pac4j.core.context.session.SessionStore;
 import org.springframework.context.ApplicationEventPublisher;
-import org.springframework.webflow.execution.RequestContext;
 import org.springframework.webflow.execution.RequestContextHolder;
 
-import javax.servlet.http.HttpServletRequest;
+import lombok.val;
 
 /**
  * Post-processor which also handles the surrogation in the authentication delegation.
@@ -60,28 +61,34 @@ public class DelegatedSurrogateAuthenticationPostProcessor extends SurrogateAuth
 
     private static final VitamUILogger LOGGER = VitamUILoggerFactory.getInstance(DelegatedSurrogateAuthenticationPostProcessor.class);
 
+    private final SessionStore sessionStore;
+
     public DelegatedSurrogateAuthenticationPostProcessor(final SurrogateAuthenticationService surrogateAuthenticationService,
                                                          final ServicesManager servicesManager, final ApplicationEventPublisher applicationEventPublisher,
                                                          final AuditableExecution registeredServiceAccessStrategyEnforcer,
-                                                         final AuditableExecution surrogateEligibilityAuditableExecution) {
+                                                         final AuditableExecution surrogateEligibilityAuditableExecution,
+                                                         final SessionStore sessionStore) {
         super(surrogateAuthenticationService, servicesManager, applicationEventPublisher, registeredServiceAccessStrategyEnforcer,
             surrogateEligibilityAuditableExecution);
+        this.sessionStore = sessionStore;
     }
 
     @Override
     public void process(final AuthenticationBuilder builder, final AuthenticationTransaction transaction) throws AuthenticationException {
 
-        final Credential credential = transaction.getPrimaryCredential().get();
+        val credential = transaction.getPrimaryCredential().get();
         if (credential instanceof ClientCredential) {
-            final ClientCredential clientCredential = (ClientCredential) credential;
-            final RequestContext requestContext = RequestContextHolder.getRequestContext();
-            final HttpServletRequest request = WebUtils.getHttpServletRequestFromExternalWebflowContext(requestContext);
-            final String surrogate = (String) request.getAttribute(Constants.SURROGATE);
-            if (surrogate != null) {
-                LOGGER.debug("surrogate: {} found after authentication delegation -> overriding credential", surrogate);
-                final SurrogateUsernamePasswordCredential newCredential = new SurrogateUsernamePasswordCredential();
+            val clientCredential = (ClientCredential) credential;
+            val requestContext = RequestContextHolder.getRequestContext();
+            val request = WebUtils.getHttpServletRequestFromExternalWebflowContext(requestContext);
+            val response = WebUtils.getHttpServletResponseFromExternalWebflowContext(requestContext);
+            val webContext = new JEEContext(request, response, sessionStore);
+            val surrogateInSession = sessionStore.get(webContext, Constants.SURROGATE).orElse(null);
+            if (surrogateInSession != null) {
+                LOGGER.debug("surrogate: {} found after authentication delegation -> overriding credential", surrogateInSession);
+                val newCredential = new SurrogateUsernamePasswordCredential();
                 newCredential.setUsername(clientCredential.getUserProfile().getId());
-                newCredential.setSurrogateUsername(surrogate);
+                newCredential.setSurrogateUsername((String) surrogateInSession);
                 WebUtils.putCredential(requestContext, newCredential);
 
                 final AuthenticationTransaction newTransaction = DefaultAuthenticationTransaction.of(transaction.getService(), newCredential);
@@ -90,7 +97,6 @@ public class DelegatedSurrogateAuthenticationPostProcessor extends SurrogateAuth
                 return;
             }
         } else {
-
             super.process(builder, transaction);
         }
     }
diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/IamSurrogateRestAuthenticationService.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/IamSurrogateRestAuthenticationService.java
index 5c0c7369ccb05daa3193c3a0a7af1bccda626a18..072a03748b0a42342ce3d6cf3dac0ecbe9e22ba2 100644
--- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/IamSurrogateRestAuthenticationService.java
+++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/IamSurrogateRestAuthenticationService.java
@@ -41,10 +41,7 @@ import fr.gouv.vitamui.commons.api.exception.VitamUIException;
 import fr.gouv.vitamui.commons.api.logger.VitamUILogger;
 import fr.gouv.vitamui.commons.api.logger.VitamUILoggerFactory;
 import fr.gouv.vitamui.iam.external.client.CasExternalRestClient;
-import fr.gouv.vitamui.iam.common.dto.SubrogationDto;
 import fr.gouv.vitamui.iam.common.enums.SubrogationStatusEnum;
-import lombok.Getter;
-import lombok.Setter;
 import org.apereo.cas.authentication.principal.Principal;
 import org.apereo.cas.authentication.principal.Service;
 import org.apereo.cas.authentication.surrogate.BaseSurrogateAuthenticationService;
@@ -52,13 +49,13 @@ import org.apereo.cas.services.ServicesManager;
 
 import java.util.List;
 
+import lombok.val;
+
 /**
  * Specific surrogate REST based on the IAM API.
  *
  *
  */
-@Getter
-@Setter
 public class IamSurrogateRestAuthenticationService extends BaseSurrogateAuthenticationService {
 
     private static final VitamUILogger LOGGER = VitamUILoggerFactory.getInstance(IamSurrogateRestAuthenticationService.class);
@@ -76,10 +73,10 @@ public class IamSurrogateRestAuthenticationService extends BaseSurrogateAuthenti
 
     @Override
     public boolean canAuthenticateAsInternal(final String surrogate, final Principal principal, final Service service) {
-        final String id = principal.getId();
+        val id = (String) principal.getAttributes().get(UserPrincipalResolver.SUPER_USER_ID_ATTRIBUTE).get(0);
         boolean canAuthenticate = false;
         try {
-            final List<SubrogationDto> subrogations = casExternalRestClient.getSubrogationsBySuperUserId(utils.buildContext(id), id);
+            val subrogations = casExternalRestClient.getSubrogationsBySuperUserId(utils.buildContext(id), id);
             canAuthenticate = subrogations
                 .stream()
                 .filter(s -> s.getStatus() == SubrogationStatusEnum.ACCEPTED)
diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/SurrogatedUserPrincipalFactory.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/SurrogatedUserPrincipalFactory.java
deleted file mode 100644
index d5921efe6dea388b94a0864d4e3a4ad63e0ddcf1..0000000000000000000000000000000000000000
--- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/SurrogatedUserPrincipalFactory.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020)
- * and the signatories of the "VITAM - Accord du Contributeur" agreement.
- *
- * contact@programmevitam.fr
- *
- * This software is a computer program whose purpose is to implement
- * implement a digital archiving front-office system for the secure and
- * efficient high volumetry VITAM solution.
- *
- * This software is governed by the CeCILL-C license under French law and
- * abiding by the rules of distribution of free software.  You can  use,
- * modify and/ or redistribute the software under the terms of the CeCILL-C
- * license as circulated by CEA, CNRS and INRIA at the following URL
- * "http://www.cecill.info".
- *
- * As a counterpart to the access to the source code and  rights to copy,
- * modify and redistribute granted by the license, users are provided only
- * with a limited warranty  and the software's author,  the holder of the
- * economic rights,  and the successive licensors  have only  limited
- * liability.
- *
- * In this respect, the user's attention is drawn to the risks associated
- * with loading,  using,  modifying and/or developing or reproducing the
- * software by the user in light of its specific status of free software,
- * that may mean  that it is complicated to manipulate,  and  that  also
- * therefore means  that it is reserved for developers  and  experienced
- * professionals having in-depth computer knowledge. Users are therefore
- * encouraged to load and test the software's suitability as regards their
- * requirements in conditions enabling the security of their systems and/or
- * data to be ensured and,  more generally, to use and operate it in the
- * same conditions as regards security.
- *
- * The fact that you are presently reading this means that you have had
- * knowledge of the CeCILL-C license and that you accept its terms.
- */
-package fr.gouv.vitamui.cas.authentication;
-
-import fr.gouv.vitamui.commons.api.exception.VitamUIException;
-import fr.gouv.vitamui.commons.api.logger.VitamUILogger;
-import fr.gouv.vitamui.commons.api.logger.VitamUILoggerFactory;
-import lombok.RequiredArgsConstructor;
-import org.apereo.cas.authentication.principal.Principal;
-import org.apereo.cas.authentication.principal.PrincipalFactory;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Principal factory used for surrogation to find the real user and its profile.
- *
- *
- */
-@RequiredArgsConstructor
-public class SurrogatedUserPrincipalFactory implements PrincipalFactory {
-
-    private static final VitamUILogger LOGGER = VitamUILoggerFactory.getInstance(SurrogatedUserPrincipalFactory.class);
-
-    private final UserPrincipalResolver resolver;
-
-    @Override
-    public Principal createPrincipal(final String username) {
-        throw new UnsupportedOperationException("This method cannot be used");
-    }
-
-    @Override
-    public Principal createPrincipal(final String id, final Map<String, List<Object>> attributes) {
-        LOGGER.debug("Creating username: {}", id);
-        try {
-            final Principal principal = resolver.resolve(id, new HashMap<>());
-            LOGGER.debug("principal: {}", principal);
-            return principal;
-
-        } catch (final VitamUIException e) {
-            LOGGER.error("Cannot get surrogated user: {}", id, e);
-        }
-        return null;
-    }
-}
diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/UserAuthenticationHandler.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/UserAuthenticationHandler.java
index 18cf370d8c7a602b64f7c61aa31924d3e28915e2..300b951813c5ee9b1723898a3af6e8f247a87d62 100644
--- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/UserAuthenticationHandler.java
+++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/UserAuthenticationHandler.java
@@ -63,15 +63,13 @@ import fr.gouv.vitamui.cas.util.Utils;
 import fr.gouv.vitamui.commons.api.exception.VitamUIException;
 import fr.gouv.vitamui.commons.api.exception.InvalidAuthenticationException;
 import fr.gouv.vitamui.commons.api.exception.TooManyRequestsException;
-import fr.gouv.vitamui.commons.rest.client.ExternalHttpContext;
 import fr.gouv.vitamui.iam.external.client.CasExternalRestClient;
 import fr.gouv.vitamui.commons.api.domain.UserDto;
 import fr.gouv.vitamui.commons.api.enums.UserStatusEnum;
-import org.springframework.webflow.context.ExternalContext;
-import org.springframework.webflow.core.collection.MutableAttributeMap;
-import org.springframework.webflow.execution.RequestContext;
 import org.springframework.webflow.execution.RequestContextHolder;
 
+import lombok.val;
+
 /**
  * Authentication handler to check the username/password on the IAM API.
  *
@@ -99,19 +97,19 @@ public class UserAuthenticationHandler extends AbstractUsernamePasswordAuthentic
     protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential transformedCredential,
                                                                                         final String originalPassword) throws GeneralSecurityException, PreventedException {
 
-        final String username = transformedCredential.getUsername().toLowerCase();
-        final RequestContext requestContext = RequestContextHolder.getRequestContext();
+        val username = transformedCredential.getUsername().toLowerCase();
+        val requestContext = RequestContextHolder.getRequestContext();
         String surrogate = null;
         String ip = null;
         if (requestContext != null) {
-            final MutableAttributeMap<Object> flow = requestContext.getFlowScope();
+            val flow = requestContext.getFlowScope();
             if (flow != null) {
-                final Object credential = flow.get("credential");
+                val credential = flow.get("credential");
                 if (credential instanceof SurrogateUsernamePasswordCredential) {
                     surrogate = ((SurrogateUsernamePasswordCredential) credential).getSurrogateUsername();
                 }
             }
-            final ExternalContext externalContext = requestContext.getExternalContext();
+            val externalContext = requestContext.getExternalContext();
             if (externalContext != null) {
                 ip = ((HttpServletRequest) externalContext.getNativeRequest()).getHeader(ipHeaderName);
             }
@@ -119,9 +117,9 @@ public class UserAuthenticationHandler extends AbstractUsernamePasswordAuthentic
 
         LOGGER.debug("Authenticating username: {} / surrogate: {} / IP: {}", username, surrogate, ip);
 
-        final ExternalHttpContext context = utils.buildContext(username);
+        val context = utils.buildContext(username);
         try {
-            final UserDto user = casExternalRestClient.login(context, username, originalPassword, surrogate, ip);
+            val user = casExternalRestClient.login(context, username, originalPassword, surrogate, ip);
             if (user != null) {
                 if (mustChangePassword(user)) {
                     LOGGER.info("Password expired for: {}", username);
@@ -158,7 +156,7 @@ public class UserAuthenticationHandler extends AbstractUsernamePasswordAuthentic
     }
 
     protected boolean mustChangePassword(final UserDto user) {
-        final OffsetDateTime pwdExpirationDate = user.getPasswordExpirationDate();
+        val pwdExpirationDate = user.getPasswordExpirationDate();
         return (pwdExpirationDate == null || pwdExpirationDate.isBefore(OffsetDateTime.now()));
     }
 }
diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/UserPrincipalResolver.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/UserPrincipalResolver.java
index 3dc60b13b08a524c9e4de82a6b6f136dd7249d66..0aa50da217d4e5f49bcab6b12c121adc1f41b4da 100644
--- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/UserPrincipalResolver.java
+++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/UserPrincipalResolver.java
@@ -71,8 +71,6 @@ import static fr.gouv.vitamui.commons.api.CommonConstants.USER_ID_ATTRIBUTE;
 
 import java.util.*;
 
-import javax.servlet.http.HttpServletRequest;
-
 import lombok.RequiredArgsConstructor;
 import org.apereo.cas.authentication.AuthenticationHandler;
 import org.apereo.cas.authentication.Credential;
@@ -84,8 +82,8 @@ import org.apereo.cas.authentication.principal.PrincipalFactory;
 import org.apereo.cas.authentication.principal.PrincipalResolver;
 import org.apereo.cas.web.support.WebUtils;
 import org.apereo.services.persondir.IPersonAttributeDao;
-import org.springframework.webflow.core.collection.MutableAttributeMap;
-import org.springframework.webflow.execution.RequestContext;
+import org.pac4j.core.context.JEEContext;
+import org.pac4j.core.context.session.SessionStore;
 import org.springframework.webflow.execution.RequestContextHolder;
 
 import fr.gouv.vitamui.cas.util.Constants;
@@ -99,6 +97,8 @@ import fr.gouv.vitamui.commons.api.utils.CasJsonWrapper;
 import fr.gouv.vitamui.commons.security.client.dto.AuthUserDto;
 import fr.gouv.vitamui.iam.external.client.CasExternalRestClient;
 
+import lombok.val;
+
 /**
  * Resolver to retrieve the user.
  *
@@ -107,9 +107,9 @@ import fr.gouv.vitamui.iam.external.client.CasExternalRestClient;
 @RequiredArgsConstructor
 public class UserPrincipalResolver implements PrincipalResolver {
 
-    private static final VitamUILogger LOGGER = VitamUILoggerFactory.getInstance(UserPrincipalResolver.class);
+    public static final String SUPER_USER_ID_ATTRIBUTE = "superUserId";
 
-    private final boolean finalSurrogationCall;
+    private static final VitamUILogger LOGGER = VitamUILoggerFactory.getInstance(UserPrincipalResolver.class);
 
     private final PrincipalFactory principalFactory;
 
@@ -117,55 +117,49 @@ public class UserPrincipalResolver implements PrincipalResolver {
 
     private final Utils utils;
 
+    private final SessionStore sessionStore;
+
     @Override
     public Principal resolve(final Credential credential, final Optional<Principal> principal, final Optional<AuthenticationHandler> handler) {
-        return resolve(principal.get().getId(), principal.get().getAttributes());
-    }
 
-    public Principal resolve(final String username, final Map<String, List<Object>> oldAttributes) {
-        String superUsername = null;
-        final RequestContext requestContext = RequestContextHolder.getRequestContext();
-        if (requestContext != null) {
-            final MutableAttributeMap<Object> flow = requestContext.getFlowScope();
-            // try to find the super user from the regular surrogation flow or in an authentication delegation
-            if (flow != null) {
-                final Object credential = flow.get("credential");
-                if (credential instanceof SurrogateUsernamePasswordCredential) {
-                    superUsername = ((SurrogateUsernamePasswordCredential) credential).getUsername();
-                }
-                else if (credential instanceof ClientCredential) {
-                    final HttpServletRequest request = WebUtils.getHttpServletRequestFromExternalWebflowContext(requestContext);
-                    final boolean hasSurrogateInRequest = request.getAttribute(Constants.SURROGATE) != null;
-                    if (hasSurrogateInRequest) {
-                        superUsername = ((ClientCredential) credential).getUserProfile().getId();
-                    }
-                }
+        val userId = principal.get().getId();
+        val requestContext = RequestContextHolder.getRequestContext();
+
+        boolean surrogationCall;
+        String username;
+        String superUsername;
+        if (credential instanceof SurrogateUsernamePasswordCredential) {
+            val surrogationCredential = (SurrogateUsernamePasswordCredential) credential;
+            username = surrogationCredential.getSurrogateUsername();
+            superUsername = surrogationCredential.getUsername();
+            surrogationCall = true;
+        } else if (credential instanceof UsernamePasswordCredential) {
+            username = userId;
+            superUsername = null;
+            surrogationCall = false;
+        } else { // ClientCredential
+            val request = WebUtils.getHttpServletRequestFromExternalWebflowContext(requestContext);
+            val response = WebUtils.getHttpServletResponseFromExternalWebflowContext(requestContext);
+            val webContext = new JEEContext(request, response, sessionStore);
+            val surrogateInSession = sessionStore.get(webContext, Constants.SURROGATE).orElse(null);
+            if (surrogateInSession != null) {
+                username = (String) surrogateInSession;
+                superUsername = userId;
+                surrogationCall = true;
+            } else {
+                username = userId;
+                superUsername = null;
+                surrogationCall = false;
             }
         }
 
-        boolean authToken = true;
-        // this is not called by the surrogation principal factory, but the surrogation is in progress, it will be called again
-        // spare the extra info on this call by not requesting the auth token
-        if (!finalSurrogationCall && superUsername != null) {
-            LOGGER.debug("No final surrogation call but surrogation in progress -> no auth token");
-            authToken = false;
-        }
-
-        LOGGER.debug("Resolving username: {} | superUsername: {} | authToken: {} | finalSurrogationCall: {}", username, superUsername, authToken,
-                finalSurrogationCall);
+        LOGGER.debug("Resolving username: {} | superUsername: {} | surrogationCall: {}", username, superUsername, surrogationCall);
 
-        String embedded = null;
-        if (authToken) {
-            embedded = AUTH_TOKEN_PARAMETER;
-            if (finalSurrogationCall) {
-                embedded += "," + SURROGATION_PARAMETER;
-            }
-            else if (requestContext == null) {
-                embedded += "," + API_PARAMETER;
-            }
-        }
-        else if (finalSurrogationCall) {
-            embedded = SURROGATION_PARAMETER;
+        String embedded = AUTH_TOKEN_PARAMETER;
+        if (surrogationCall) {
+            embedded += "," + SURROGATION_PARAMETER;
+        } else if (requestContext == null) {
+            embedded += "," + API_PARAMETER;
         }
         LOGGER.debug("Computed embedded: {}", embedded);
         final UserDto user = casExternalRestClient.getUserByEmail(utils.buildContext(username), username, Optional.ofNullable(embedded));
@@ -177,7 +171,7 @@ public class UserPrincipalResolver implements PrincipalResolver {
             LOGGER.debug("User cannot login: {} - User {}", username, user.toString());
             return null;
         }
-        final Map<String, List<Object>> attributes = new HashMap<>();
+        val attributes = new HashMap<String, List<Object>>();
         attributes.put(USER_ID_ATTRIBUTE, Collections.singletonList(user.getId()));
         attributes.put(CUSTOMER_ID_ATTRIBUTE, Collections.singletonList(user.getCustomerId()));
         attributes.put(EMAIL_ATTRIBUTE, Collections.singletonList(username));
@@ -198,11 +192,11 @@ public class UserPrincipalResolver implements PrincipalResolver {
         attributes.put(PASSWORD_EXPIRATION_DATE_ATTRIBUTE, Collections.singletonList(user.getPasswordExpirationDate()));
         attributes.put(GROUP_ID_ATTRIBUTE, Collections.singletonList(user.getGroupId()));
         attributes.put(ADDRESS_ATTRIBUTE, Collections.singletonList(new CasJsonWrapper(user.getAddress())));
-        if (finalSurrogationCall) {
+        if (surrogationCall) {
             attributes.put(SUPER_USER_ATTRIBUTE, Collections.singletonList(superUsername));
             final UserDto superUser = casExternalRestClient.getUserByEmail(utils.buildContext(superUsername), superUsername, Optional.empty());
             attributes.put(SUPER_USER_IDENTIFIER_ATTRIBUTE, Collections.singletonList(superUser.getIdentifier()));
-
+            attributes.put(SUPER_USER_ID_ATTRIBUTE, Collections.singletonList(superUser.getId()));
         }
         if (user instanceof AuthUserDto) {
             final AuthUserDto authUser = (AuthUserDto) user;
@@ -222,7 +216,8 @@ public class UserPrincipalResolver implements PrincipalResolver {
 
     @Override
     public boolean supports(final Credential credential) {
-        return credential instanceof UsernamePasswordCredential || credential instanceof ClientCredential;
+        return credential instanceof UsernamePasswordCredential || credential instanceof ClientCredential
+            || credential instanceof SurrogateUsernamePasswordCredential;
     }
 
     @Override
diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/config/AppConfig.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/config/AppConfig.java
index f20fec9411bc2d8e89a1e1ead674baac068c70f1..bbc58298e6f54e7a4a5ce33b1387cc120adc91e5 100644
--- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/config/AppConfig.java
+++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/config/AppConfig.java
@@ -36,12 +36,11 @@
  */
 package fr.gouv.vitamui.cas.config;
 
+import fr.gouv.vitamui.cas.authentication.DelegatedSurrogateAuthenticationPostProcessor;
 import org.apereo.cas.audit.AuditableExecution;
-import org.apereo.cas.authentication.AuthenticationEventExecutionPlanConfigurer;
-import org.apereo.cas.authentication.AuthenticationHandler;
-import org.apereo.cas.authentication.AuthenticationMetaDataPopulator;
-import org.apereo.cas.authentication.AuthenticationPostProcessor;
+import org.apereo.cas.authentication.*;
 import org.apereo.cas.authentication.principal.PrincipalFactory;
+import org.apereo.cas.authentication.principal.PrincipalResolver;
 import org.apereo.cas.authentication.surrogate.SurrogateAuthenticationService;
 import org.apereo.cas.configuration.CasConfigurationProperties;
 import org.apereo.cas.services.ServicesManager;
@@ -50,6 +49,7 @@ import org.apereo.cas.ticket.accesstoken.OAuth20AccessTokenFactory;
 import org.apereo.cas.ticket.accesstoken.OAuth20DefaultAccessToken;
 import org.apereo.cas.token.JwtBuilder;
 import org.apereo.cas.util.crypto.CipherExecutor;
+import org.pac4j.core.context.session.SessionStore;
 import org.springframework.beans.factory.ObjectProvider;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
@@ -63,8 +63,6 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
 import org.springframework.core.Ordered;
 
-import fr.gouv.vitamui.cas.authentication.DelegatedSurrogateAuthenticationPostProcessor;
-import fr.gouv.vitamui.cas.authentication.SurrogatedUserPrincipalFactory;
 import fr.gouv.vitamui.cas.authentication.UserAuthenticationHandler;
 import fr.gouv.vitamui.cas.authentication.UserPrincipalResolver;
 import fr.gouv.vitamui.cas.provider.ProvidersService;
@@ -168,34 +166,40 @@ public class AppConfig extends BaseTicketCatalogConfigurer {
     @Value("${vitamui.cas.identity}")
     private String casIdentity;
 
+    @Autowired
+    @Qualifier("delegatedClientDistributedSessionStore")
+    private SessionStore delegatedClientDistributedSessionStore;
+
     @Bean
     public UserAuthenticationHandler userAuthenticationHandler() {
         return new UserAuthenticationHandler(servicesManager, principalFactory, casRestClient(), utils(), ipHeaderName);
     }
 
     @Bean
-    public UserPrincipalResolver userResolver() {
-        return new UserPrincipalResolver(false, principalFactory, casRestClient(), utils());
-    }
-
-    @Bean
-    public UserPrincipalResolver userResolverForSurrogation() {
-        return new UserPrincipalResolver(true, principalFactory, casRestClient(), utils());
+    @RefreshScope
+    public PrincipalResolver surrogatePrincipalResolver() {
+        return new UserPrincipalResolver(principalFactory, casRestClient(), utils(), delegatedClientDistributedSessionStore);
     }
 
     @Bean
     public AuthenticationEventExecutionPlanConfigurer registerInternalHandler() {
-        return plan -> plan.registerAuthenticationHandlerWithPrincipalResolver(userAuthenticationHandler(), userResolver());
+        return plan -> plan.registerAuthenticationHandlerWithPrincipalResolver(userAuthenticationHandler(), surrogatePrincipalResolver());
     }
 
     @Bean
     public AuthenticationEventExecutionPlanConfigurer pac4jAuthenticationEventExecutionPlanConfigurer() {
         return plan -> {
-            plan.registerAuthenticationHandlerWithPrincipalResolver(clientAuthenticationHandler, userResolver());
+            plan.registerAuthenticationHandlerWithPrincipalResolver(clientAuthenticationHandler, surrogatePrincipalResolver());
             plan.registerAuthenticationMetadataPopulator(clientAuthenticationMetaDataPopulator);
         };
     }
 
+    @Bean
+    public AuthenticationPostProcessor surrogateAuthenticationPostProcessor() {
+        return new DelegatedSurrogateAuthenticationPostProcessor(surrogateAuthenticationService, servicesManager, eventPublisher,
+            registeredServiceAccessStrategyEnforcer, surrogateEligibilityAuditableExecution, delegatedClientDistributedSessionStore);
+    }
+
     @Bean
     public IamExternalRestClientFactory iamRestClientFactory() {
         LOGGER.debug("Iam client factory: {}", iamClientProperties);
@@ -222,17 +226,6 @@ public class AppConfig extends BaseTicketCatalogConfigurer {
         return new Saml2ClientBuilder();
     }
 
-    @Bean
-    public PrincipalFactory surrogatePrincipalFactory() {
-        return new SurrogatedUserPrincipalFactory(userResolverForSurrogation());
-    }
-
-    @Bean
-    public AuthenticationPostProcessor surrogateAuthenticationPostProcessor() {
-        return new DelegatedSurrogateAuthenticationPostProcessor(surrogateAuthenticationService, servicesManager, eventPublisher,
-                registeredServiceAccessStrategyEnforcer, surrogateEligibilityAuditableExecution);
-    }
-
     @Bean
     public IdentityProviderHelper identityProviderHelper() {
         return new IdentityProviderHelper();
diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/config/WebflowConfig.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/config/WebflowConfig.java
index 65a538a03173ca366f309c460c40b3d40dd6ed24..5b5607c5d62985b267a0bfa64441214aea4d51fd 100644
--- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/config/WebflowConfig.java
+++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/config/WebflowConfig.java
@@ -193,9 +193,13 @@ public class WebflowConfig {
     @Autowired
     private Utils utils;
 
+    @Autowired
+    private DelegatedClientWebflowManager delegatedClientWebflowManager;
+
     @Bean
     public DispatcherAction dispatcherAction() {
-        return new DispatcherAction(providersService, identityProviderHelper, casRestClient, surrogationSeparator, utils);
+        return new DispatcherAction(providersService, identityProviderHelper, casRestClient,
+            surrogationSeparator, utils, delegatedClientDistributedSessionStore.getObject());
     }
 
     @Bean
@@ -236,7 +240,7 @@ public class WebflowConfig {
             builtClients.getObject(),
             servicesManager.getObject(),
             registeredServiceDelegatedAuthenticationPolicyAuditableEnforcer.getObject(),
-            delegatedClientWebflowManager(),
+            delegatedClientWebflowManager,
             authenticationSystemSupport.getObject(),
             casProperties,
             authenticationRequestServiceSelectionStrategies.getObject(),
@@ -252,17 +256,6 @@ public class WebflowConfig {
             surrogationSeparator);
     }
 
-    @RefreshScope
-    @Bean
-    public DelegatedClientWebflowManager delegatedClientWebflowManager() {
-        return new CustomDelegatedClientWebflowManager(ticketRegistry,
-            ticketFactory,
-            casProperties,
-            authenticationRequestServiceSelectionStrategies.getObject(),
-            argumentExtractor.getObject()
-        );
-    }
-
     @Bean
     @RefreshScope
     public Action terminateSessionAction() {
diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/CustomDelegatedClientWebflowManager.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/CustomDelegatedClientWebflowManager.java
deleted file mode 100644
index 4bea0c2e4e5ae4d491a96d45636c160b9937a5b4..0000000000000000000000000000000000000000
--- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/CustomDelegatedClientWebflowManager.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020)
- * and the signatories of the "VITAM - Accord du Contributeur" agreement.
- *
- * contact@programmevitam.fr
- *
- * This software is a computer program whose purpose is to implement
- * implement a digital archiving front-office system for the secure and
- * efficient high volumetry VITAM solution.
- *
- * This software is governed by the CeCILL-C license under French law and
- * abiding by the rules of distribution of free software.  You can  use,
- * modify and/ or redistribute the software under the terms of the CeCILL-C
- * license as circulated by CEA, CNRS and INRIA at the following URL
- * "http://www.cecill.info".
- *
- * As a counterpart to the access to the source code and  rights to copy,
- * modify and redistribute granted by the license, users are provided only
- * with a limited warranty  and the software's author,  the holder of the
- * economic rights,  and the successive licensors  have only  limited
- * liability.
- *
- * In this respect, the user's attention is drawn to the risks associated
- * with loading,  using,  modifying and/or developing or reproducing the
- * software by the user in light of its specific status of free software,
- * that may mean  that it is complicated to manipulate,  and  that  also
- * therefore means  that it is reserved for developers  and  experienced
- * professionals having in-depth computer knowledge. Users are therefore
- * encouraged to load and test the software's suitability as regards their
- * requirements in conditions enabling the security of their systems and/or
- * data to be ensured and,  more generally, to use and operate it in the
- * same conditions as regards security.
- *
- * The fact that you are presently reading this means that you have had
- * knowledge of the CeCILL-C license and that you accept its terms.
- */
-package fr.gouv.vitamui.cas.webflow;
-
-import fr.gouv.vitamui.cas.util.Constants;
-import org.apereo.cas.authentication.AuthenticationServiceSelectionPlan;
-import org.apereo.cas.authentication.principal.Service;
-import org.apereo.cas.configuration.CasConfigurationProperties;
-import org.apereo.cas.ticket.TicketFactory;
-import org.apereo.cas.ticket.TransientSessionTicket;
-import org.apereo.cas.ticket.registry.TicketRegistry;
-import org.apereo.cas.web.DelegatedClientWebflowManager;
-import org.apereo.cas.web.support.ArgumentExtractor;
-import org.pac4j.core.context.JEEContext;
-import org.pac4j.core.context.WebContext;
-import org.springframework.webflow.execution.RequestContext;
-
-import java.io.Serializable;
-import java.util.Map;
-
-/**
- * A webflow manager for authentication delegation which saves/restores the surrogate.
- *
- *
- */
-public class CustomDelegatedClientWebflowManager extends DelegatedClientWebflowManager {
-
-    public CustomDelegatedClientWebflowManager(final TicketRegistry ticketRegistry,
-        final TicketFactory ticketFactory,
-        final CasConfigurationProperties casProperties,
-        final AuthenticationServiceSelectionPlan authenticationRequestServiceSelectionStrategies,
-        final ArgumentExtractor argumentExtractor) {
-        super(ticketRegistry, ticketFactory, casProperties, authenticationRequestServiceSelectionStrategies, argumentExtractor);
-    }
-
-    @Override
-    protected Map<String, Serializable> buildTicketProperties(final JEEContext webContext) {
-        final Map<String, Serializable> properties = super.buildTicketProperties(webContext);
-
-        properties.put(Constants.SURROGATE, (String) webContext.getRequestAttribute(Constants.SURROGATE).orElse(null));
-
-        return properties;
-    }
-
-    @Override
-    protected Service restoreDelegatedAuthenticationRequest(final RequestContext requestContext, final WebContext webContext,
-                                                            final TransientSessionTicket ticket) {
-
-        webContext.setRequestAttribute(Constants.SURROGATE, ticket.getProperties().get(Constants.SURROGATE));
-
-        return super.restoreDelegatedAuthenticationRequest(requestContext, webContext, ticket);
-    }
-}
diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/CustomDelegatedClientAuthenticationAction.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/CustomDelegatedClientAuthenticationAction.java
index c90475a1afef1ad60c9716dc86f0e7b1a0e081b5..28a8cbc693f2e147387e2e0898464836385fe82a 100644
--- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/CustomDelegatedClientAuthenticationAction.java
+++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/CustomDelegatedClientAuthenticationAction.java
@@ -43,7 +43,6 @@ import fr.gouv.vitamui.cas.util.Utils;
 import fr.gouv.vitamui.commons.api.CommonConstants;
 import fr.gouv.vitamui.commons.api.logger.VitamUILogger;
 import fr.gouv.vitamui.commons.api.logger.VitamUILoggerFactory;
-import fr.gouv.vitamui.iam.common.dto.IdentityProviderDto;
 import fr.gouv.vitamui.iam.common.utils.IdentityProviderHelper;
 import org.apache.commons.lang3.StringUtils;
 import org.apereo.cas.CentralAuthenticationService;
@@ -66,17 +65,14 @@ import org.apereo.cas.web.support.WebUtils;
 import org.pac4j.core.client.Clients;
 import org.pac4j.core.context.JEEContext;
 import org.pac4j.core.context.session.SessionStore;
-import org.pac4j.saml.client.SAML2Client;
-import org.springframework.webflow.core.collection.MutableAttributeMap;
 import org.springframework.webflow.execution.Event;
 import org.springframework.webflow.execution.RequestContext;
 
-import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.List;
-import java.util.Optional;
+
+import lombok.val;
 
 /**
  * Custom authentication delegation:
@@ -141,10 +137,10 @@ public class CustomDelegatedClientAuthenticationAction extends DelegatedClientAu
     public Event doExecute(final RequestContext context) {
 
         // save a label in the webflow
-        final MutableAttributeMap<Object> flowScope = context.getFlowScope();
+        val flowScope = context.getFlowScope();
         flowScope.put(Constants.PORTAL_URL, vitamuiPortalUrl);
 
-        final Event event = super.doExecute(context);
+        val event = super.doExecute(context);
         if ("error".equals(event.getId())) {
 
             // extract and parse the request username if provided
@@ -167,13 +163,13 @@ public class CustomDelegatedClientAuthenticationAction extends DelegatedClientAu
             }
 
             // get the idp if it exists
-            final HttpServletRequest request = WebUtils.getHttpServletRequestFromExternalWebflowContext(context);
-            final String idp = getIdpValue(request);
+            val request = WebUtils.getHttpServletRequestFromExternalWebflowContext(context);
+            val idp = getIdpValue(request);
             LOGGER.debug("Provided idp: {}", idp);
             if (StringUtils.isNotBlank(idp)) {
 
                 TicketGrantingTicket tgt = null;
-                final String tgtId = WebUtils.getTicketGrantingTicketId(context);
+                val tgtId = WebUtils.getTicketGrantingTicketId(context);
                 if (tgtId != null) {
                     tgt = ticketRegistry.getTicket(tgtId, TicketGrantingTicket.class);
                 }
@@ -182,11 +178,11 @@ public class CustomDelegatedClientAuthenticationAction extends DelegatedClientAu
                 if (tgt == null || tgt.isExpired()) {
 
                     // if it matches an existing IdP, save it and redirect
-                    final Optional<IdentityProviderDto> optProvider = identityProviderHelper.findByTechnicalName(providersService.getProviders(), idp);
+                    val optProvider = identityProviderHelper.findByTechnicalName(providersService.getProviders(), idp);
                     if (optProvider.isPresent()) {
-                        final HttpServletResponse response = WebUtils.getHttpServletResponseFromExternalWebflowContext(context);
+                        val response = WebUtils.getHttpServletResponseFromExternalWebflowContext(context);
                         response.addCookie(utils.buildIdpCookie(idp, casProperties.getTgc()));
-                        final SAML2Client client = ((SamlIdentityProviderDto) optProvider.get()).getSaml2Client();
+                        val client = ((SamlIdentityProviderDto) optProvider.get()).getSaml2Client();
                         LOGGER.debug("Force redirect to the SAML IdP: {}", client.getName());
                         try {
                             return utils.performClientRedirection(this, client, context);
@@ -207,7 +203,7 @@ public class CustomDelegatedClientAuthenticationAction extends DelegatedClientAu
         if (StringUtils.isNotBlank(idp)) {
             return idp;
         }
-        final Cookie cookie = org.springframework.web.util.WebUtils.getCookie(request, CommonConstants.IDP_PARAMETER);
+        val cookie = org.springframework.web.util.WebUtils.getCookie(request, CommonConstants.IDP_PARAMETER);
         if (cookie != null) {
             return cookie.getValue();
         }
diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/DispatcherAction.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/DispatcherAction.java
index fcbc21509d1e3d50ba5924d97daa7e9059e1bea6..6a51c276feeba46888512611bc14f91ed9dd0898 100644
--- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/DispatcherAction.java
+++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/DispatcherAction.java
@@ -40,7 +40,6 @@ import fr.gouv.vitamui.cas.provider.SamlIdentityProviderDto;
 import fr.gouv.vitamui.cas.provider.ProvidersService;
 import fr.gouv.vitamui.cas.util.Constants;
 import fr.gouv.vitamui.cas.util.Utils;
-import fr.gouv.vitamui.commons.api.domain.UserDto;
 import fr.gouv.vitamui.commons.api.enums.UserStatusEnum;
 import fr.gouv.vitamui.commons.api.exception.InvalidFormatException;
 import fr.gouv.vitamui.commons.api.exception.NotFoundException;
@@ -52,14 +51,17 @@ import lombok.RequiredArgsConstructor;
 import org.apache.commons.lang.StringUtils;
 import org.apereo.cas.authentication.credential.UsernamePasswordCredential;
 import org.apereo.cas.web.support.WebUtils;
+import org.pac4j.core.context.JEEContext;
+import org.pac4j.core.context.session.SessionStore;
 import org.springframework.webflow.action.AbstractAction;
 import org.springframework.webflow.execution.Event;
 import org.springframework.webflow.execution.RequestContext;
 
-import javax.servlet.http.HttpServletRequest;
 import java.io.IOException;
 import java.util.Optional;
 
+import lombok.val;
+
 /**
  * This class can dispatch the user:
  * - either to the password page
@@ -87,11 +89,13 @@ public class DispatcherAction extends AbstractAction {
 
     private final Utils utils;
 
+    private final SessionStore sessionStore;
+
     @Override
     protected Event doExecute(final RequestContext requestContext) throws IOException {
 
-        final UsernamePasswordCredential credential = WebUtils.getCredential(requestContext, UsernamePasswordCredential.class);
-        final String username = credential.getUsername().toLowerCase();
+        val credential = WebUtils.getCredential(requestContext, UsernamePasswordCredential.class);
+        val username = credential.getUsername().toLowerCase();
         String dispatchedUser = username;
         String surrogate = null;
         if (username.contains(surrogationSeparator)) {
@@ -106,7 +110,7 @@ public class DispatcherAction extends AbstractAction {
 
         // if the user is disabled, send him to a specific page (ignore not found users: it will fail when checking login/password)
         try {
-            final UserDto dispatcherUserDto = casExternalRestClient.getUserByEmail(utils.buildContext(dispatchedUser), dispatchedUser, Optional.empty());
+            val dispatcherUserDto = casExternalRestClient.getUserByEmail(utils.buildContext(dispatchedUser), dispatchedUser, Optional.empty());
             if (dispatcherUserDto != null && dispatcherUserDto.getStatus() != UserStatusEnum.ENABLED) {
                 return userDisabled(dispatchedUser);
             }
@@ -116,7 +120,7 @@ public class DispatcherAction extends AbstractAction {
         }
         if (surrogate != null) {
             try {
-                final UserDto surrogateDto = casExternalRestClient.getUserByEmail(utils.buildContext(surrogate), surrogate, Optional.empty());
+                val surrogateDto = casExternalRestClient.getUserByEmail(utils.buildContext(surrogate), surrogate, Optional.empty());
                 if (surrogateDto != null && surrogateDto.getStatus() != UserStatusEnum.ENABLED) {
                     LOGGER.error("Bad status for surrogate: {}", surrogate);
                     return userDisabled(surrogate);
@@ -127,24 +131,26 @@ public class DispatcherAction extends AbstractAction {
             }
         }
 
-        final HttpServletRequest request = WebUtils.getHttpServletRequestFromExternalWebflowContext(requestContext);
+        val request = WebUtils.getHttpServletRequestFromExternalWebflowContext(requestContext);
         boolean isInternal;
-        final SamlIdentityProviderDto provider = (SamlIdentityProviderDto) identityProviderHelper.findByUserIdentifier(providersService.getProviders(), dispatchedUser).orElse(null);
+        val provider = (SamlIdentityProviderDto) identityProviderHelper.findByUserIdentifier(providersService.getProviders(), dispatchedUser).orElse(null);
         if (provider != null) {
             isInternal = provider.getInternal();
         } else {
             return new Event(this, BAD_CONFIGURATION);
         }
+        val response = WebUtils.getHttpServletResponseFromExternalWebflowContext(requestContext);
+        val webContext = new JEEContext(request, response, sessionStore);
         if (isInternal) {
-            request.removeAttribute(Constants.SURROGATE);
+            sessionStore.set(webContext, Constants.SURROGATE, null);
             LOGGER.debug("Redirect the user to the password page...");
             return success();
         } else {
 
-            // save the surrogate as a request attribute if he exists for the DelegatedClientWebflowManager
+            // save the surrogate in the session to be retrieved by the UserPrincipalResolver and DelegatedSurrogateAuthenticationPostProcessor
             if (surrogate != null) {
                 LOGGER.debug("Saving surrogate for after authentication delegation: {}", surrogate);
-                request.setAttribute(Constants.SURROGATE, surrogate);
+                sessionStore.set(webContext, Constants.SURROGATE, surrogate);
             }
 
             return utils.performClientRedirection(this, provider.getSaml2Client(), requestContext);
diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/SelectRedirectAction.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/SelectRedirectAction.java
index 3564f0c25f5a91a42109fc09d84e446c9ad8ab39..ff25f295c28d6bc02a72fd64f2f3030dcee29599 100644
--- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/SelectRedirectAction.java
+++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/SelectRedirectAction.java
@@ -47,6 +47,8 @@ import org.springframework.webflow.action.AbstractAction;
 import org.springframework.webflow.execution.Event;
 import org.springframework.webflow.execution.RequestContext;
 
+import lombok.val;
+
 /**
  * Select the appropriate redirect action: directly to the service or via the "secure connexion" page.
  *
@@ -63,9 +65,9 @@ public class SelectRedirectAction extends AbstractAction {
     protected Event doExecute(final RequestContext requestContext) {
         boolean isFromNewLogin = false;
 
-        final String stId = WebUtils.getServiceTicketFromRequestScope(requestContext);
+        val stId = WebUtils.getServiceTicketFromRequestScope(requestContext);
         if (stId != null) {
-            final ServiceTicket st = centralAuthenticationService.getTicket(stId, ServiceTicket.class);
+            val st = centralAuthenticationService.getTicket(stId, ServiceTicket.class);
             if (st != null) {
                 isFromNewLogin = st.isFromNewLogin();
             }
diff --git a/cas/cas-server/src/test/java/fr/gouv/vitamui/cas/authentication/IamSurrogateRestAuthenticationServiceTest.java b/cas/cas-server/src/test/java/fr/gouv/vitamui/cas/authentication/IamSurrogateRestAuthenticationServiceTest.java
index d3e227c8c96a223e60c404dede1ba458bc7f1e4d..35b08641b978300935f7adec757a237ebf306577 100644
--- a/cas/cas-server/src/test/java/fr/gouv/vitamui/cas/authentication/IamSurrogateRestAuthenticationServiceTest.java
+++ b/cas/cas-server/src/test/java/fr/gouv/vitamui/cas/authentication/IamSurrogateRestAuthenticationServiceTest.java
@@ -6,6 +6,7 @@ import fr.gouv.vitamui.commons.rest.client.ExternalHttpContext;
 import fr.gouv.vitamui.iam.external.client.CasExternalRestClient;
 import fr.gouv.vitamui.iam.common.dto.SubrogationDto;
 import fr.gouv.vitamui.iam.common.enums.SubrogationStatusEnum;
+import org.apereo.cas.authentication.principal.DefaultPrincipalFactory;
 import org.apereo.cas.authentication.principal.Principal;
 import org.apereo.cas.services.ServicesManager;
 import org.junit.Before;
@@ -16,10 +17,14 @@ import org.springframework.test.context.TestPropertySource;
 import org.springframework.test.context.junit4.SpringRunner;
 
 import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
 
 import static org.mockito.Mockito.*;
 import static org.junit.Assert.*;
 
+import lombok.val;
+
 /**
  * Tests {@link IamSurrogateRestAuthenticationService}.
  *
@@ -48,43 +53,48 @@ public final class IamSurrogateRestAuthenticationServiceTest {
 
     @Test
     public void testCanAuthenticateOk() {
-        when(casExternalRestClient.getSubrogationsBySuperUserId(any(ExternalHttpContext.class), eq(SU_ID))).thenReturn(Arrays.asList(buildSubrogation()));
+        when(casExternalRestClient.getSubrogationsBySuperUserId(any(ExternalHttpContext.class), eq(SU_ID))).thenReturn(Arrays.asList(surrogation()));
 
-        final Principal principal = () -> SU_ID;
-        assertTrue(service.canAuthenticateAsInternal(SURROGATE, principal, null));
+        assertTrue(service.canAuthenticateAsInternal(SURROGATE, principal(), null));
     }
 
     @Test
     public void testCanAuthenticateCannotSurrogate() {
-        final SubrogationDto subrogation = buildSubrogation();
+        final SubrogationDto subrogation = surrogation();
         subrogation.setSurrogate("anotherUser");
         when(casExternalRestClient.getSubrogationsBySuperUserId(any(ExternalHttpContext.class), eq(SU_ID)))
             .thenReturn(Arrays.asList(subrogation));
 
-        final Principal principal = () -> SU_ID;
-        assertFalse(service.canAuthenticateAsInternal(SURROGATE, principal, null));
+        assertFalse(service.canAuthenticateAsInternal(SURROGATE, principal(), null));
     }
 
     @Test
     public void testCanAuthenticateNotAccepted() {
-        final SubrogationDto subrogation = buildSubrogation();
+        final SubrogationDto subrogation = surrogation();
         subrogation.setStatus(SubrogationStatusEnum.CREATED);
         when(casExternalRestClient.getSubrogationsBySuperUserId(any(ExternalHttpContext.class), eq(SU_ID)))
             .thenReturn(Arrays.asList(subrogation));
 
-        final Principal principal = () -> SU_ID;
-        assertFalse(service.canAuthenticateAsInternal(SURROGATE, principal, null));
+        assertFalse(service.canAuthenticateAsInternal(SURROGATE, principal(), null));
     }
 
     @Test(expected = UnsupportedOperationException.class)
     public void testGetAccounts() {
         when(casExternalRestClient.getSubrogationsBySuperUserEmail(any(ExternalHttpContext.class), eq(SU_EMAIL)))
-            .thenReturn(Arrays.asList(buildSubrogation()));
+            .thenReturn(Arrays.asList(surrogation()));
 
         service.getEligibleAccountsForSurrogateToProxy(SU_EMAIL);
     }
 
-    private SubrogationDto buildSubrogation() {
+    private Principal principal() {
+        val attributes = new HashMap<String, List<Object>>();
+        attributes.put(UserPrincipalResolver.SUPER_USER_ID_ATTRIBUTE, Arrays.asList(SU_ID));
+
+        val factory = new DefaultPrincipalFactory();
+        return factory.createPrincipal("x", attributes);
+    }
+
+    private SubrogationDto surrogation() {
         final SubrogationDto subrogation = new SubrogationDto();
         subrogation.setSurrogate(SURROGATE);
         subrogation.setSuperUser(SU_EMAIL);
diff --git a/cas/cas-server/src/test/java/fr/gouv/vitamui/cas/authentication/UserPrincipalResolverTest.java b/cas/cas-server/src/test/java/fr/gouv/vitamui/cas/authentication/UserPrincipalResolverTest.java
index 7267736ed479db8beee9c2219e9b37293f3adbd4..a8029130d83b0d35a4277246223b685aecefd548 100644
--- a/cas/cas-server/src/test/java/fr/gouv/vitamui/cas/authentication/UserPrincipalResolverTest.java
+++ b/cas/cas-server/src/test/java/fr/gouv/vitamui/cas/authentication/UserPrincipalResolverTest.java
@@ -1,6 +1,8 @@
 package fr.gouv.vitamui.cas.authentication;
 
+import fr.gouv.vitamui.cas.util.Constants;
 import fr.gouv.vitamui.cas.util.Utils;
+import fr.gouv.vitamui.cas.webflow.actions.BaseWebflowActionTest;
 import fr.gouv.vitamui.commons.api.CommonConstants;
 import fr.gouv.vitamui.commons.api.domain.AddressDto;
 import fr.gouv.vitamui.commons.api.domain.GroupDto;
@@ -13,19 +15,24 @@ import fr.gouv.vitamui.commons.api.utils.CasJsonWrapper;
 import fr.gouv.vitamui.commons.rest.client.ExternalHttpContext;
 import fr.gouv.vitamui.commons.security.client.dto.AuthUserDto;
 import fr.gouv.vitamui.iam.external.client.CasExternalRestClient;
+import org.apereo.cas.authentication.SurrogateUsernamePasswordCredential;
+import org.apereo.cas.authentication.credential.UsernamePasswordCredential;
+import org.apereo.cas.authentication.principal.ClientCredential;
 import org.apereo.cas.authentication.principal.DefaultPrincipalFactory;
 import org.apereo.cas.authentication.principal.Principal;
+import org.apereo.cas.authentication.principal.PrincipalFactory;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.pac4j.core.context.JEEContext;
+import org.pac4j.core.context.session.SessionStore;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.TestPropertySource;
 import org.springframework.test.context.junit4.SpringRunner;
-import org.springframework.webflow.execution.RequestContext;
-import org.springframework.webflow.execution.RequestContextHolder;
 
 import java.util.*;
 
+import static fr.gouv.vitamui.commons.api.CommonConstants.SUPER_USER_ATTRIBUTE;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
@@ -34,6 +41,8 @@ import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import lombok.val;
+
 /**
  * Tests {@link UserPrincipalResolver}.
  *
@@ -42,11 +51,15 @@ import static org.mockito.Mockito.when;
 @RunWith(SpringRunner.class)
 @ContextConfiguration(classes = ServerIdentityAutoConfiguration.class)
 @TestPropertySource(locations = "classpath:/application-test.properties")
-public final class UserPrincipalResolverTest {
+public final class UserPrincipalResolverTest extends BaseWebflowActionTest {
 
     private static final String USERNAME = "jleleu@test.com";
+    private static final String ADMIN = "admin@test.com";
+
+    private static final String PWD = "password";
 
-    private static final String ID = "1234";
+    private static final String USERNAME_ID = "jleleu";
+    private static final String ADMIN_ID = "admin";
 
     private static final String ROLE_NAME = "role1";
 
@@ -54,13 +67,19 @@ public final class UserPrincipalResolverTest {
 
     private CasExternalRestClient casExternalRestClient;
 
+    private PrincipalFactory principalFactory;
+
+    private SessionStore sessionStore;
+
     @Before
     public void setUp() {
+        super.setUp();
+
         casExternalRestClient = mock(CasExternalRestClient.class);
         final Utils utils = new Utils(casExternalRestClient, null, 0, null);
-        resolver = new UserPrincipalResolver(false, new DefaultPrincipalFactory(), casExternalRestClient, utils);
-        final RequestContext context = mock(RequestContext.class);
-        RequestContextHolder.setRequestContext(context);
+        principalFactory = new DefaultPrincipalFactory();
+        sessionStore = mock(SessionStore.class);
+        resolver = new UserPrincipalResolver(principalFactory, casExternalRestClient, utils, sessionStore);
     }
 
     @Test
@@ -68,24 +87,84 @@ public final class UserPrincipalResolverTest {
         when(casExternalRestClient.getUserByEmail(any(ExternalHttpContext.class), eq(USERNAME),
                 eq(Optional.of(CommonConstants.AUTH_TOKEN_PARAMETER)))).thenReturn(userProfile(UserStatusEnum.ENABLED));
 
-        final Principal principal = resolver.resolve(USERNAME, new HashMap<>());
-        assertEquals(ID, principal.getId());
+        final Principal principal = resolver.resolve(new UsernamePasswordCredential(USERNAME, PWD),
+            Optional.of(principalFactory.createPrincipal(USERNAME)), Optional.empty());
+
+        assertEquals(USERNAME_ID, principal.getId());
+        final Map<String, List<Object>> attributes = principal.getAttributes();
+        assertEquals(USERNAME, attributes.get(CommonConstants.EMAIL_ATTRIBUTE).get(0));
+        assertEquals(Arrays.asList(ROLE_NAME), attributes.get(CommonConstants.ROLES_ATTRIBUTE));
+        assertNull(attributes.get(SUPER_USER_ATTRIBUTE));
+    }
+
+    @Test
+    public void testResolveAuthnDelegation() {
+        when(casExternalRestClient.getUserByEmail(any(ExternalHttpContext.class), eq(USERNAME),
+            eq(Optional.of(CommonConstants.AUTH_TOKEN_PARAMETER)))).thenReturn(userProfile(UserStatusEnum.ENABLED));
+        when(sessionStore.get(any(JEEContext.class), eq(Constants.SURROGATE))).thenReturn(Optional.empty());
+
+        final Principal principal = resolver.resolve(new ClientCredential(),
+            Optional.of(principalFactory.createPrincipal(USERNAME)), Optional.empty());
+
+        assertEquals(USERNAME_ID, principal.getId());
         final Map<String, List<Object>> attributes = principal.getAttributes();
         assertEquals(USERNAME, attributes.get(CommonConstants.EMAIL_ATTRIBUTE).get(0));
         assertEquals(Arrays.asList(ROLE_NAME), attributes.get(CommonConstants.ROLES_ATTRIBUTE));
+        assertNull(attributes.get(SUPER_USER_ATTRIBUTE));
     }
 
-    @Test public void testResolveAddressDeserializSuccessfully() {
+    @Test
+    public void testResolveSurrogateUser() {
+        when(casExternalRestClient.getUserByEmail(any(ExternalHttpContext.class), eq(USERNAME),
+            eq(Optional.of(CommonConstants.AUTH_TOKEN_PARAMETER + "," + CommonConstants.SURROGATION_PARAMETER))))
+            .thenReturn(userProfile(UserStatusEnum.ENABLED));
+        when(casExternalRestClient.getUserByEmail(any(ExternalHttpContext.class), eq(ADMIN),
+            eq(Optional.empty()))).thenReturn(adminProfile());
+
+        val credential = new SurrogateUsernamePasswordCredential();
+        credential.setUsername(ADMIN);
+        credential.setSurrogateUsername(USERNAME);
+        final Principal principal = resolver.resolve(credential, Optional.of(principalFactory.createPrincipal(ADMIN)), Optional.empty());
+
+        assertEquals(USERNAME_ID, principal.getId());
+        final Map<String, List<Object>> attributes = principal.getAttributes();
+        assertEquals(USERNAME, attributes.get(CommonConstants.EMAIL_ATTRIBUTE).get(0));
+        assertEquals(Arrays.asList(ROLE_NAME), attributes.get(CommonConstants.ROLES_ATTRIBUTE));
+        assertEquals(ADMIN, attributes.get(SUPER_USER_ATTRIBUTE).get(0));
+    }
+
+    @Test
+    public void testResolveAuthnDelegationSurrogate() {
+        when(casExternalRestClient.getUserByEmail(any(ExternalHttpContext.class), eq(USERNAME),
+            eq(Optional.of(CommonConstants.AUTH_TOKEN_PARAMETER + "," + CommonConstants.SURROGATION_PARAMETER))))
+            .thenReturn(userProfile(UserStatusEnum.ENABLED));
+        when(casExternalRestClient.getUserByEmail(any(ExternalHttpContext.class), eq(ADMIN),
+            eq(Optional.empty()))).thenReturn(adminProfile());
+        when(sessionStore.get(any(JEEContext.class), eq(Constants.SURROGATE))).thenReturn(Optional.of(USERNAME));
+
+        final Principal principal = resolver.resolve(new ClientCredential(),
+            Optional.of(principalFactory.createPrincipal(ADMIN)), Optional.empty());
+
+        assertEquals(USERNAME_ID, principal.getId());
+        final Map<String, List<Object>> attributes = principal.getAttributes();
+        assertEquals(USERNAME, attributes.get(CommonConstants.EMAIL_ATTRIBUTE).get(0));
+        assertEquals(Arrays.asList(ROLE_NAME), attributes.get(CommonConstants.ROLES_ATTRIBUTE));
+        assertEquals(ADMIN, attributes.get(SUPER_USER_ATTRIBUTE).get(0));
+    }
+
+    @Test
+    public void testResolveAddressDeserializSuccessfully() {
         AuthUserDto authUserDto = userProfile(UserStatusEnum.ENABLED);
         when(casExternalRestClient.getUserByEmail(any(ExternalHttpContext.class), eq(USERNAME), eq(Optional.of(CommonConstants.AUTH_TOKEN_PARAMETER))))
                 .thenReturn(authUserDto);
 
-        final Principal principal = resolver.resolve(USERNAME, new HashMap<>());
+        final Principal principal = resolver.resolve(new UsernamePasswordCredential(USERNAME, PWD),
+            Optional.of(principalFactory.createPrincipal(USERNAME)), Optional.empty());
 
+        assertEquals(USERNAME_ID, principal.getId());
         AddressDto addressDto = (AddressDto) ((CasJsonWrapper) principal.getAttributes().get(CommonConstants.ADDRESS_ATTRIBUTE).get(0)).getData();
-
-        assertEquals(ID, principal.getId());
         assertThat(addressDto).isEqualToComparingFieldByField(authUserDto.getAddress());
+        assertNull(principal.getAttributes().get(SUPER_USER_ATTRIBUTE));
     }
 
     @Test
@@ -93,7 +172,8 @@ public final class UserPrincipalResolverTest {
         when(casExternalRestClient.getUserByEmail(any(ExternalHttpContext.class), eq(USERNAME),
                 eq(Optional.of(CommonConstants.AUTH_TOKEN_PARAMETER)))).thenReturn(null);
 
-        assertNull(resolver.resolve(USERNAME, new HashMap<>()));
+        assertNull(resolver.resolve(new UsernamePasswordCredential(USERNAME, PWD),
+            Optional.of(principalFactory.createPrincipal(USERNAME)), Optional.empty()));
     }
 
     @Test
@@ -102,7 +182,8 @@ public final class UserPrincipalResolverTest {
                 eq(Optional.of(CommonConstants.AUTH_TOKEN_PARAMETER))))
                         .thenReturn(userProfile(UserStatusEnum.DISABLED));
 
-        assertNull(resolver.resolve(USERNAME, new HashMap<>()));
+        assertNull(resolver.resolve(new UsernamePasswordCredential(USERNAME, PWD),
+            Optional.of(principalFactory.createPrincipal(USERNAME)), Optional.empty()));
     }
 
     @Test
@@ -110,12 +191,21 @@ public final class UserPrincipalResolverTest {
         when(casExternalRestClient.getUserByEmail(any(ExternalHttpContext.class), eq(USERNAME),
                 eq(Optional.of(CommonConstants.AUTH_TOKEN_PARAMETER)))).thenReturn(userProfile(UserStatusEnum.BLOCKED));
 
-        assertNull(resolver.resolve(USERNAME, new HashMap<>()));
+        assertNull(resolver.resolve(new UsernamePasswordCredential(USERNAME, PWD),
+            Optional.of(principalFactory.createPrincipal(USERNAME)), Optional.empty()));
+    }
+
+    private AuthUserDto adminProfile() {
+        return profile(UserStatusEnum.ENABLED, ADMIN_ID);
     }
 
     private AuthUserDto userProfile(final UserStatusEnum status) {
+        return profile(status, USERNAME_ID);
+    }
+
+    private AuthUserDto profile(final UserStatusEnum status, final String id) {
         final AuthUserDto user = new AuthUserDto();
-        user.setId(ID);
+        user.setId(id);
         user.setStatus(status);
         user.setType(UserTypeEnum.NOMINATIVE);
         AddressDto address = new AddressDto();
diff --git a/cas/cas-server/src/test/java/fr/gouv/vitamui/cas/webflow/actions/BaseWebflowActionTest.java b/cas/cas-server/src/test/java/fr/gouv/vitamui/cas/webflow/actions/BaseWebflowActionTest.java
index ae75f1e3d45938f86572ed853670196e779ebba0..9d414610d6698caed26b021c6c6fae52372492af 100644
--- a/cas/cas-server/src/test/java/fr/gouv/vitamui/cas/webflow/actions/BaseWebflowActionTest.java
+++ b/cas/cas-server/src/test/java/fr/gouv/vitamui/cas/webflow/actions/BaseWebflowActionTest.java
@@ -15,6 +15,7 @@ import org.springframework.webflow.engine.FlowVariable;
 import org.springframework.webflow.execution.FlowExecutionContext;
 import org.springframework.webflow.execution.FlowSession;
 import org.springframework.webflow.execution.RequestContext;
+import org.springframework.webflow.execution.RequestContextHolder;
 import org.springframework.webflow.test.MockParameterMap;
 
 import javax.servlet.http.HttpServletRequest;
@@ -82,5 +83,7 @@ public abstract class BaseWebflowActionTest {
         final FlowSession flowSession = mock(FlowSession.class);
         when(flowContext.getActiveSession()).thenReturn(flowSession);
         when(flowSession.getScope()).thenReturn(new LocalAttributeMap<>());
+
+        RequestContextHolder.setRequestContext(context);
     }
 }
diff --git a/cas/cas-server/src/test/java/fr/gouv/vitamui/cas/webflow/actions/DispatcherActionTest.java b/cas/cas-server/src/test/java/fr/gouv/vitamui/cas/webflow/actions/DispatcherActionTest.java
index c6e8dbbeffcd83de360117ca40ab38e1277fa4e0..d7745918419651ce9ff3fefc1b1189a9b47a5008 100644
--- a/cas/cas-server/src/test/java/fr/gouv/vitamui/cas/webflow/actions/DispatcherActionTest.java
+++ b/cas/cas-server/src/test/java/fr/gouv/vitamui/cas/webflow/actions/DispatcherActionTest.java
@@ -17,6 +17,7 @@ import org.apereo.cas.authentication.credential.UsernamePasswordCredential;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.pac4j.core.context.session.SessionStore;
 import org.pac4j.saml.client.SAML2Client;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.TestPropertySource;
@@ -65,7 +66,7 @@ public final class DispatcherActionTest extends BaseWebflowActionTest {
         casExternalRestClient = mock(CasExternalRestClient.class);
 
         final Utils utils = new Utils(casExternalRestClient, null, 0, null);
-        action = new DispatcherAction(providersService, identityProviderHelper, casExternalRestClient, ",", utils);
+        action = new DispatcherAction(providersService, identityProviderHelper, casExternalRestClient, ",", utils, mock(SessionStore.class));
 
         final SAML2Client client = new SAML2Client();
         provider = new SamlIdentityProviderDto(new IdentityProviderDto(), client);