1

I'm currently using a object @SessionScoped "SessionBean" to store information of the logged user and to return him a custom ID, for instance.

@Path("/auth")
public class AuthenticationResource {

    @SessionScoped
    @Inject
    SessionBean sessionBean;

    @Inject
    HttpSession httpSession;

    @PermitAll
    @POST
    @Path("/login")
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    @Produces(MediaType.TEXT_PLAIN)
    public String login(@FormParam("username") String username, @FormParam("password") String password) {

        // if OK, validate the session and store info in the 'sessionBean'
        if ( customService.isValidUser(username, password) ) {
            sessionBean.setJessionId(httpSession.getId());
            return sessionBean.getId();
        } else {
            httpSession.invalidate();
        }
        return null;
    }

    @POST
    @Path("/logout")
    public void logout() {
        sessionBean.setJessionId(null);
        httpSession.invalidate();
    }
}

@SessionScoped
public class SessionBean {
...
}

And to make sure other REST API are protected, I use this sessionScoped in a ContainerRequestFilter to make sure the user is logged in:

@Provider
@Priority(Priorities.AUTHORIZATION)
public class AuthenticationRequestFilter implements ContainerRequestFilter {

    @SessionScoped
    @Inject
    SessionBean sessionBean;

    @Inject
    HttpSession httpSession;

    @Context
    ResourceInfo resourceInfo;

    @Override
    public void filter(ContainerRequestContext crc) throws IOException {

        // method annotated @PermitAll is for login
        if (resourceInfo.getResourceMethod().isAnnotationPresent(PermitAll.class)) {
            return;
        }
        if (httpSession.isNew() || sessionBean.getJessionId() == null) {
            crc.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
        }
    }

}

My question: is it safe and is the @SessionScoped + JESSIONID is enough to protect the server?

Note: I use Quarkus 2.6.2 + Undertow.

iriiko
  • 43
  • 4

1 Answers1

1

@SessionScoped beans, as stated in the documentation:

The session context is shared between all servlet requests that occur in the same HTTP session. The session context is destroyed when the HTTPSession times out, after all HttpSessionListeners have been called, and at the very end of any request in which invalidate() was called, after all filters and ServletRequestListeners have been called.

So yes. They are meeant for exactly that purpose (among others).

Another matter is using the name "jsessionid" for a self generated value. That is the standard name in Java EE containers for the cookie that stores the session id. So if you use a self generated value I would change the name.

And beware that many REST request from clients are stateless, meaning that they no maintain the session. The session isnactually attaches to the JSESSIONID cookie, so if they don't keep the cookies between requests your server will consider those request as different sessions.

Willy
  • 21
  • 2
  • Thanks. I know it's a statefull, but the amount of client will be low, so it's OK. Is it a security issue if the same SessionID is stolen and used on an other machine? Does the server (undertow for instance) double-check the origin (IP) of the request? – iriiko Feb 04 '22 at 10:18
  • stolen the session ID is a security issue always. The same way is a security issue if your cookies for a domain are read by another domain (cookies for google.com cannot be read by a page in otherdomain.com). The browser ensures the privacy of the cookies, and the Java EE Server ensures the privacy of the session (which is bound to the session cookie value). All the session security is based on that, from a backend and frontend point of view. – Willy Feb 04 '22 at 11:27
  • I don't know about undertow, but I guess it doesn't. Browsers keep the session (because they keep the cookies, and if the server doesn't set the cookie with a low expiration value) even when you connect from different ip adressess. – Willy Feb 04 '22 at 11:27