Vincent F Vincent F - 1 year ago 72
Java Question

bypass CAS to get un/secured health infos from Spring boot app

I have a Spring Boot app using CAS WebSecurity to make sure that all incoming non authenticated requests are redirected to a common login page.

public class CASWebSecurityConfig extends WebSecurityConfigurerAdapter {

I want to expose health endpoints through actuator, and added the relevant dependency. I want to bypass the CAS check for these /health URL which are going to be used by monitoring tools, so in the configure method, I have added :


This works, but now I want to tweak it further :

  • detailed health status (ie "full content" as per the docs) should be accessible only to some specific monitoring user, for which credentials are provided in property file.

  • if no authentication is provided, then "status only" should be returned.

Following, I've configured the properties as below, so that it should work : true false

But I have a problem with how I configure the credentials... following , I added in my config file : admin
security.user.password: secret

But it's not working - and when I don't put the properties, I don't see the password generated in logs.

So I'm trying to put some custom properties like

healthcheck.username: healthCheckMonitoring
healthcheck.password: healthPassword

and inject these into my Security config so that configureGlobal method becomes :

public void configureGlobal(AuthenticationManagerBuilder auth,
CasAuthenticationProvider authenticationProvider) throws Exception {


and in the configure method, I change the config for the URL pattern to :


With that config, I get full content when authenticated, but logically, I don't get any status (UP or DOWN) when I'm not authenticated, because the request doesn't even reach the endpoint : it is intercepted and rejected by the security config.

How can I tweak my Spring Security config so that this works properly ? I have the feeling I should somehow chain the configs, with the CAS config first allowing the request to go through purely based on the URL, so that the request then hits a second config that will do basic http authentication if credentials are provided, or let the request hit the endpoint unauthenticated otherwise, so that I get the "status only" result.. But at the same time, I'm thinking Spring Boot can manage this correctly if I configure it properly..

Thanks !

Answer Source

Solution is not great, but so far, that's what works for me :

in my config (only the relevant code):

public class CASWebSecurityConfig extends WebSecurityConfigurerAdapter {

protected void configure(HttpSecurity http) throws Exception {
    //disable HTTP Session management
        .securityContextRepository(new NullSecurityContextRepository())

    http.requestCache().requestCache(new NullRequestCache());

    //no security checks for health checks



    http // login configuration

Then I added a specific filter :

public class HealthcheckSimpleStatusFilter  extends GenericFilterBean {

private final String AUTHORIZATION_HEADER_NAME="Authorization";

private final String URL_PATH = "/health";

private String username;

private String password;

private String healthcheckRole="ADMIN";

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    throws IOException, ServletException {
    HttpServletRequest httpRequest = this.getAsHttpRequest(request);

    //doing it only for /health endpoint.
    if(URL_PATH.equals(httpRequest.getServletPath())) {

        String authHeader = httpRequest.getHeader(AUTHORIZATION_HEADER_NAME);

        if (authHeader != null && authHeader.startsWith("Basic ")) {
            String[] tokens = extractAndDecodeHeader(authHeader);
            if (tokens != null && tokens.length == 2 && username.equals(tokens[0]) && password.equals(tokens[1])) {
                createUserContext(username, password, healthcheckRole, httpRequest);
            } else {
                throw new BadCredentialsException("Invalid credentials");
    chain.doFilter(request, response);

 * setting the authenticated user in Spring context so that {@link HealthMvcEndpoint} knows later on that this is an authorized user
 * @param username
 * @param password
 * @param role
 * @param httpRequest
private void createUserContext(String username, String password, String role,HttpServletRequest httpRequest) {
    List<GrantedAuthority> authoritiesForAnonymous = new ArrayList<>();
    authoritiesForAnonymous.add(new SimpleGrantedAuthority("ROLE_" + role));
    UserDetails userDetails = new User(username, password, authoritiesForAnonymous);
    UsernamePasswordAuthenticationToken authentication =
        new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));

private HttpServletRequest getAsHttpRequest(ServletRequest request) throws ServletException {
    if (!(request instanceof HttpServletRequest)) {
        throw new ServletException("Expecting an HTTP request");
    return (HttpServletRequest) request;

private String[] extractAndDecodeHeader(String header) throws IOException {
    byte[] base64Token = header.substring(6).getBytes("UTF-8");

    byte[] decoded;
    try {
        decoded = Base64.decode(base64Token);
    } catch (IllegalArgumentException var7) {
        throw new BadCredentialsException("Failed to decode basic authentication token",var7);

    String token = new String(decoded, "UTF-8");
    int delim = token.indexOf(":");
    if(delim == -1) {
        throw new BadCredentialsException("Invalid basic authentication token");
    } else {
        return new String[]{token.substring(0, delim), token.substring(delim + 1)};

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download