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
git clone -b part-01 https://github.com/riebeekn/phx-auth-with-pow custom-pow
cd custom-powWe’ll create a branch for today’s work.
Terminal
git checkout -b customize-authenticationAnd make sure we have our dependencies and database set-up.
Terminal
mix deps.getTerminal
cd assets && npm installNote: 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
# Configure your database
config :warehouse, Warehouse.Repo,
username: "postgres",
password: "postgres",
database: "warehouse_dev",
hostname: "localhost",
pool_size: 10Terminal
cd ..
mix ecto.setupWith that out of the way… let’s see where we are starting from.
Terminal
mix phx.serverIf 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
mix ecto.gen.migration add_is_disabled_to_usersAnd update the migration as follows.
/priv/repo/migrations/_add_is_disabled_to_users.exs
defmodule Warehouse.Repo.Migrations.AddIsDisabledToUsers do
use Ecto.Migration
def change do
alter table(:users) do
add :is_disabled, :boolean, null: false, default: false
end
end
endPretty 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
mix ecto.migrate
And we also need to add the new column to our user schema.
/lib/warehouse/users/user.ex
defmodule Warehouse.Users.User do
use Ecto.Schema
use Pow.Ecto.Schema
schema "users" do
pow_user_fields()
field :is_disabled, :boolean
timestamps()
end
endSo 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
touch lib/warehouse/users/users.ex/lib/warehouse/users/users.ex
defmodule Warehouse.Users do
use Pow.Ecto.Context,
repo: Warehouse.Repo,
user: Warehouse.Users.User
def authenticate(params) do
user = pow_authenticate(params)
if user != nil && user.is_disabled do
nil
else
user
end
end
endWhat 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
# Pow configuration
config :warehouse, :pow,
user: Warehouse.Users.User,
repo: Warehouse.Repo,
web_module: WarehouseWeb,
users_context: Warehouse.UsersTesting things out
Let’s start up our server to see our changes in action.
Terminal
mix phx.serverDisable 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
update users set is_disabled = true
where email = 'bob@example.com'
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
update users set is_disabled = false
where email = 'bob@example.com'


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!