Implement email verification using JWT

Furqan Aziz
4 min readMay 19, 2018
Photo by Volkan Olmez on Unsplash

Almost every application today do have signup/signin functionality which leads to authentication and authorization of pages or resources later. While signing up it is very much important for a good application to ensure the correctness and ownership of the email address used for. The wrong email can restrict actual email owner to signup if he is interested too, although he can use forgot password feature to get access to the account that will sound frustrating to him. In case we are using that email address to send several account notifications or marketing emails, these will be going straight to a wrong person.

To ensure the correctness and ownership of the sign up email address most of the applications do have an email verification feature. Whenever somebody signs up, an email with verification link is sent to his inbox, by clicking the link user is brought to the browser and is marked as verified. A user is mostly unable to login or uses certain features of the application till email is not verified. Same email verification is again used if an existing user wants to change his email address. In the latter situation, the old email will not be replaced with new one till the new one is not verified.

Most of the applications implement the basic email verification feature with having two fields emailVerified: boolean and emailVerificationToken: string on users table. The first field is being used to set if the email is verified or not and the second one is being used to store email verification token which is sent to user along-with email verification link to his inbox. This token is randomly generated (avoiding duplicate token) and is being used to reference the user from the database to mark emailVerified: true when he clicks the link. Some application also stores emailVerificationTokenExpiry: Date too to add more security.

This flow is totally alright and works perfectly fine if it is implemented correctly, but this looks like a legacy approach to me and you will be following me very soon if you understand the power of JSON-Web-Tokens (JWT). JWT is a hash like (encrypted) string, can carry any amount of data, no need to store this token at all in the database, and will make a developer’s life much easier for almost all the features needed token storage, token expiry, reference to user object and security as well. The same applies to forgot/reset password feature, multi-step signup wizard and partner/referral URLs etc.

Here is how it should work, You do not need to have emailVerificationToken or emailVerificationTokenExpiry at all in your users’ table. Try to find a jsonwebtoken package in your language and bring that in. If you are coding a REST API then most probably jsonwebtoken package is already a part of your project. If not, feel free to bring it in as it is very light weighted, well-defined, easy to use, have stable API and small package. On signup, pick user’s id (compulsory), email(optional), name(optional) and combine these in a map/hash/array format whichever is easy for you to retrieve it back. Your jsonwebtoken package must have a sign function, use that function to sign this information. You have to pass an expiry date, and a secret while signing the JWT token and will get back an encrypted token. Again, no need to store this token and pass directly to email verification link.

When user will click the link to verify his email, you can decode this token on frontend to validate if token is valid and not expired along-with picking user’s email and name to show him a pretty greetings on page while a request on the backend is sent to the server to mark user validated (in case of single page application). decode will not need secret and will just return exact data you passed to it while signing along-with expiry date. On the server, we will use the same secret to verify the token again, if the token is valid and is not expired we will get back the data we passed to it while signing else an error or false. Just to avoid the use of the same token multiple time we can pick the user from the database based on the ID returned from JWT and look if the user is already verified to throw back an error else mark him verified.

In case you are using the JWT token for multiple purposes in one application, don’t forget to pass a token type while signing the token and verify it back on the server after decoding to avoid a security vulnerability.

P.S. Pardon me in case you find any English problems as this is my very first writing. Thanks

--

--