I have setup a spring boot backend with a react frontend. I want to use sessions, and have chosen Redis to do this.
The issue is that my chrome dev tools shows that there are no cookies being added, but in my redis-cli it shows that there are cookies. The issue no arises cause I want to send information using axios with withCredentials: true
, but nothing will show up since there are no cookies in Chrome.
I won’t include the import statements as they may clutter the page.
Main
@SpringBootApplication
@EnableRedisHttpSession
public class LetstalkstartApplication {
public static void main(String[] args) {
SpringApplication.run(LetstalkstartApplication.class, args);
}
}
Security Filter Chain
@Configuration
@EnableWebSecurity
public class SecurityConfig {
private final UserDetailsServiceImpl userDetailsServiceImpl;
private final CustomLogoutHandler logoutHandler;
private final UserDetailsService userDetailsService;
public SecurityConfig(UserDetailsServiceImpl userDetailsServiceImpl,
CustomLogoutHandler logoutHandler, UserDetailsService userDetailsService) {
this.userDetailsServiceImpl = userDetailsServiceImpl;
this.logoutHandler = logoutHandler;
this.userDetailsService = userDetailsService;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return
http
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(
req -> req.requestMatchers("/login/**", "/register/**")
.permitAll()
.requestMatchers("/admin_only").hasAnyAuthority("ADMIN")
.requestMatchers("/getinfo").authenticated()
.anyRequest().authenticated()
).userDetailsService(userDetailsServiceImpl)
.logout(l -> l.logoutUrl("/logout")
.addLogoutHandler(logoutHandler)
.logoutSuccessHandler(
(request, response, authentication) -> SecurityContextHolder.clearContext()
))
.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
return configuration.getAuthenticationManager();
}
}
Endpoints:
@PostMapping("/register")
public ResponseEntity<AuthenticationResponse> register(
@RequestBody User request
) {
return ResponseEntity.ok(authenticationService.register(request));
}
@PostMapping("/login")
public ResponseEntity<AuthenticationResponse> login(
HttpSession session,
@RequestBody User request,
HttpServletResponse httpResp
) {
AuthenticationResponse response = authenticationService.authenticate(request);
if (response != null && response.isSuccess()) { // Check if authentication was successful
// Store user information in the session
Cookie sessionCookie = new Cookie("SESSION_ID", session.getId());
sessionCookie.setHttpOnly(true); // Make it HTTP-only
sessionCookie.setSecure(false); // Make it secure
sessionCookie.setPath("/"); // Set the path for the cookie
// Add the cookie to the response
httpResp.addCookie(sessionCookie);
UserDetails user = userDetailsService.loadUserByUsername(request.getUsername());
// session.setUsername(user.getUsername());
}
return ResponseEntity.ok(response);
}
@GetMapping("/getinfo")
public ResponseEntity<AuthenticationResponse> getUserInfo(HttpServletRequest request) {
AuthenticationResponse authenticationResponse = new AuthenticationResponse();
if (request != null) {
authenticationResponse.setSuccess(true);
authenticationResponse.setMessage("Success!");
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
System.out.println("Cookie Name: " + cookie.getName() + ", Cookie Value: " + cookie.getValue());
}
}
HttpSession session = request.getSession(false);
if (session != null) {
System.out.println("Session ID: " + session.getId());
System.out.println("Session Attributes: ");
session.getAttributeNames().asIterator().forEachRemaining(name ->
System.out.println(name + ": " + session.getAttribute(name))
);
} else {
System.out.println("No active session found");
}
} else {
authenticationResponse.setSuccess(false);
authenticationResponse.setMessage("Failed to retrieve user information");
}
return ResponseEntity.ok(authenticationResponse);
}
I’ve been using the /getinfo
endpoint to test if the cookies are actually working, it’s not meant to serve any greater function within the app.
Here’s my auth service:
public class AuthenticationService {
private final UserRepository repository;
private final PasswordEncoder passwordEncoder;
private final AuthenticationManager authenticationManager;
private final UserDetailsService userDetailsService;
public AuthenticationService(UserRepository repository, PasswordEncoder passwordEncoder, JwtService jwtService, AuthenticationManager authenticationManager, TokenRepository tokenRepository, UserDetailsService userDetailsService) {
this.repository = repository;
this.passwordEncoder = passwordEncoder;
this.authenticationManager = authenticationManager;
this.userDetailsService = userDetailsService;
}
public AuthenticationResponse register(User request) {
User user = new User();
user.setFirstName(request.getFirstName());
user.setLastName(request.getLastName());
user.setUsername(request.getUsername());
user.setPassword(passwordEncoder.encode(request.getPassword()));
user.setEmail(request.getEmail());
user.setRole(request.getRole());
user = repository.save(user);
AuthenticationResponse response = new AuthenticationResponse();
response.setMessage("Registration Successful");
response.setSuccess(true);
return response;
}
public AuthenticationResponse authenticate(User request) {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
request.getUsername(), request.getPassword()
)
);
System.out.println(" in authentication ");
UserDetails userDetails = userDetailsService.loadUserByUsername(request.getUsername());
if (userDetails != null && passwordEncoder.matches(request.getPassword(), userDetails.getPassword())) {
AuthenticationResponse authenticationResponse = new AuthenticationResponse();
authenticationResponse.setSuccess(true);
authenticationResponse.setMessage("Authentication successful");
return authenticationResponse;
}
AuthenticationResponse authenticationResponse = new AuthenticationResponse();
authenticationResponse.setSuccess(false);
authenticationResponse.setMessage("Authentication failed");
return authenticationResponse;
}
}
I tried to log in as an example and redis showed after running redis-cli
127.0.0.1:6379> keys *
1) "spring:session:sessions:84c2f69f-f969-4427-b74b-e6e783c6053a"
However, in chrome the cookies page is empty completely. I followed a youtube tutorial and when they log in with the premade page given via spring boot it adds it to the cookies. I’m confused as to what the difference could be.
Login page for frontend in react:
class AuthService {
login(username, password) {
return axios.post(API_URL + "/login",
{
username: username,
password: password
},
{
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
},
)
.then(response => {
console.log("response: ", response)
if (response.status == 200) {
console.log("Logged in")
} else {
console.log("Couldn't log in")
}
return response.data;
});
}
// get info call
const getUserInfo = () => {
axios.get(API_URL + "/getinfo", {
withCredentials: true,
});
};
Thank you all
I tried following a youtube tutorial which led to the right result, but when I did the same stuff in my own page it didn’t work. I initially thought this may be an issue with my log in page, but if that’s the case why can I still see a session added via the redis-cli command. Just confused why it’s not showing up in chrome at all.