I am a bit new to Play, so forgive me if I’m missing something obvious here.
Basically, it looks like filters don’t work with WebSockets, which seems to block me in what I want to do. Is there some kind of workaround, or am I just out of luck?
I am actually trying to use PAC4J to secure my Play app. PAC4J provides a nice ability to secure routes using a security filter. Basically you add the SecurityFilter to your filters, add the route to the PAC4J config, and that’s it. This works fine with normal Actions. When I added the route of my WebSocket, I was hoping it would just work, but obviously it did not. The underlying issue seems to be that Play’s filters don’t work with WebSockets. (As opposed to some deficiency in PAC4J.)
But it seems like filtering WebSockets should be possible? Is it just not implemented?
Any help would be appreciated. Especially if I have made some kind of conceptual error, or if there is a workaround I could use. Thanks!
The short answer is that this is expected behavior. Filters work with actions, i.e. EssentialAction instances, which model normal HTTP calls that accept a request and produce a response. A WebSocket is a totally different type of handler, and it behaves differently from a normal action because it’s typically upgraded to the websocket protocol afterward, so the filter action can’t return an arbitrary response.
I haven’t used pac4j, but the typical approach is to check the cookie during the initial handshake request and use that to authenticate the WebSocket, using WebSocket.acceptOrResult. Some auth frameworks like Silhouette provide examples of how to do this: https://www.silhouette.rocks/v5.0/docs/endpoints#section-websockets. The approach would probably be similar for pac4j using whatever constructs they provide to identify the user from the authentication cookie.
I haven’t heard of Silhouette, but it looks interesting. I’ll look into it. PAC4J doesn’t seem to have any options to secure a WebSocket, which is unfortunate.