Spring Security support for Apereo's Central Authentication Service (CAS) enabling Single Sign-On authentication
—
Web filters and entry points for processing CAS authentication flows, handling service ticket validation, and managing gateway authentication. These components integrate CAS authentication into the Spring Security web filter chain.
Processes CAS service tickets from callback URLs and handles proxy granting ticket reception for proxy authentication scenarios.
/**
* Processes CAS service tickets and proxy authentication requests.
* Must be configured in the Spring Security filter chain to handle CAS callbacks.
*/
public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
/**
* Creates a CAS authentication filter with default settings.
* Default filter processes URL pattern "/login/cas".
*/
public CasAuthenticationFilter();
/**
* Attempts authentication by extracting and validating CAS service ticket.
* @param request HTTP request containing CAS ticket parameter
* @param response HTTP response for redirects
* @return Authentication object if successful
* @throws AuthenticationException if authentication fails
* @throws IOException if I/O errors occur
*/
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException;
/**
* Determines if authentication is required for this request.
* @param request the HTTP request
* @param response the HTTP response
* @return true if authentication should be attempted
*/
protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response);
/**
* Extracts the CAS artifact (ticket) from the request.
* @param request HTTP request containing ticket parameter
* @return the CAS ticket or null if not present
*/
protected String obtainArtifact(HttpServletRequest request);
/**
* Sets failure handler for proxy authentication failures.
* @param proxyFailureHandler handler for proxy authentication failures
*/
public void setProxyAuthenticationFailureHandler(AuthenticationFailureHandler proxyFailureHandler);
/**
* Sets failure handler for regular authentication failures.
* @param failureHandler handler for authentication failures
*/
public void setAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler);
/**
* Sets request matcher for identifying proxy receptor requests.
* @param proxyReceptorMatcher matcher for proxy receptor URLs
*/
public void setProxyReceptorMatcher(RequestMatcher proxyReceptorMatcher);
/**
* Sets the proxy receptor URL for receiving proxy granting tickets.
* @param proxyReceptorUrl URL pattern for proxy ticket reception
*/
public void setProxyReceptorUrl(String proxyReceptorUrl);
/**
* Sets storage for proxy granting tickets.
* @param proxyGrantingTicketStorage storage implementation for PGTs
*/
public void setProxyGrantingTicketStorage(ProxyGrantingTicketStorage proxyGrantingTicketStorage);
/**
* Sets service properties for CAS integration.
* @param serviceProperties CAS service configuration
*/
public void setServiceProperties(ServiceProperties serviceProperties);
/**
* Sets security context repository for storing authentication.
* @param securityContextRepository repository for security context persistence
*/
public void setSecurityContextRepository(SecurityContextRepository securityContextRepository);
/**
* Sets security context holder strategy.
* @param securityContextHolderStrategy strategy for managing security context
*/
public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy);
/**
* Sets redirect strategy for handling redirects.
* @param redirectStrategy strategy for performing redirects
*/
public void setRedirectStrategy(RedirectStrategy redirectStrategy);
/**
* Sets request cache for saving original requests.
* @param requestCache cache for storing original requests before authentication
*/
public void setRequestCache(RequestCache requestCache);
}Usage Example:
@Bean
public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
CasAuthenticationFilter filter = new CasAuthenticationFilter();
filter.setAuthenticationManager(authenticationManager());
filter.setServiceProperties(serviceProperties());
filter.setAuthenticationSuccessHandler(successHandler());
filter.setAuthenticationFailureHandler(failureHandler());
return filter;
}Initiates CAS authentication by redirecting unauthenticated users to the CAS server login page.
/**
* Authentication entry point that redirects users to CAS server for authentication.
* Invoked when authentication is required but user is not authenticated.
*/
public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, InitializingBean {
/**
* Commences authentication by redirecting to CAS login URL.
* @param servletRequest the HTTP request
* @param response the HTTP response
* @param authenticationException exception that triggered authentication requirement
* @throws IOException if I/O errors occur during redirect
*/
public void commence(HttpServletRequest servletRequest, HttpServletResponse response,
AuthenticationException authenticationException) throws IOException;
/**
* Validates configuration after properties are set.
* @throws IllegalArgumentException if required properties are missing
*/
public void afterPropertiesSet() throws IllegalArgumentException;
/**
* Gets the CAS server login URL.
* @return the login URL
*/
public String getLoginUrl();
/**
* Gets the service properties configuration.
* @return the service properties
*/
public ServiceProperties getServiceProperties();
/**
* Sets the CAS server login URL.
* @param loginUrl URL of CAS server login page (required)
*/
public void setLoginUrl(String loginUrl);
/**
* Sets service properties for CAS integration.
* @param serviceProperties CAS service configuration (required)
*/
public void setServiceProperties(ServiceProperties serviceProperties);
/**
* Sets whether to encode service URL with session ID.
* @param encodeServiceUrlWithSessionId true to encode session ID in service URL
*/
public void setEncodeServiceUrlWithSessionId(boolean encodeServiceUrlWithSessionId);
/**
* Sets redirect strategy for performing redirects.
* @param redirectStrategy strategy for handling redirects
*/
public void setRedirectStrategy(RedirectStrategy redirectStrategy);
/**
* Creates service URL for CAS authentication request.
* @param request the HTTP request
* @param response the HTTP response
* @return the service URL for CAS callback
*/
protected String createServiceUrl(HttpServletRequest request, HttpServletResponse response);
/**
* Creates full redirect URL including service parameter.
* @param serviceUrl the service URL for CAS callback
* @return complete CAS login URL with service parameter
*/
protected String createRedirectUrl(String serviceUrl);
/**
* Hook method called before redirect is performed.
* @param request the HTTP request
* @param response the HTTP response
*/
protected void preCommence(HttpServletRequest request, HttpServletResponse response);
/**
* Gets the encode service URL with session ID setting.
* @return true if service URL should include session ID
*/
protected boolean getEncodeServiceUrlWithSessionId();
}Usage Example:
@Bean
public CasAuthenticationEntryPoint casAuthenticationEntryPoint() {
CasAuthenticationEntryPoint entryPoint = new CasAuthenticationEntryPoint();
entryPoint.setLoginUrl("https://cas.example.com/cas/login");
entryPoint.setServiceProperties(serviceProperties());
entryPoint.setEncodeServiceUrlWithSessionId(false);
return entryPoint;
}Handles CAS gateway authentication by redirecting requests to CAS server with gateway=true parameter for optional SSO.
/**
* Filter that redirects requests to CAS server with gateway=true parameter.
* Enables optional Single Sign-On where authentication is attempted but not required.
*/
public final class CasGatewayAuthenticationRedirectFilter extends GenericFilterBean {
/** Request attribute key for gateway authentication marker */
public static final String CAS_GATEWAY_AUTHENTICATION_ATTR = "CAS_GATEWAY_AUTHENTICATION";
/**
* Creates gateway redirect filter with CAS login URL and service properties.
* @param casLoginUrl URL of CAS server login page
* @param serviceProperties service configuration for CAS
*/
public CasGatewayAuthenticationRedirectFilter(String casLoginUrl, ServiceProperties serviceProperties);
/**
* Processes request and performs gateway redirect if appropriate.
* @param req the servlet request
* @param res the servlet response
* @param chain the filter chain
* @throws IOException if I/O errors occur
* @throws ServletException if servlet errors occur
*/
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException;
/**
* Sets request matcher for determining when to perform gateway authentication.
* @param requestMatcher matcher for gateway authentication requests
*/
public void setRequestMatcher(RequestMatcher requestMatcher);
/**
* Sets request cache for storing original requests.
* @param requestCache cache for saving requests before redirect
*/
public void setRequestCache(RequestCache requestCache);
}Usage Example:
@Bean
public CasGatewayAuthenticationRedirectFilter gatewayFilter() {
CasGatewayAuthenticationRedirectFilter filter =
new CasGatewayAuthenticationRedirectFilter(
"https://cas.example.com/cas/login",
serviceProperties()
);
filter.setRequestMatcher(new AntPathRequestMatcher("/protected/**"));
return filter;
}Request matcher that delegates to GatewayResolver to prevent infinite gateway authentication loops.
/**
* Request matcher that uses GatewayResolver to determine if gateway authentication
* should be attempted, preventing infinite redirect loops.
*/
public final class CasGatewayResolverRequestMatcher implements RequestMatcher {
/**
* Creates gateway resolver request matcher with service properties.
* @param serviceProperties service configuration for CAS
*/
public CasGatewayResolverRequestMatcher(ServiceProperties serviceProperties);
/**
* Determines if the request matches gateway authentication criteria.
* @param request the HTTP request to evaluate
* @return true if gateway authentication should be attempted
*/
public boolean matches(HttpServletRequest request);
/**
* Sets gateway storage resolver for tracking gateway attempts.
* @param gatewayStorage resolver for managing gateway state
*/
public void setGatewayStorage(GatewayResolver gatewayStorage);
}Creates ServiceAuthenticationDetails objects for requests where service URL needs to be determined dynamically.
/**
* Authentication details source that creates ServiceAuthenticationDetails
* for dynamic service URL determination during CAS authentication.
*/
public class ServiceAuthenticationDetailsSource
implements AuthenticationDetailsSource<HttpServletRequest, ServiceAuthenticationDetails> {
/**
* Creates details source with service properties.
* @param serviceProperties base service configuration
*/
public ServiceAuthenticationDetailsSource(ServiceProperties serviceProperties);
/**
* Creates details source with custom artifact parameter name.
* @param serviceProperties base service configuration
* @param artifactParameterName custom artifact parameter name
*/
public ServiceAuthenticationDetailsSource(ServiceProperties serviceProperties, String artifactParameterName);
/**
* Builds authentication details from HTTP request.
* @param context the HTTP request
* @return ServiceAuthenticationDetails with dynamic service URL
*/
public ServiceAuthenticationDetails buildDetails(HttpServletRequest context);
}Example Spring Security configuration integrating CAS filters:
@Configuration
@EnableWebSecurity
public class CasWebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authz -> authz
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
)
.exceptionHandling(exceptions -> exceptions
.authenticationEntryPoint(casAuthenticationEntryPoint())
)
.addFilter(casAuthenticationFilter())
.addFilterBefore(gatewayFilter(), CasAuthenticationFilter.class);
return http.build();
}
@Bean
public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
CasAuthenticationFilter filter = new CasAuthenticationFilter();
filter.setAuthenticationManager(authenticationManager());
filter.setServiceProperties(serviceProperties());
filter.setAuthenticationDetailsSource(authenticationDetailsSource());
return filter;
}
@Bean
public ServiceAuthenticationDetailsSource authenticationDetailsSource() {
return new ServiceAuthenticationDetailsSource(serviceProperties());
}
}/login/cas/login/cas/proxyreceptorInstall with Tessl CLI
npx tessl i tessl/maven-org-springframework-security--spring-security-cas