ellou'
I have common Play WebSocket method which is working as expected, but I need to authenticate user. Unfortunately when trying even simplest way to identify user in the method:
public class Application extends Controller {
public static WebSocket<JsonNode> connect() {
return new WebSocket<JsonNode>() {
@Override
public void onReady(final WebSocket.In<JsonNode> in, final WebSocket.Out<JsonNode> out) {
User logged = User.findByUsername(Http.Context.current().request().username());
// ...
}
};
}
}
I get an error:
java.lang.RuntimeException: There is no HTTP Context available from here.
My current workaround is to pass random, unique identifier to view and saving it in User model, than I can connect to the socket from the view and find user with the given identifier, but this is no perfect as there can be only one WebSocket connection per user and also doesn't prevent the spoof.
How should I authenticate the user and prevent spoof attack?
Authentication FlowThe client makes a WebSocket handshake request with the external authentication token passed as a query-string parameter in the handshake endpoint URL. The server checks the cache to see if the external authentication token is valid.
Authentication/authorizationThe WebSocket protocol doesn't handle authorization or authentication. Practically, this means that a WebSocket opened from a page behind auth doesn't “automatically” receive any sort of auth; you need to take steps to also secure the WebSocket connection.
I don't know where comes your piece of code, but you should be able to access the HTTP request on the initialization of the Websocket (first connection), ie you should be able to check for authentication only when you initiate the websocket socket connection (subsequent call will not be using HTTP, it is how Webscokets works).
So for instance, in your controller, you could have something like this:
public class Application extends Controller {
public static WebSocket<JsonNode> connect() {
Logger.info("Username from request = " + request().username());
return new WebSocket<JsonNode>() {
@Override
public void onReady(final WebSocket.In<JsonNode> in, final WebSocket.Out<JsonNode> out) {
// ....
}
};
}
}
Have you tried retrieving the authenticated user ID from the HTTP Session instead? The context seems to be available at that point.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With