Spring Security provides various ways to access the details of the authenticated user in your application. This information can be useful for authorization purposes, personalization, auditing, and more. In this article, we’ll explore different approaches to retrieve user information in Spring Security.

1. Using SecurityContextHolder programmatically

The SecurityContextHolder is a static utility class that provides access to the SecurityContext object, which holds the Authentication object containing the user’s details. You can use it anywhere in the application. Here’s an example:

Java
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName();
Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();

This approach allows you to retrieve the username and granted authorities (roles) of the authenticated user. However, it’s considered a low-level approach and not recommended for use in web applications.

To improve this snippet. first check if there is an authenticated user before trying to access it:

Java
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (!(authentication instanceof AnonymousAuthenticationToken)) {
    String currentUserName = authentication.getName();
    return currentUserName;
}

2. Using @AuthenticationPrincipal in Controller

Spring Security provides the @AuthenticationPrincipal annotation, which can be used to retrieve the UserDetails object directly in your controller method. Here’s an example:

Java
@GetMapping("/username")
public String getCurrentUserName(@AuthenticationPrincipal UserDetails userDetails) {
    return userDetails.getUsername();
}

This approach is more concise and easier to use than the SecurityContextHolder approach. It automatically resolves the UserDetails object from the Authentication object and injects it into the method parameter.

2.1. Accessing User Details from UserDetailsService

If you need to access user details beyond the standard UserDetails interface, you can retrieve the UserDetails object from the UserDetailsService. Here’s an example:

Java
@Autowired
private UserDetailsService userDetailsService;

@GetMapping("/roles")
public Collection<? extends GrantedAuthority> getUserRoles(
        @AuthenticationPrincipal String username) {
    UserDetails userDetails = userDetailsService.loadUserByUsername(username);
    return userDetails.getAuthorities();
}

In this example, we’re using the @AuthenticationPrincipal annotation to retrieve the username and then using the UserDetailsService to load the full UserDetails object for that username.

2.2. Using Custom AuthenticationPrincipal

Spring Security allows you to use a custom principal object instead of the default UserDetails. This can be useful if you need to store additional user information in the principal object. Here’s an example:

Java
// Custom User class
public class CustomUser implements UserDetails { ... }

// Controller method
@GetMapping("/email") 
public String getUserEmail(@AuthenticationPrincipal CustomUser customUser) {
    return customUser.getEmail();
}

In this example, we’re using a custom CustomUser class that implements the UserDetails interface and extends it with additional properties (e.g., email). We can then retrieve the custom user object directly in our controller method using the @AuthenticationPrincipal annotation.

3. Using Principal as argument in Controller

Define the principal directly as a method argument, and the framework will correctly resolve it:

Java
@RestController
public class GetUserWithPrincipalController {

    @GetMapping(value = "/username")
    public String currentUserName(Principal principal) {
        return principal.getName();
    }
}

4. Accessing Authentication as argument

You can also access the Authentication object directly in your controller method and extract the UserDetails object from it. Here’s an example:

Java
@GetMapping("/info")
public String getUserInfo(Authentication authentication) {
    UserDetails userDetails = (UserDetails) authentication.getPrincipal();
    return userDetails.getUsername() + " " + userDetails.getAuthorities();
}

This approach is more verbose than using the @AuthenticationPrincipal annotation, but it provides more flexibility if you need to access other properties of the Authentication object.

5. Using SecurityContext in Method Argument

Similar to accessing the Authentication object directly, you can also access the SecurityContext object in your controller method and retrieve the Authentication object from it. Here’s an example:

Java
@GetMapping("/details")
public String getUserDetails(SecurityContext securityContext) {
    Authentication authentication = securityContext.getAuthentication();
    UserDetails userDetails = (UserDetails) authentication.getPrincipal();
    return userDetails.getUsername() + " " + userDetails.getPassword();
}

This approach is even more verbose than accessing the Authentication object directly, but it can be useful in certain scenarios where you need to access other properties of the SecurityContext object.

6. Accessing the Current Logged-In User in JSP:

In a Spring Security-enabled application, you can access the currently authenticated user (principal) in JSP pages using the Spring Security taglib. Here’s how you can do it:

  1. First, make sure you have the Spring Security taglib declared in your JSP file:
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
  1. Next, you can refer to the principal (logged-in user) using the sec:authentication attribute:
<security:authorize access="isAuthenticated()">
    Welcome, <span sec:authentication="name"></span>
</security:authorize>

The above code snippet will display the username of the currently logged-in user

7. Accessing the Current Logged-In User in Thymeleaf:

Thymeleaf provides similar functionality for accessing the logged-in user. You can use the Thymeleaf Extras module along with the Spring Security Dialect. Here’s how:

1. First, add the Thymeleaf Extras module to your project (if you haven’t already). Use the latest version:

XML
<!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf-spring6 -->
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf-spring6</artifactId>
    <version>3.1.2.RELEASE</version>
</dependency>


<!-- https://mvnrepository.com/artifact/org.thymeleaf.extras/thymeleaf-extras-springsecurity6 -->
<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity6</artifactId>
    <version>3.1.2.RELEASE</version>
</dependency>

2. In your Thymeleaf template, use the thymeleaf-extras-springsecurity5 namespace:

HTML
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<!-- ... other HTML content ... -->
<body>
    <div sec:authorize="isAuthenticated()">
        Welcome, <span sec:authentication="name"></span>
    </div>
</body>
</html>

Key terminologies:

  • SecurityContextHolder: This class provides access to the security context, which holds information about the current user’s authentication and authorization.
  • Principal: Represents the currently authenticated user. It can be obtained directly as a method argument in a controller.
  • Authentication: Contains information about the current user’s authentication status. It includes the principal (user) and their granted authorities.
  • UserDetails: Represents the user’s details, such as username, password, and authorities. It’s an interface that you can implement to load user-specific data from your data store.

Conclusion

Spring Security provides various approaches to retrieve user information in your application. The choice of approach depends on your specific requirements and preferences. The @AuthenticationPrincipal annotation is generally the simplest and most recommended approach for most use cases. However, the other approaches can be useful in certain scenarios or if you need to access additional information beyond the standard UserDetails interface.

By |Last Updated: May 10th, 2024|Categories: Spring Security|