2

TL;DR Given that all of the state information for a web browser is accessible to a (potentially hostile) user, how can challenge-response authentication between the browser and the server be considered secure?

The Longer Version

I'm developing a web application and I want to implement web sockets for communication between the client and the server. I'm looking at implementing a WAMP router and I'm trying to understand modes of authentication with a system like this.

The WAMP protocol allows for challenge-response authentication (CRA). The way I understand it (and please correct me if I have this wrong), when a client makes a request to connect, the server sends a challenge. The client then encrypts the challenge using a secret key which is shared between the client and the server and returns it. The server checks the encrypted version from the client and, if it was correctly encrypted, allows access. The use of a shared secret allows the server to know that the request came from an authorized client.

This leads to question #1: the Javascript code sent to the browser must contain the shared secret. So the shared secret is not very secret, is it? So how can we consider this a secure method of authentication?

In thinking about this question, I've come up with a solution that I think might solve the problem.

Important note: all connections will be secured via TLS.

Here's how my authentication system might work:

  1. user logs in through the normal, form-based authentication method

  2. server generates an authentication key and a secret, and passes those values to the client as part of the page HTML. The key and secret are both generated via a cryptographically secure method.

  3. client then initiates websocket connection. This begins the challenge-response authentication sequence, using the key and secret generated by the server

  4. server authenticates, using key & secret, and everything is cool.

The key here is the one-time use of the key and secret values. If they change periodically, then there is no way an attacker could generate a key/secret pair or use one that they had saved from a previous visit.

Which brings me to question #2: is this an adequate authentication scheme?

And finally, question #3: assuming the authentication scheme described above is adequate, how often should the key/secret values change? I'm thinking it should definitely change every time the user logs in, and should also expire after 6-8 hours have elapsed. Thoughts?

Kryten
  • 349
  • 2
  • 7

1 Answers1

2

This leads to question #1: the Javascript code sent to the browser must contain the shared secret. So the shared secret is not very secret, is it? So how can we consider this a secure method of authentication?

If you study the documentation of the Challenge Response Authentication with WAMP you should notice the following information:

The client and the server share a secret. The secret never travels the wire,

Instead it is considered that the secret was shared before doing the authentication:

The actual pre-sharing of the secret is outside the scope of the authentication mechanism.

In case of using Websockets from the browser that probably means that the code which contains the secret should be transferred with TLS. When using Websockets inside a standalone application shipped to the user the secret can be pre-shipped inside the application. Since the secret itself is not specific to the user but only used to secure the communication it can be exchanged before any kind of authentication.

Important note: all connections will be secured via TLS.

WAMP-CRA is explicitly designed to be usable with non-TLS. From the documentation:

... hence WAMP-CRA can be used via non-TLS connections

Of course WAMP-CRA can be used with TLS, but if you have a secure connection already you don't need to use a protocol designed to work within the limitations of non-TLS, but you could use a much simpler authentication like cookie-based or make use of mutual authentication provided by TLS.

... Which brings me to question #2 ... And finally, question #3:

Since your original assumption was wrong there is no need to add security on top of the existing protocol. Thus I don't cover these parts of the question which deal with the security of your added authentication layer.

But a more general answer, independent from the framework you use: Websockets are a communication channel created by upgrading an existing HTTP(s) connection. This means any kind of authentication done for the HTTP(s) connection can be applied to the Websocket connection, i.e. mutual TLS authentication, Basic Authentication, session cookies etc. Thus if the HTTP(s) connection is already authenticated their is no need to do an additional authentication inside the Websockets channel because this is the same TCP/TLS connection which was already authorized.

Steffen Ullrich
  • 184,332
  • 29
  • 363
  • 424
  • Thanks for your response. I did read the documentation, but I guess there's one thing I'm not understanding then: the secret has to travel from the server to the client (as part of the Javascript sent to the client) - how can one then say that "the secret never travels the wire"? Is it because the secret travels via HTTP, while the challenge/response messages travel via the WebSocket connection? That doesn't seem all that secure to me. – Kryten Sep 01 '15 at 14:27
  • @Kryten: I've updated the answer. The sharing of the secret is actually out of the scope of the authentication but within a web application you could simply use TLS to transfer the relevant files. – Steffen Ullrich Sep 01 '15 at 14:44
  • Thanks Steffen, your answer has helped clarify this for me. I think my real question is "how do you share a secret with a web browser"? But that's a different question, so I'll ask it separately... – Kryten Sep 01 '15 at 15:12