Secure Thymeleaf Templates with <sec:authorize>: A Practical Guide
Learn how to use Thymeleaf's Spring Security dialect to conditionally render UI elements based on authentication and role checks, with a working example, trade‑offs, and actionable steps.
10 Dec 2025, 01:20 UTC

Why Secure UI Rendering Matters
When a web app exposes sensitive data or actions, it’s not enough to protect the backend endpoints. The user interface must also hide or disable options that the current user shouldn’t see. Otherwise, a careless click or a simple URL tweak can reveal hidden links or trigger unintended actions. Thymeleaf’s built‑in support for Spring Security lets you declaratively enforce these rules directly in your templates.
The <sec:authorize> Attribute
The thymeleaf-extras-springsecurity5 dialect introduces the <sec:authorize> tag. It accepts a Spring Security expression and renders its body only if the expression evaluates to true. Because the expression is evaluated against the current Authentication object, you can check roles, authorities, or even custom predicates.
Typical Use‑Cases
- Show an “Admin Panel” link only to users with the
ADMINrole. - Hide a “Delete” button when the user lacks the
DELETE_PRIVILEGEauthority. - Render a fragment only for authenticated users, leaving it blank for guests.
Getting Started: Add the Dialect
- In a Maven project, add the dependency:
<dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity5</artifactId> <version>3.1.1.RELEASE</version> </dependency> - For Spring Boot 3.x, the dialect registers automatically. If you’re on an older Spring Boot or a plain Spring MVC setup, declare the dialect bean:
@Configuration public class ThymeleafConfig { @Bean public SpringSecurityDialect securityDialect() { return new SpringSecurityDialect(); } } - Ensure that Spring Security is on the classpath and that an
Authenticationobject is available in the request (standard Spring Security setup does this).
Concrete Example: Admin‑Only Section
Below is a minimal template fragment that displays a link only for users with the ADMIN role. The expression uses Spring Security’s hasRole function.
<sec:authorize access="hasRole('ADMIN')">
<a href="/admin">Admin Dashboard</a>
</sec:authorize>
When the template is rendered for a user without the ADMIN role, the entire <sec:authorize> block is omitted from the HTML sent to the browser.
Testing the Behavior
Using Spring's MockMvc, you can assert that the fragment appears or disappears as expected:
@SpringBootTest
@AutoConfigureMockMvc
class AdminPanelRenderingTest {
@Autowired
private MockMvc mockMvc;
@Test
void adminUserSeesPanel() throws Exception {
mockMvc.perform(get("/home").with(user("admin").roles("ADMIN")))
.andExpect(status().isOk())
.andExpect(content().string(containsString("Admin Dashboard")));
}
@Test
void regularUserDoesNotSeePanel() throws Exception {
mockMvc.perform(get("/home").with(user("user").roles("USER")))
.andExpect(status().isOk())
.andExpect(content().string(not(containsString("Admin Dashboard"))));
}
}
These tests confirm that the <sec:authorize> block behaves correctly for different authentication states.
Trade‑offs and Limitations
- Dependency Bloat: Adding the extras module increases the classpath. In micro‑service environments with strict size constraints, weigh the benefit against the additional jar.
- Expression Complexity: Overly complex expressions can degrade template readability. Keep expressions concise or move heavy logic to a service layer.
- Missing Security Context: If the template is rendered outside a security filter chain (e.g., during scheduled tasks),
<sec:authorize>will evaluate to false and may silently hide content. Verify that the context is present during rendering. - Case Sensitivity: The tag name is case‑sensitive. Using
<sec:Authorize>causes a parse error. Stick to lower‑case<sec:authorize>.
Actionable Checklist
- Include
thymeleaf-extras-springsecurity5in your build. - Confirm the dialect is registered (auto‑config in Spring Boot 3.x).
- Wrap UI elements in
<sec:authorize>with a clear expression. - Write unit or integration tests using
MockMvcto assert visibility for different roles. - Deploy and monitor: verify that unauthorized users never receive the protected fragments.
By following these steps, you can enforce UI‑level access control declaratively, keeping your templates clean and your security tight.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.