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