The context is confused when using ContextPropagator to pass the ThreadLocal context

Hi, I use ContextPropagator to pass the username which serialize from the spring security context holder.

And deserialize the username then set it to spring security context holder.But sometime the child workflow’s user is different with parent workflow, it should be same.

For example,user A start a workflow wfA, user B start a workflow wfB when wfA is about to end.
The wfB’s child workflow wfB1’s user will be user A sometimes.

I can’t figure out what happened. Shouldn’t i use ContextPropagator for my purpose?

The following is my ContextPropagator code:

public class SpringSecurityContextPropagators implements ContextPropagator {

    public SpringSecurityContextPropagators(UserContext userContext){
        this.userContext = userContext;
    }

    private UserContext userContext;

    public final Logger logger = LoggerFactory.getLogger(this.getClass().getName());
    private static final String PROPAGATOR_KEY = "username";

    @Override
    public String getName() {
        return this.getClass().getName();
    }

    @Override
    public Map<String, Payload> serializeContext(Object context) {
        if (context == null) {
            return Collections.emptyMap();
        }
        Map<String, Payload> serializedContext = new HashMap<>();
        serializedContext.put(PROPAGATOR_KEY, Payload.newBuilder().setData(ByteString.copyFromUtf8((String) context)).build());
        return serializedContext;
    }

    @Override
    public Object deserializeContext(Map<String, Payload> context) {
        Payload payload = context.get(PROPAGATOR_KEY);
        return payload == null ? null : payload.getData().toStringUtf8();
    }

    @Override
    public Object getCurrentContext() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null) {
            logger.warn("auth info is empty!");
            return null;
        }
        return ((UserDetails) authentication.getPrincipal()).getUsername();
    }

    @Override
    public void setCurrentContext(Object context) {
        if (context == null) {
            return;
        }
        userContext.loadAuthenticationByUsername((String) context);
    }
}
1 Like

@zuodimiaoyun
Using Interceptors is preferred over context propagator in most cases.
You can see interceptors use in the Java SDK OpenTracing module, and small sample here.

My guess is that your problem is not linked to the ContextPropagator, but how SecurityContextHolder interacts with the workflow threads.

Thanks for the reply, I will give a try using Interceptors.

Yes, My problem is how SecurityContextHolder interacts with not only the workflow threads but also activity threads.
I think I can use ContextPropagator to do it, but it not worked as expected.
I will try using Interceptors to make it as tihomir says.