Build Email Verification from Scratch With Masonite Framework and JSON Web Tokens
Masonite Framework is a modern and developer centric Python web framework. The architecture of Masonite is much more similar to the Laravel framework.
In this tutorial, I’ll show you how to build email verification from scratch for your Masonite application.
Masonite comes with a CLI tool called Craft. Craft provides an easy way to scaffold what you need for authentication using a simple command:
$ craft auth
The above command generates everything you need for authentication: 4 new controllers, 5 new templates and 6 new routes. So you want to handle a user email verification and validate the email. There we go!
Create new Masonite project and scaffold authentication
$ pipenv install masonite-cli
$ craft new masonite-app-with-user-verification
$ cd masonite-app-with-user-verification
$ craft install
$ craft auth
Setup database
In order to register users, we will need a database. Let’s use a MySQL Database.
$ pipenv install PyMySQL
Create new database and put your database credentials into .env file:
DB_DRIVER=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=masonite
DB_USERNAME=root
DB_PASSWORD=root
Add ‘active’ attribute to User Model
Let’s create a new migration:
$ craft migration add_active_to_users_table --table=users
Then, add new active attribute:
from orator.migrations import Migrationclass AddActiveToUsersTable(Migration):
def up(self):
with self.schema.table('users') as table:
table.boolean('active').default(False)
def down(self):
with self.schema.table('users') as table:
table.drop_column('active')
Apply your migrations 😄
$ craft migrate
Why use JWT for email verification?
JSON Web Tokens are a good way of securely transmitting information between parties.
For email verification, we need to send a random hash to registered user.
Generate new jwt token on registration
We need to use JSON Web Token implementation in Python:
$ pipenv install PyJWT
Then
data = {'email': user.email}
encoded = jwt.encode(data, 'secret', algorithm='HS256')
token = str(encoded, 'utf-8')
Now, we need to send a mail. Masonite provides a package call notification that can help us perform this.
$ pipenv install masonite-notifications
Let’s create a notification for email verification.
$ craft notification EmailVerificationNotification
Our notification should send an e-mail with a link containing the verification token.
from notifications import Notifiable
class EmailVerificationNotification(Notifiable):def mail(self):
return self.subject('New account signup!') \
.driver('smtp') \
.heading('Masonite App With User Verification') \
.line('In order to use your account, you have to validate your email address.') \
.line('Please click on the link below.') \
.action('Validate my account', href=self._link)
Not bad.
Then, let’s send that email to our users
if token: Notify.mail(EmailVerificationNotification, to=user.email, link='http://localhost:8000/activate/{0}'.format(token)) Session.flash(‘success’, ‘Almost done! Please check your email to complete the registration process.’) return Request.redirect(‘/login’)
If your smtp credentials are correct, you’ll have this in your mail:
Create a route for email verification
get('/activate/@token', 'RegisterController@validate')
Define fillable attribute ‘activate’ on User Model
class User(Model):
__fillable__ = ['name', 'email', 'password', 'active']
Validate users
def validate(self, Request): if Request.param('token'):
data = jwt.decode(Request.param('token'), os.environ.get('KEY'), algorithms=[‘HS256’])
user = User.where('email', data['email']).first() if user:
user.active = True
user.save()
Session.flash('success', 'You\'re in! Let\'s login!') return Request.redirect('/login')
Last thing! Login users:
def store(self, Request, Session):
user = User.where('email', Request.input('email')).first() if user.active:
if Auth(Request).login(Request.input('email'), Request.input('password')):
return Request.redirect('/home')
return Request.redirect('/login')
else:
Session.flash('warning', 'Please check your email to complete the registration process.')
return Request.back()
Your user is now verified 🔥
I’ll release this stuff inside a Masonite package. If you want to contribute to the development of the package or interested in the development of Masonite then be sure to join the Slack channel or star the repo on GitHub.
Feel free to add you comments for further discussion. The entire code for this tutorial is available on Github. Thanks!