3

I'm working on a site that implements user authentication (using Comeonin and Guardian).

I'm in the process of implementing email verification. I thought that I might take advantage of the functions in Guardian to generate the url using a JWT token. As per this post, this seems like a plausible solution (as long as the url uses https and the token expires in a relatively short period of time).

Here's the code I've written so far:

def email_verification( user = %User{} ) do
  if ( user.email != nil ) do
    claims = Guardian.Claims.app_claims
       |> Map.put("email", user.email)
       |> Guardian.Claims.ttl({1, :hours})

    { :ok, jwt, full_claims } = Guardian.encode_and_sign(user, :email_verification, claims)

    Zoinks.Mailer.send_verification_email( user.email, jwt )
  end
end

I have put the email address in as a claim. The idea being that I could match the "email" claim with the email address in the database, once the user clicks the link.

However, I'm assuming that this is a bad idea - especially since the link will be exposed as clear text via email.

Following the pattern outlined in this SO post, maybe I could generate a random number, hash it (using Comeonin), store it against the user and put that in as my claim instead? Is this a good idea, or am I completely off-track?

Assuming that I get this part of the solution working, is it okay to set the payload type to :email_verification?

Community
  • 1
  • 1
Mitkins
  • 4,031
  • 3
  • 40
  • 77
  • What do you exactly mean with ```However, I'm assuming that this is a bad idea - especially since the link will be exposed as clear text via email.```? If you use a strong secret, there should be no issue using your approach AFAIK – Jonas Dellinger Sep 13 '16 at 19:27
  • To be honest, I'm not sure - I'm inexperienced when it comes to security – Mitkins Sep 13 '16 at 23:17
  • I'm assuming that if you collect enough tokens (clear text via email), then it might be possible to apply a technique such as a Rainbow Table attack? If the security for the token in the email is compromised, then the website is as well - since it's using the same configuration – Mitkins Sep 13 '16 at 23:17

1 Answers1

1

Sending a JWT via e-mail is completely fine, as long a strong secret is used (but that's always important, despite the transport method)

Quote from the comments:

I'm assuming that if you collect enough tokens (clear text via email), then it might be possible to apply a technique such as a Rainbow Table attack?

That's why you should pick a strong secret. The last part of the JWT, the signature, is a combination of base64UrlEncode(header), base64UrlEncode(payload) and secret put into a strong hashing function like HMAC SHA256. For more security infos, there is a good description on jwt.io

Implementation

You don't need to put the actual email inside the claims at all. A simple field like email=true should be enough, since your Serializer already puts the user id into the token. Just make sure a user can only be verified once and pick a strong secret!

Jonas Dellinger
  • 1,294
  • 9
  • 19
  • 1
    If I allow the user to change their email address at any time (i.e. even before the user clicked the activation link) - wouldn't I need to confirm that the web token was for the email address in the database? – Mitkins Sep 16 '16 at 11:50
  • Yes, if you want to support validating different E-Mails for a single user, then storing the E-Mail inside the token is a correct approach! My thought was just about initial, single e-mail validation. – Jonas Dellinger Sep 16 '16 at 11:53