Search code examples
springspring-bootauthenticationspring-securitythymeleaf

Why is #authentication always null in thymeleaf despite user being logged in and readable by SecurityContextHolder?


I have a problem with my Spring Boot project using Spring Security and Thymeleaf. In Thymeleaf files, security variable ${#authentication} is always null. Also, adding

sec:authentication="isAnonymous()"

or

sec:authentication="isAuthenticated()"

to an html element in thymeleaf doesn't change anything and the elements with those attributes are visible all the time while being logged out and while being logged in.

I know that controllers have no problem authenticating user because in HomeController.java below I pass a variable to model after taking it from currently logged user by SecurityContextHolder. I print it in Thymeleaf with ${name} and it prints as it should. That is also how I know whether I am logged in or logged out and I know that logging in works and user can be authenticated by the controller.

So controllers have no problem authenticating logged user but Thymeleaf just can't do it.

Maybe it is worth mentioning that my Thymeleaf html files are in resources/templates path.

Any help will be greatly appreciated. Thank you in advance.

SecurityConfig.java:

@Configuration
@EnableWebSecurity
public class SecurityConfig{
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.formLogin(form -> form.loginPage("/login"));
        return http.build();
    }
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

HomeController.java:

@Controller
public class HomeController {

    @GetMapping("/")
    public String hello(Model model){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        model.addAttribute("name",authentication.getName());
        return "test/home";
    }
}

home.html:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
    <title>Home</title>
</head>
<body>
<div>
    <span th:text="${#authentication == null ? 'authentNull' : 'authentNotNull'}"></span>
    <span th:text="${#authorization == null ? 'authNull' : 'authNotNull'}"></span>
    <span sec:authentication="isAnonymous()" th:text="${'anonymous'}">anonymous</span>
    <span sec:authentication="isAuthenticated()" th:text="${'authenticated'}">authenticated</span>
    <h1 th:text="${name}"></h1>
</div>
</body>
</html>

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.2</version>
        <relativePath/>
    </parent>
    <groupId>pl.edziennik</groupId>
    <artifactId>edziennik</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>edziennik</name>
    <description>E-dziennik</description>
    <properties>
        <java.version>17</java.version>
        <spring.version>5.3.10.RELEASE</spring.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.1-api</artifactId>
            <version>1.0.2.Final</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.26</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>3.0.4</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
            <version>3.1.2</version>
        </dependency>
        <dependency>
            <groupId>nz.net.ultraq.thymeleaf</groupId>
            <artifactId>thymeleaf-layout-dialect</artifactId>
            <version>3.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity5</artifactId>
            <version>3.1.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-taglibs</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

the output of the Thymeleaf (admin is username of logged user):

authentNull authNull anonymous authenticated

admin

I tried changing many many things in those files, especially with pom.xml but none of them worked. For example, I tried switching to thymeleaf-extras-springsecurity4. Also, I tried chaning the links in tag in the html file. And many other things i found on stackoverflow. None of them worked.


Solution

  • The problem was that thymeleaf-extras-springsecurity5 is deprecated in relation to my project's version. I needed to use thymeleaf-extras-springsecurity6 instead.

    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity6</artifactId>
        <version>3.1.1.RELEASE</version>
    </dependency>