papercups-io / papercups

Open-source live customer chat
https://app.papercups.io/demo
MIT License
5.77k stars 525 forks source link

Provide secure way of identifying customer #803

Open robserva opened 3 years ago

robserva commented 3 years ago

Problem As a user, I can change the email address associated with my Papercups chat client-side. This would lead whoever is chatting with me to believe I'm someone else and if they aren't doing other forms of verification they might reveal some information about me.

Solution I'd like to be able to do one of the following:

cheeseblubber commented 3 years ago

For reference https://developers.intercom.com/installing-intercom/docs/enable-identity-verification-on-your-web-product

reichert621 commented 3 years ago

thanks for the write-up @robserva! been meaning to do something like this :+1:

lucasavila00 commented 3 years ago

That is a feature that would be really useful.

On top of that, it would be really interesting if an identified user could be reliably reached.

So if the user has sent a message or not I can send him one and it will send the message to their browsers.

lucasavila00 commented 3 years ago

A proposal for an implementation would be:

  1. Adding a new field, a sibling to the customer object here, called customerSigned
  2. Using a private key provided by Papercups, servers will sign the customer object. Notice that it will sign and not encrypt the customer object. The signature would contain an expiration date, too.
  3. When displaying user information (name, email, external_id) these would be shown as "signed/safe".
  4. There should be a configuration option so that no conversation is started if no valid signed customer object is found. It would be the responsibility of the caller to provide anonymous users with their "anonymous" name/signed customer object, thus making using Papercups harder, so this should be opt-in.

This approach would be basically what Imagekit does with signed urls. Setting it up like this means that no server communication is needed to verify the authenticity of the parameters, at the expense of not being able to revoke a signature.

Questions:

  1. What signing algorithm to use? I was considering JWT but it seems overkill, as we don't need to use any public key features. An HMAC signature of the parameters encoded as query strings should be enough. Which algorithm to use, then: SHA1 or SHA256?
robserva commented 3 years ago

What signing algorithm to use? I was considering JWT but it seems overkill, as we don't need to use any public key features. An HMAC signature of the parameters encoded as query strings should be enough. Which algorithm to use, then: SHA1 or SHA256?

I agree that JWT isn't needed. HMAC SHA256 should do the trick, and I think that's the general best practice.

In theory HMAC SHA1 should still be secure (https://crypto.stackexchange.com/questions/26510/why-is-hmac-sha1-still-considered-secure) but I think SHA256 is still standard.

lucasavila00 commented 3 years ago

I imagine a possible implementation would be to validate the metadata/customer params with the signature after calling Customers.sanitize_metadata() here and here

I haven't figured out how to access information specific to the account_id, though. I would need to know a boolean which defines the need to check for signatures and the private key needed to check the HMAC.

On the client side it should just pass the string around until it reaches these 2 endpoints.

reichert621 commented 3 years ago

(bumping this up, see https://app.intercom.com/a/apps/x4uvwkvj/settings/identity-verification/web)