'Spring boot security, always redirects to login page, if navigate through address bar
I have a react project, and the security works fine untill I navigate within page - i.e. clicking buttons etc. But, if I refresh page, or input url directly into adress field, it always navigates to login form. This is my security config:
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic()
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.logout()
.and()
.csrf().disable();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/v2/api-docs",
"/configuration/ui",
"/swagger-resources/**",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**");
web.ignoring().antMatchers("/rest/system/getVersion");
}
}
This is restAuthenticationEntryPoint -
@Slf4j
@Component
@RequiredArgsConstructor
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
private final ResponseWrapMessage responseWrapMessage;
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
log.error(e.getLocalizedMessage(), e);
BaseResponse baseResponse = new BaseResponse(UNKNOWN_ERROR, e.getLocalizedMessage());
insufficientAuthenticationWrapper(baseResponse, e);
responseWrapMessage.wrap(httpServletResponse, baseResponse);
}
private void insufficientAuthenticationWrapper(BaseResponse baseResponse, AuthenticationException e) {
if (e instanceof InsufficientAuthenticationException) {
baseResponse.setContent(CREDENTIAL_NO_VALID);
}
}
}
This is accessDeniedHandler:
@Slf4j
@Component
@RequiredArgsConstructor
public class RestAccessDeniedHandler implements AccessDeniedHandler {
private final ResponseWrapMessage responseWrapMessage;
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
log.error(accessDeniedException.getLocalizedMessage(), accessDeniedException);
BaseResponse baseResponse = new BaseResponse(UNKNOWN_ERROR, accessDeniedException.getLocalizedMessage());
responseWrapMessage.wrap(response, baseResponse);
}
}
How can it be changed? I want to persist session, untill I do the logout.
UPDATE: I see that cookie JSESSIONID is set on the logine page like -
set-cookie: JSESSIONID=9E3BD2B1CF7C69A49902DAA7E71E393E; Path=/mctm-bh; HttpOnly
And then it is sent out when I navigate pressing buttons within the page -
Cookie: JSESSIONID=9E3BD2B1CF7C69A49902DAA7E71E393E
But if I press enter in the address URL then it is NOT sent out, and hence I am redirected to login page
How can it be changed? Maybe I there is some problem with the cookie - like there is now expires attribute. But.. specification does not say that it should be additionally customized and also it is not clear how to do it.
!UPDATE2! I heard, that it is a common problem with basic authorization. If we authorise with 'Authorization: basic ...' then browser saves auth in some cash. And that cash is invalidated if we type something in browser address field. And the way out is not to use basic auth, and to migrate as an option to spring tokens solution. And some more details could also be found here: https://habr.com/ru/post/488388/
Solution 1:[1]
I suggest you check that your session tracking mechanics is working, e.g. check that you have cookies allowed in your browser, and define the tracking-mode parameter explicitly in the application.properties:
server.servlet.session.tracking-modes=COOKIE
This chooses where to store the JSESSIONID — in the cookie
Solution 2:[2]
Typing in the Address bar is equivalent to creating a new session/ or opening the link in a new tab. This can be one reason why it is asking for a new log-in every time you navigate through the address bar.
Solution 3:[3]
I heard, that it is a common problem with basic authorization. If we authorise with 'Authorization: basic ...' then browser saves auth in some cash. And that cash is invalidated if we type something in browser address field. And the way out is not to use basic auth, and to migrate as an option to spring tokens solution. And some more details could also be found here: https://habr.com/ru/post/488388/
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Mukhar Jain |
Solution 3 | Dmitry Bakhtiarov |