11

I'd like some feedback on the following authentication idea, does it makes sense, and is there a standard way of doing this (or similar) so I can rely on a well tested implementation.

I've seen many answers here on how to secure the communication to the server, and most answers are to simply use TLS properly. I'm looking for a solution that allows for encrypting and signing the messages themselves, so the message stay safe as they go through the backend, until they reach the destination service.

Context

  • Mobile app for android 2.3+ and iOS 6+ built with phonegap (so libs used should be usable from Java/obj-c or js)
  • The app communicates with the server using a REST json api
  • Message content should stay confidential as it goes through the backend (no termination at proxy/load balancer)
  • Should support "remember me", so the user doesn't have to re-enter their passphrase all the time
  • All communication are done over ssl/tls

Authentication

  • the client collects the user credentials (username, passphrase and some extra security info)
  • the client generates a symmetric key
  • the client encrypts the credentials with the symmetric key
  • the client encrypts the symmetric key with the server public key (shipped with the client)
  • the client sends the encrypted message, key and nonce via https (validating the server cert)
  • the server proxy forwards the authentication request to the authentication service
  • the authentication service decrypts the symmetric key and message
  • if the credentials are valid, the service generates an authentication token
  • the token is associated to the symmetric key on the server, if credentials are invalid, the key is discarded after replying to the request
  • the token is returned to the user, encrypted with the symmetric key
  • the token and key are stored locally on the client, encrypted by a short password

I assume that these requests are safe from replay attacks if tls is used, so there is no risk of an attacker replaying the message to get a new token.

Other API calls

  • the client generates the request messages, encrypts it and sign the encrypted message
  • the client sends the encrypted message, nonce and signature with its auth token to the server
  • on reception the server looks up key associated with the received token, verifies the signature and decrypts the message before processing

Questions

  • is there any issue with reusing the same symmetric key?
  • what is a good choice of symmetric key?
    • What about AES-OCB or AES-CBC + HMAC signing?
  • how often should the symmetric key be changed?
  • What is the best way of updating the key/refreshing tokens? I was thinking of issuing a refresh token during the authentication response and have the keys expire after a specific period, so if the user does't refresh their key they have to login again.

Thanks

6
  • I didn't look into the details of your scheme yet, but one point where most non TLS schemes fall down are replay attacks. Commented Jun 16, 2013 at 21:12
  • This is exactly the sort of scenario where SOAP might be a better option than REST.
    – Xander
    Commented Jun 17, 2013 at 1:27
  • @CodesInChaos The communication would still happen with TLS, but yes replay after the tls termination on the server side is a possibility without nonce, which I forgot to mention. Commented Jun 17, 2013 at 6:18
  • @Xander I'm not as familiar with SOAP, but it seemed that ws-security for example was addressing some of those issues, right? Commented Jun 17, 2013 at 6:26
  • @NicolasEsteves Yes, exactly. SOAP is panned for it's complexity, but the reason it's complex is because it has incorporated solutions to problems like this through XML encryption and WS-Security, so in these cases, it can be be the best option.
    – Xander
    Commented Jun 17, 2013 at 6:34

2 Answers 2

5

Unless I have missed something your solution looks awfully like a Security Token Service. For an STS the key is to have a party that is trusted to identify the initiating party to the relying party. In your case the trust broker and relying party appears to be the same entity.

If your goal is to have trust propagate to the final destination, just use SSL through the proxy, and use a client certificate to identify the end point. Assuming you want HTTP going through your proxy so that you inspect traffic, implement a standard STS.

As Xander has said, REST is great for lightweight service calls, but the moment you want to do security you should use SOAP, specifically the WS-Security extension. It really isn't that hard, especially if you control both ends as you do. See this stack overflow question for how to do this in Java on Android.

If you do go ahead with your home baked solution it is worth noting that the last three bullets in your Authentication look to be your weak point.

3

I can't say I've reviewed them in details, but you may be interested in existing attempts at implementing Message-Level Security at the HTTP level. For example:

Both projects seem inactive. They may also lack the expert scrutiny that other security protocols usually have, or should have. That is not to say there is anything wrong with them. I would suspect the lack of success of HTTPsec is rather due to its arrival during the "SOAP v.s. REST wars" (adding a bit of complexity on the REST side) and the fact it only had one implementation (in Java) with a non-free licence.

Investigating whether encrypting and signing your message entities with existing tools like OpenPGP might be of interest.

REST is a word that has different meaning for various people. Sometimes, it just means payload over HTTP, without the multiple layers of SOAP. Whether such services actually follow the HATEOS principles is another matter.

My personal opinion on this is that the statelessness of REST should be applied to the core features of the application, not necessarily to its security aspects. It's of course very difficult (if not impossible) to prevent replay attacks without keeping some sort of state on the recipient's side.

This being said, I'm not sure from your questions that you're interested in pure message-level security. Rather, it seems that you're mainly interested in tunnelling an equivalent of SSL/TLS through HTTP, because you're unable to run a direct TCP connection from the client to the backend. Since you're also using SSL/TLS, this suggests the main reason for all this is that you don't trust the load balancer. Trying to write your own protocol is generally difficult, and often a bad idea. Recommendations regarding encryption and MAC algorithms depend on the details. (In comparison, it took a while for some issues with TLS to be identified and addressed, even though it's an open protocol with a detailed specification, studied by a number of experts.)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .