Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I authenticate user in Play's 2.0 WebSocket?

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?

like image 917
biesior Avatar asked May 07 '12 15:05

biesior


People also ask

How do I authenticate a WebSocket client?

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.

What is WebSocket authentication?

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.


2 Answers

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) {
                // ....

            }

        };
    }

}
like image 96
ndeverge Avatar answered Sep 22 '22 05:09

ndeverge


Have you tried retrieving the authenticated user ID from the HTTP Session instead? The context seems to be available at that point.

like image 42
Jason C Avatar answered Sep 22 '22 05:09

Jason C