JSF stateless views and CSRF protection

JavaServer Faces (JSF) – especially since version 2.2 – provides a good Cross-Site Request Forgery (CSRF) protection. To achieve this, every form automatically receives a random hidden token:

JSF non-transient view

Nothing more to do for the developer, JSF takes care of comparing the token’s value against the one stored in the server side session. Without the correct token, the request won’t be processed.

JSF 2.2 also introduced stateless views, simply by marking one as transient:

<f:view transient="true">...</f:view>

Using a transient view may make sense e.g. before a user has logged in and no session needs to be stored on the server. Or you want to avoid that nasty ViewExpiredException. But keep in mind that this influences the out of the box CSRF protection as well. Looking at the same form from before but with transient on true, the anti CSRF token changes:

JSF transient view

An anti CSRF token needs to be unpredictable and absolutely random to be of any use for CSRF protection. The static value stateless of course is not.

Is this a bug? No! The most common implementation for CSRF protection is called Synchronizer Token Pattern. This pattern stores a hidden value in forms (like javax.faces.ViewState) and the corresponding value in the server side session. Using transient=”true” avoids creating a server side session. No session, no Synchronizer Token Pattern, no CSRF protection. So when using stateless views you’ll have to implement CSRF protection yourself. The requirement is the same: a random token calculated per user and per session (or per request depending on your security needs). But without the server side session the implementation needs to change. Luckily, there is another option called Double Submit Pattern (see here for a description of both patterns). Double submit, as the name implies, submits the same token from two different places: one in a cookie and the other one, as before, in each form you want to protect. Whereas the cookie is always submitted – including faked requests – the form token is missing and your backend – which has to compare the two submitted tokes – can recognize an invalid request. So by avoiding session creation for every visitor (user), you’ll be giving away the out of the box JSF CSRF protection.

One usage scenario for stateless views might be a login form. After logging in, you want a session for the user, but not for any anonymous visitor. You might ask yourself, what harm a login form that is prone to CSRF could do? Well, it may enable an attacker to automatically log in a user with prepared credentials. This way, the attacker may record and retrace the users’ actions. Therefore you should protect the login form against CSRF as well.

That’s the tradeoff you have the be aware of: JSF provides out of the box CSRF protection, as long as your view isn’t transient. If that this the case you’ll have to take care of the CSRF protection yourself.