Mitkins
Mitkins

Reputation: 4341

Create email verification url using Guardian

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?

Upvotes: 3

Views: 738

Answers (1)

Jonas Dellinger
Jonas Dellinger

Reputation: 1364

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!

Upvotes: 1

Related Questions