Spring Boot
User Authentication
Security
Java
Programming Tips

How to find out the currently logged-in user in Spring Boot?

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

In Spring Boot applications, identifying the currently logged-in user is a common and important requirement, especially for applications involving user-specific content and actions. This process usually involves integration with Spring Security, a powerful and customizable authentication and access-control framework for Java applications. In this article, we will delve into how you can determine the currently logged-in user in Spring Boot, providing technical explanations, code examples, and considerations to ensure secure and efficient implementations.

Spring Security: An Overview

Spring Security is often integrated into a Spring Boot application to handle the authentication and authorization of users. It provides mechanisms for securing the application and obtaining user details via its rich features.

Key Spring Security Components

  • Authentication: The individual or entity's claim about its identity is validated here.
  • Principal: The currently logged-in user, stored in the SecurityContext.
  • SecurityContext: Stores security information (like the principal) for the current request.
  • UserDetails: An interface providing essential user information like username, password, and user authorities.

Obtaining the Currently Logged-in User

To access the currently logged-in user in a Spring Boot application, follow these steps:

Step 1: Configure Spring Security

Ensure your application is configured for security by setting up SpringSecurity configurations. Typically, you have an @Configuration class that extends WebSecurityConfigurerAdapter.

java
1@Configuration
2@EnableWebSecurity
3public class SecurityConfig extends WebSecurityConfigurerAdapter {
4
5    @Autowired
6    private UserDetailsService userDetailsService;
7
8    @Bean
9    public PasswordEncoder passwordEncoder() {
10        return new BCryptPasswordEncoder();
11    }
12
13    @Override
14    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
15        auth.userDetailsService(userDetailsService)
16            .passwordEncoder(passwordEncoder());
17    }
18    
19    @Override
20    protected void configure(HttpSecurity http) throws Exception {
21        http
22            .authorizeRequests()
23            .antMatchers("/admin/**").hasRole("ADMIN")
24            .antMatchers("/", "/home").permitAll()
25            .anyRequest().authenticated()
26            .and()
27            .formLogin()
28            .and()
29            .httpBasic();
30    }
31}

Step 2: Accessing the User

There are multiple ways to access the currently authenticated user in a Spring Boot application:

Method 1: Using the SecurityContextHolder

The SecurityContextHolder is the most common way to access the current security context.

java
1import org.springframework.security.core.Authentication;
2import org.springframework.security.core.context.SecurityContextHolder;
3import org.springframework.security.core.userdetails.UserDetails;
4
5public UserDetails getCurrentUser() {
6    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
7    if (authentication != null && authentication.getPrincipal() instanceof UserDetails) {
8        return (UserDetails) authentication.getPrincipal();
9    }
10    return null; // or throw an appropriate exception
11}

Method 2: Using @AuthenticationPrincipal

Spring allows the use of @AuthenticationPrincipal annotation to directly inject the authenticated UserDetails into controller methods.

java
1import org.springframework.security.core.annotation.AuthenticationPrincipal;
2import org.springframework.security.core.userdetails.UserDetails;
3import org.springframework.web.bind.annotation.GetMapping;
4import org.springframework.web.bind.annotation.RestController;
5
6@RestController
7public class UserController {
8
9    @GetMapping("/user")
10    public String currentUser(@AuthenticationPrincipal UserDetails userDetails) {
11        return userDetails.getUsername(); // Or any other property you'd like to access
12    }
13}

Method 3: Using @CurrentSecurityContext

The @CurrentSecurityContext annotation fetches the entire security context. You can work with it to access various parts, including the principal.

java
1import org.springframework.security.core.context.SecurityContext;
2import org.springframework.security.core.context.SecurityContextHolder;
3import org.springframework.security.core.annotation.CurrentSecurityContext;
4import org.springframework.web.bind.annotation.GetMapping;
5import org.springframework.web.bind.annotation.RestController;
6
7@RestController
8public class SecurityController {
9
10    @GetMapping("/userinfo")
11    public String getUserInfo(@CurrentSecurityContext(expression = "authentication") SecurityContext securityContext) {
12        return securityContext.getAuthentication().getName();
13    }
14}

Table: Methods to Retrieve Logged-in User

Method / AnnotationDescriptionUsage Example
SecurityContextHolderAccesses the security context manually.SecurityContextHolder.getContext().getAuthentication();
@AuthenticationPrincipalInjects current user directly into controller methods.@GetMapping("/user") public String user(@AuthenticationPrincipal UserDetails user)
@CurrentSecurityContextAccess security context, principal is manually extracted.@GetMapping("/userinfo") public String info(@CurrentSecurityContext(expression = "authentication") SecurityContext context)

Additional Considerations

  • Error Handling: Always consider handling scenarios where the authentication might be null when accessing the authentication.
  • Performance Optimization: Accessing the user directly in controllers using @AuthenticationPrincipal can help reduce boilerplate code and improve readability.
  • Security: Ensure that user roles and permissions are properly managed via Spring Security configurations, to avoid unauthorized access.

Conclusion

In Spring Boot applications, identifying the currently logged-in user is a common task that is handled in various ways using Spring Security. By understanding and implementing these methods, you can secure your application while efficiently accessing required user information. Ensure to understand the unique requirements of your application and choose the appropriate method that suits your architectural needs. Always test the security configurations to ensure that the application is protected against unauthorized access.


Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.