package org.apereo.cas.authentication; import java.util.Arrays; import java.util.Collection; import static java.util.stream.Collectors.joining; /** * ThreadLocal based holder for current set of credentials and/or authentication object for any current * CAS authentication transaction. Useful for making this information available to all the interested CAS * components that are not tightly coupled with core CAS APIs, for example audit principal resolver component, etc. * <p> * The thread local state carried by this class should be set by core CAS components processing core authentication and * CAS protocol events e.g. {@code AbstractAuthenticationManager}, {@code CentralAuthenticationServiceImpl}, etc. * <p> * The clearing of this state at the end of a thread execution path is the responsibility * of {@code AuthenticationCredentialsLocalBinderClearingFilter} * * @author Dmitriy Kopylenko * @since 5.0.0 */ public class AuthenticationCredentialsLocalBinder { private static final ThreadLocal<Authentication> CURRENT_AUTHENTICATION = new ThreadLocal<>(); private static final ThreadLocal<String[]> CURRENT_CREDENTIAL_IDS = new ThreadLocal<>(); protected AuthenticationCredentialsLocalBinder() { } /** * Bind credentials to ThreadLocal. * * @param credentials the credentials */ public static void bindCurrent(final Collection<Credential> credentials) { bindCurrent(credentials.toArray(new Credential[0])); } /** * Bind credentials to ThreadLocal. * * @param credentials the credentials */ public static void bindCurrent(final Credential... credentials) { CURRENT_CREDENTIAL_IDS.set(Arrays.stream(credentials).map(Credential::getId).toArray(String[]::new)); } /** * Get credential ids from ThreadLocal. * * @return credential ids */ public static String[] getCurrentCredentialIds() { return CURRENT_CREDENTIAL_IDS.get(); } /** * Get credential ids String representation from ThreadLocal. * * @return credential ids String representation */ public static String getCurrentCredentialIdsAsString() { return getCurrentCredentialIds() != null ? Arrays.stream(getCurrentCredentialIds()).collect(joining(", ")) : null; } /** * Bind Authentication to ThreadLocal. * * @param authentication the authentication */ public static void bindCurrent(final Authentication authentication) { CURRENT_AUTHENTICATION.set(authentication); } /** * Get Authentication from ThreadLocal. * * @return authentication */ public static Authentication getCurrentAuthentication() { return CURRENT_AUTHENTICATION.get(); } /** * Clear ThreadLocal state. */ public static void clear() { CURRENT_CREDENTIAL_IDS.remove(); CURRENT_AUTHENTICATION.remove(); } }