I am trying to access HttpServletRequest
or HttpSession
in my service component.
The service component is where github OAuth2 login is being processed.
Below is my service code.
@RequiredArgsConstructor
@Service
public class GithubOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
private final UserRepository userRepository;
private final JwtTokenUtil jwtTokenUtil;
private final HttpServletRequest request;
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2UserService<OAuth2UserRequest, OAuth2User> delegate = new DefaultOAuth2UserService();
OAuth2User oAuth2User = delegate.loadUser(userRequest);
String userNameAttributeName = userRequest.getClientRegistration()
.getProviderDetails().getUserInfoEndpoint()
.getUserNameAttributeName();
OAuthAttributes attributes = OAuthAttributes.ofGithub(userNameAttributeName, oAuth2User.getAttributes());
User user = saveOrFindUser(attributes);
request.setAttribute("token", jwtTokenUtil.generateAccessToken(user.getId(), user.getRole()));
return new DefaultOAuth2User(
Collections.singleton(new SimpleGrantedAuthority(user.getRole().name())),
attributes.getAttributes(),
attributes.getNameAttributeKey()
);
}
private User saveOrFindUser(OAuthAttributes attributes) {
Optional<User> optionalUser = userRepository.findByEmail(attributes.getEmail());
if(optionalUser.isPresent()) {
return optionalUser.get();
} else {
return userRepository.save(attributes.toEntity());
}
}
}
And below is my Spring Security configuration class.
@RequiredArgsConstructor
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final GithubOAuth2UserService githubOAuth2UserService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.headers().frameOptions().disable()
.and().csrf().disable()
.cors().configurationSource(corsConfigurationSource())
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/v1/health-check")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/")
.and()
.oauth2Login()
.successHandler(authenticationSuccessHandler())
.failureHandler(authenticationFailureHandler())
.userInfoEndpoint()
.userService(githubOAuth2UserService);
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.addAllowedOriginPattern("*");
configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*");
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Bean
public AuthenticationFailureHandler authenticationFailureHandler() {
return new GithubOAuthExceptionHandler();
}
@Bean
public AuthenticationSuccessHandler authenticationSuccessHandler() {
return new GithubOAuthOnSuccessHandler();
}
}
I have tried to autowire HttpSession
and HttpServletRequest
using Lombok's @RequiredArgsConstructor
, and also tried the way below.
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
And I am getting the error below.
java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
I am trying to access HttpServletRequest
or HttpSession
in a @Service
component, but I cannot understand why this error is occuring.
Are there any extra configurations to access these classes in components?
I am using spring boot 2.4.3.