21

I am using a working JWT authentication of my web application with the following configuration:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
      .csrf().disable()
      .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
      .and()
      .exceptionHandling()
      .authenticationEntryPoint(
          (req, rsp, e) -> p.sendError(HttpServletResponse.SC_UNAUTHORIZED))
      .and()
      .addFilter(new UsernamePasswordAuthenticationFilter(authenticationManager(),
          jwtConfig))
      .addFilterAfter(new JwtTokenAuthenticationFilter(jwtConfig),
          UsernamePasswordAuthenticationFilter.class)
      .authorizeRequests()
      .antMatchers(HttpMethod.POST, jwtConfig.getUri()).permitAll()
      .anyRequest().authenticated();
}

As of SessionCreationPolicy.STATELESS i am expecting that Spring will not create a session itself. However, if i access any other resource than /login, i still see the following entry in the response header:

set-cookie: JSESSIONID=...; Path=/; HttpOnly

Can someone explain where this is coming from (maybe not from Spring) and if it does still come from Spring what needs to be changed?

Edit:

Testing in my controller, the session is still injected as indicated by the above token being present. I still have no clue where this is coming from.

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public void create(HttpSession session) {
    if (session != null) {
        System.out.println("Session is existing"); // executes
    }
}
Glains
  • 2,773
  • 3
  • 16
  • 30
  • 1
    in the doc it says **STATELESS Spring Security will never create an HttpSession and it will never use it to obtain the SecurityContext** , which i suppose is overridden by the order of your lambdas. Don't ask me for the working order, though :/ – Gewure Sep 30 '18 at 00:15
  • 1
    @Gewure Thanks a lot, I'll try to play around a bit. Maybe that helps! – Glains Sep 30 '18 at 00:19
  • 2
    You using JSPs perhaps? They _love_ creating sessions. – Boris the Spider Sep 30 '18 at 14:51
  • @BoristheSpider Not using JSPs, but good point! – Glains Oct 01 '18 at 20:01
  • @Gewure Reordering did not help, but thanks for you effort! – Glains Oct 01 '18 at 20:02
  • 2
    The session will always be injected (and created if one doesn't exists) if you request that, that has nothing to do with setting Spring Security to stateless. That is only a setting for Spring Security NOT the remainder of your application. If you are using JSP you will get a session always and depending on your controllers that also might create a session. – M. Deinum Oct 02 '18 at 09:43
  • @M.Deinum Is there a possibility to disable that globally or shouldnt i bother with this and just ignore that? – Glains Oct 02 '18 at 10:26
  • The only way would be to hack into your servlet container and prevent it there, but why bother... Currently you are doing it yrouself (I suspect) or another filter in your change. You can change your post method to use the `HttpServeltRequest` and use `getSession(false)` to prevent session instantiation. When defining it as an argument it will automatically create one. – M. Deinum Oct 02 '18 at 10:28
  • @M.Deinum I wondered whether it was good or bad to have the session id included in the response body, since I don't need it. – Glains Oct 02 '18 at 18:48
  • 1
    Well apparently you do need it else a session wouldn't be created. – M. Deinum Oct 03 '18 at 07:17

5 Answers5

6

Your current configuration (sessionCreationPolicy(SessionCreationPolicy.STATELESS)) ensures that Spring-Security (and only Spring-Security)

  • won't create the session
  • won't rely on the session for providing authentication details (for example, providing the Principal).

Any other component of your application (for example, if you would use Spring-Session) is still free to create the session.

  • Is it true that any request to other resources than `/login` will authenticate the user with that token and then provide the authenticated user in a Spring session? – Glains Oct 01 '18 at 20:00
  • Any other request than `/login` should authenticate the user based on JWT. With your current configuration, the `principal` should not be stored in the session (that is ensured by the `stateless` attribute). –  Oct 02 '18 at 03:17
  • 2
    Then i still have no clue where the session is coming from. I have made an edit to confirm that the session is injected. Beside the security config and my JWT authentication, its only a simple request. Any other idea? – Glains Oct 02 '18 at 09:37
  • Does this answer help? https://stackoverflow.com/a/14510798/5022951 – Mat Aug 13 '20 at 14:47
  • @Glains have you fix this issue? please share it. have same issue – NHS Jan 05 '21 at 11:26
3

Try to set the session to none in the application.yml:

spring.session.store-type=none

as mentioned in the docs: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-session.html

nils petersohn
  • 2,317
  • 2
  • 25
  • 27
2

Even with SessionCreationPolicy.STATELESS, a session can still be created outside the scope of spring security. For example, when you call request.getSession() or request.getSession(true), or if you access a session scoped bean (internally spring will call request.getSession(true)).

If you add the following to your application.properties, a stacktrace will be output every time a session is created, which may help you find out what is going on.

logging.level.org.springframework.session.web.http.SessionRepositoryFilter.SESSION_LOGGER=DEBUG
rougou
  • 956
  • 9
  • 14
1

Credit to nils petersohn:

sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)

Solved this for me in Firefox at least. spring.session.store-type=none in the application.properties did not have any effect.

Javanator
  • 871
  • 7
  • 10
0

I had the same problem. I discovered that the HttpSession injection creates a session if there isn't already one. So you'll have to get the session yourself and be sure to use the false parameter in the getSession() method. So try this :

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public void create() {
        ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        HttpSession session = attr.getRequest().getSession(false); // do not create one
        if (session == null) {
            LOGGER.warn("Session is null.");
        } else {
            LOGGER.warn("Session id = {}", session.getId());
        }
}
RonyV
  • 1