Apereo CAS Web Application Themes Support - Provides comprehensive theme resolution and management capabilities for the Central Authentication Service
npx @tessl/cli install tessl/maven-org-apereo-cas--cas-server-support-themes@7.2.0The CAS Themes Support library provides comprehensive theme management capabilities for the Central Authentication Service (CAS). It enables dynamic theme selection based on multiple strategies including registered service configurations, browser cookies, HTTP session attributes, request headers, and fixed configuration settings.
Gradle:
implementation 'org.apereo.cas:cas-server-support-themes:7.2.4'Maven:
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-support-themes</artifactId>
<version>7.2.4</version>
</dependency>// Main Configuration
import org.apereo.cas.config.CasThemesAutoConfiguration;
// Theme Sources
import org.apereo.cas.services.web.DefaultCasThemeSource;
import org.apereo.cas.services.web.AggregateCasThemeSource;
import org.apereo.cas.services.web.CasThemeResourceBundleMessageSource;
// Theme Resolvers
import org.apereo.cas.services.web.ChainingThemeResolver;
import org.apereo.cas.services.web.RegisteredServiceThemeResolver;
import org.apereo.cas.services.web.RequestHeaderThemeResolver;
// Configuration Properties
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.configuration.model.support.themes.ThemeProperties;
import org.apereo.cas.configuration.model.core.web.view.ViewProperties;
// CAS Services API (for service-based theme resolution)
import org.apereo.cas.services.ServicesManager;
import org.apereo.cas.services.WebBasedRegisteredService;
import org.apereo.cas.authentication.AuthenticationServiceSelectionPlan;
import org.apereo.cas.authentication.principal.Service;
// Spring Framework Types
import org.springframework.ui.context.ThemeSource;
import org.springframework.web.servlet.ThemeResolver;
import org.springframework.web.servlet.theme.AbstractThemeResolver;
import org.springframework.ui.context.support.ResourceBundleThemeSource;import org.apereo.cas.services.web.ChainingThemeResolver;
import org.apereo.cas.services.web.DefaultCasThemeSource;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.springframework.web.servlet.theme.CookieThemeResolver;
import org.springframework.web.servlet.theme.SessionThemeResolver;
// Basic theme source setup
CasConfigurationProperties casProperties = // ... obtained from Spring context
DefaultCasThemeSource themeSource = new DefaultCasThemeSource(casProperties);
// Create a chaining theme resolver with multiple strategies
ChainingThemeResolver chainResolver = new ChainingThemeResolver();
chainResolver.setDefaultThemeName("cas-theme-default");
// Add cookie-based theme resolution
CookieThemeResolver cookieResolver = new CookieThemeResolver();
cookieResolver.setDefaultThemeName("cas-theme-default");
chainResolver.addResolver(cookieResolver);
// Add session-based theme resolution
SessionThemeResolver sessionResolver = new SessionThemeResolver();
sessionResolver.setDefaultThemeName("cas-theme-default");
chainResolver.addResolver(sessionResolver);
// Resolve theme from HTTP request
String themeName = chainResolver.resolveThemeName(request);
System.out.println("Resolved theme: " + themeName);
// Get theme resources
Theme theme = themeSource.getTheme(themeName);
MessageSource messageSource = theme.getMessageSource();
String welcomeMessage = messageSource.getMessage("login.welcome", null,
"Welcome", request.getLocale());The CAS Themes Support library is built around several key components:
CasThemesAutoConfiguration) that automatically sets up theme resolution based on propertiesDefaultCasThemeSource, AggregateCasThemeSource)ChainingThemeResolver)Spring Boot auto-configuration that sets up theme resolution beans automatically based on CAS configuration properties.
@AutoConfiguration
@ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.Thymeleaf)
public class CasThemesAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "casThemeSource")
@RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
public ThemeSource themeSource(CasConfigurationProperties casProperties);
@Bean
@ConditionalOnMissingBean(name = "casThemeResolver")
@RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
public ThemeResolver themeResolver(
ObjectProvider<CasConfigurationProperties> casProperties,
ObjectProvider<AuthenticationServiceSelectionPlan> authenticationRequestServiceSelectionStrategies,
ObjectProvider<ServicesManager> servicesManager);
}Theme source implementations that load and manage theme properties and resources from various locations.
public class DefaultCasThemeSource extends ResourceBundleThemeSource {
public DefaultCasThemeSource(CasConfigurationProperties casProperties);
@Override
protected MessageSource createMessageSource(@Nonnull String basename);
}
public class AggregateCasThemeSource extends ResourceBundleThemeSource {
public AggregateCasThemeSource(CasConfigurationProperties casProperties);
@Override
protected MessageSource createMessageSource(@Nonnull String basename);
}Chain-based theme resolution system that evaluates multiple resolution strategies in priority order.
public class ChainingThemeResolver extends AbstractThemeResolver {
public ChainingThemeResolver addResolver(ThemeResolver r);
@Override
public String resolveThemeName(@Nonnull HttpServletRequest httpServletRequest);
@Override
public void setThemeName(@Nonnull HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, String s);
}Advanced theme resolution based on registered service configurations, supporting Groovy scripts and HTTP URLs for dynamic theme selection.
public class RegisteredServiceThemeResolver extends AbstractThemeResolver {
public RegisteredServiceThemeResolver(
ObjectProvider<ServicesManager> servicesManager,
ObjectProvider<AuthenticationServiceSelectionPlan> authenticationRequestServiceSelectionStrategies,
ObjectProvider<CasConfigurationProperties> casProperties);
@Override
public String resolveThemeName(@Nonnull HttpServletRequest request);
}Service-Based Theme Resolution
Simple theme resolution that extracts theme names from HTTP request headers.
public class RequestHeaderThemeResolver extends AbstractThemeResolver {
public RequestHeaderThemeResolver(String themeHeaderName);
@Override
public String resolveThemeName(HttpServletRequest request);
}// Spring Framework Types
interface ThemeSource {
Theme getTheme(String themeName);
}
interface Theme {
String getName();
MessageSource getMessageSource();
}
interface ThemeResolver {
String resolveThemeName(HttpServletRequest request);
void setThemeName(HttpServletRequest request, HttpServletResponse response, String themeName);
}
abstract class AbstractThemeResolver implements ThemeResolver {
String getDefaultThemeName();
void setDefaultThemeName(String defaultThemeName);
}
class ResourceBundleThemeSource implements ThemeSource {
String getBasenamePrefix();
void setBasenamePrefix(String basenamePrefix);
protected MessageSource createMessageSource(String basename);
}
// CAS Services Types
interface Service {
String getId();
}
interface ServicesManager {
RegisteredService findServiceBy(Service service);
}
class WebBasedRegisteredService extends BaseRegisteredService {
String getTheme();
void setTheme(String theme);
RegisteredServiceAccessStrategy getAccessStrategy();
}
interface AuthenticationServiceSelectionPlan {
Service resolveService(Service service);
}
// CAS Configuration Types
class CasConfigurationProperties {
ThemeProperties getTheme();
ViewProperties getView();
TgcProperties getTgc();
}
class ThemeProperties {
String getDefaultThemeName(); // Default: "cas-theme-default"
String getParamName(); // Default: "theme"
}
class ViewProperties {
List<String> getTemplatePrefixes();
ThemeSourceTypes getThemeSourceType(); // Default: DEFAULT
enum ThemeSourceTypes {
DEFAULT, // Use DefaultCasThemeSource
AGGREGATE // Use AggregateCasThemeSource
}
}
class TgcProperties {
String getDomain();
boolean isHttpOnly();
String getMaxAge();
String getPath();
boolean isSecure();
}
// Spring Web Types
class HttpServletRequest {
String getHeader(String name);
String getQueryString();
Locale getLocale();
void setAttribute(String name, Object value);
}
class HttpServletResponse {
// HTTP response methods
}
interface MessageSource {
String getMessage(String code, Object[] args, String defaultMessage, Locale locale);
}
class StaticMessageSource implements MessageSource {
void addMessage(String code, Locale locale, String msg);
}