Javalin websockets headers

92 views Asked by At

I am trying to connect to my Javalin-Backend with a websocket in js. This is my Access-Manager in Javalin:

@Override
  public void manage(@NotNull Handler handler, @NotNull Context context, @NotNull Set<? extends RouteRole> set) throws Exception {
    if (set.isEmpty()) {
      handler.handle(context);
      return;
    }

    String token = context.header("token");
    if (token == null) {
      context.status(HttpStatus.UNAUTHORIZED);
      return;
    }

    Integer userId = this.tokenService.getUserIdByToken(token).orElse(null);
    if (userId == null) {
      context.status(HttpStatus.UNAUTHORIZED);
      return;
    }

    Account account = this.accountService.getAccount(userId).orElse(null);
    if (account == null || account.isDisabled()) {
      context.status(HttpStatus.FORBIDDEN);
      return;
    }

    if (set.contains(AuthenticationLevel.ADMIN) && !account.isAdministrator()) {
      context.status(HttpStatus.FORBIDDEN);
      return;
    }

    context.attribute(Constants.ACCOUNT_ATTRIBUTE_KEY, account);
    handler.handle(context);
  }

Now every websocket-connection also passes the acces manager from javalin by default. But my websocket connection failes due to missing header ("token").

Here is my code of the websocket-connection:

    const socket = new WebSocket("wss://luxcars-api.lukas.bayern/chat", "your-subprotocol", {
        headers: {
            'token': getCookie('token')
        }
    });

Does anyone know, how to set the header direct at connection? In the Javalin documentation (https://javalin.io/documentation#wscontext) there is also the header method for WebSocketContext. But how to set the header?

I can't wait for the first message because my access manager prevents the connection.

Thanks a lot.

1

There are 1 answers

0
kaqqao On

This will come as a cold shower, but browsers cannot send HTTP headers during a WebSocket handshake, despite it being a regular HTTP request, except for a few special headers outside of your control, and the WebSocket sub-protocol header Sec-WebSocket-Protocol, which is the only one you have control over. So it's not your Java code that's the issue.

There are various workarounds you can try, including smuggling your token as a sub-protocol, since Sec-WebSocket-Protocol can have multiple values. See my (insanely comprehensive) answer here: https://stackoverflow.com/a/77060459/294657