Pow is an excellent authentication solution for Phoenix HTML applications and APIs. It provides a solid, comprehensive bundle of features out of the box; but what if you need customized behaviour? In this post, we’ll look at how easy it is to customize the default functionality of Pow.
A common area where some customization may be desired is during authentication. This is the scenario we’ll look at today. We want Pow
to handle the concept of a disabled
user. When a user is disabled we don’t want them to be able to log in.
A pretty simple requirement, so let’s get at it!
Getting started
To save some time in getting a boiler plate application set up, we’ll use the code from an earlier post, Phoenix authentication with Pow - Part 1, as a starting point. The code contains a basic Pow
configured application, along with some scaffolding, which we can ignore for the purposes of this post.
So let’s grab the code.
Clone the Repo:
Terminal
We’ll create a branch for today’s work.
Terminal
And make sure we have our dependencies and database set-up.
Terminal
Terminal
Note: before running ecto.setup
you may need to update the username / password database settings in dev.config
to match your local postgres settings, i.e.
/config/dev.config …line 69
Terminal
With that out of the way… let’s see where we are starting from.
Terminal
If we navigate to http://localhost:4000/ we’ll see our application.
Nothing fancy, basically just the application you would get by running mix phx.new
and setting up Pow
. All we care about for today is the sign in
process so let’s follow the sign up link and create a user to work with.
After signing up, we’ll see that we’ve been logged into our application.
Time to add the disable user functionality.
Adding the disable user functionality
The way our disable functionality will work, is we will have a column in the users
table indicating whether a user is disabled or not. Once we have the column in the database, we’ll update Pow
to take this column into account when authenticating.
Making the database updates
So the first thing we’ll need to do is add a new column to the users
table; let’s create a new migration.
Terminal
And update the migration as follows.
/priv/repo/migrations/_add_is_disabled_to_users.exs
Pretty simple, we’re adding a new non-null column to users
, and defaulting the value of the column to false
.
Now we’ll run the migration.
Terminal
And we also need to add the new column to our user
schema.
/lib/warehouse/users/user.ex
So that’s it for the database and schema updates, onto Pow
!
Updating Pow
So how can we get Pow
to take into account our new column? Turns out this is pretty easy! Looking at the Pow
source, the context module contains some comments which tell us exactly what we need to do:
Nice! So we’re going to want to use pow_authenticate/1
, let’s have a look at the spec
for authenticate
.
Ok, so it looks like the method returns a user
on valid authentication and nil
otherwise.
We now have enough information to implment our disabled user functionality.
The first step is to create the custom context.
Terminal
/lib/warehouse/users/users.ex
What we’ve done is we now check the is_disabled
flag when a user is returned from pow_authenticate\1
. If the flag is set we return nil
instead of the user
… simple!
Before testing things out, we need to update the Pow
configuration.
/config/config.exs …line 20
Testing things out
Let’s start up our server to see our changes in action.
Terminal
Disable the user
Normally you might create some sort of admin application for managing users, but for the purposes of this post we’ll stick with plain old SQL
. I’m using TablePlus, but you can use any SQL
client you prefer.
SQL
If we now attempt to sign-in again, we’ll see:
Success! Looks like our changes have worked!
If we switch the is_disabled
flag back to false, we’ll once again be able to login.
SQL
Summary
The design of Pow
makes customization of the default behaviour very straight forward and clean. This is fantastic as it means we don’t need to add a bunch of hacks to adapt Pow
to our particular requirements… always a good thing!
Thanks for reading and I hope you enjoyed the post!