User registration and session management is a very common feature of any non-trivial web application. A custom solution is always an option and is usually pretty easy to implement. This is certainly the case when working with Phoenix, and there are many books and online tutorials that step thru the process of building out a custom authentication solution.
Although not difficult, this can get pretty involved, especially when adding typical features such as registration confirmation, password reset, and session persistence.
README section is pretty comprehensive, providing a good description of how to get things up and running. However, I figured a step-by-step tutorial might still be useful, so let’s
Power up (ha, ha) and see how it works!
What we’ll build
For the purposes of demonstrating how to use
Pow we will be building a very bare bones Phoenix application. We won’t worry about making it look pretty or customizing it in any way, but we will use a generator to create some pages we want to secure with
Pow, just to demonstrate how that functionality works.
I’d encourage you to follow along, but if you want to skip directly to the code, it’s available on GitHub at: https://github.com/riebeekn/phx-auth-with-pow.
So let’s get at it!
Creating our app
Our first step is to create our application, we’ll pretend we are building out a basic (super, super, basic) warehouse inventory system, so we’ll call our application
Y when asked to fetch and install dependencies. Now we’ll change into the application directory and create the database.
We’ll want to demonstrate how to secure pages when using
Pow, so let’s use a generator to create our “inventory” context and our “product” pages. We’ll look to restrict access to these pages, only allowing logged in users to view them.
As per the
mix output, let’s run the migrations…
… and update the routes.
/lib/warehouse_web/router.ex …line 16
Let’s also add a link in the header for navigating to the main products page where we list our products.
/lib/warehouse_web/templates/layout/app.html.eex …line 11
That is pretty much it as far as our application functionality goes so let’s fire up the application and see what we got.
If we navigate to http://localhost:4000/ we’ll see the standard Phoenix landing page, and the Products link will take us to the main Products page.
So with a very basic application in place, let’s see how we can add user authentication and management to our application via
Using Pow within our application
There are a number of options and extensions available to us when using
Pow but we’ll start with a basic installation, and go from there.
The first step is to add
pow to our list of dependencies.
/mix.exs …line 34
Now we need to grab our dependencies via
mix output will indicate that
pow has been added to our application.
Next we need to install
Now we need to deal with a bit of configuration.
config.ex, adding a new configuration section for
Pow. I’ve placed this above the logger configuration.
Next we need to update
/lib/warehouse_web/endpoint.ex …line 40
We’ve added a
pow specific plug directly after the session plug.
That’s it for configuration, we now need to add some routes.
There are some
Pow specific routes we need to add, and we also need a specific pipeline for protected resources.
So we’ve added a new
use statement for the
Pow routes (
use Pow.Phoenix.Router); a new pipeline; and two new scopes. We can see that the second scope is where our protected routes should be going.
Finally, when we installed
Pow, a new migration file was created, so we also need to run migrations.
Using TablePlus we can view the structure of the
users table created for us by
Updating the navigation links
Before we run our application let’s have a look at our routes.
Pow has made available a number of new routes for us.
Let’s update our navigation to include links to relevent routes. We also now have access to a
current_user variable, so can display appropriate links based on whether a user is currently logged in or not.
We’ll always display the
Products link… just to make it easy to test whether it has been properly protected.
/lib/warehouse_web/templates/layout/app.html.eex …line 13
Ok, with all these changes in place let’s start our server back up and see how things are looking.
Checking out the Pow functionality
Our new links are appearing in the header.
sign up link we see the registration page
Pow creates for us:
After signing up, we are automatically signed in.
We now have access to pages that are specific to signed in users, such as the “Edit profile / account” page.
If we sign-out we’ll see that despite being signed out we can still access the
Let’s secure the page by updating our routes.
/lib/warehouse_web/router.ex …line 29
We’ve removed the ‘products’ resources from the lower scope and placed them in the protected scope. Clicking the
Products link now re-directs to the sign in page.
Customizing the Pow templates
So this is pretty sweet! We have a good amount of functionality and it’s required very little effort or set-up.
What if we’re not happy with the templates
Pow creates however? Before stopping for the day, let’s see how easy it is to customize the
The first step is to generate the templates.
We then need to update
config.exs to indicate we want to use the generated templates.
/config/config.exs …line 20
We’ve added the
web_module value, and we can now update the templates in
lib/warehouse_web/templates/pow and we’ll see our changes reflected in our application. Changing the configuration requires a server restart, so let’s restart our server.
And then make a few small changes to the
/lib/warehouse_web/templates/pow/session/new.html.eex …line 18
We’ve updated the text to read
Sign in now!, and this get’s reflected in our application.
A pretty trivial change, something that might make a bit more sense is adding a “Close account” link to the edit profile page.
/lib/warehouse_web/templates/pow/registration/edit.html.eex …line 26
And voila, user’s now have a way to close out their account.
If we ever want to revert to the default templates, we can just remove the
/config/config.exs …line 20
After a server restart, we’re back to our original templates.
I like having that “Close account” available on the Edit page however, so let’s switch the configuration back to include
/config/config.exs …line 20
A quick word about tests
I haven’t been sure how to handle testing for the purposes of this post. Testing is obviously very important but at the same time can require a fair bit of explanation which can add significantly to the length of a post and distract from the core subject.
Initially I was going to completely ignore testing, and indeed if you run
mix test you’ll see a number of tests will fail with the updates we’ve made to the code base.
This felt a little janky… so as a compromise I’ve updated the existing tests in the master branch of the GitHub repo so they pass; but there is no discussion of the tests (as you’ve no doubt noticed) and I haven’t added any new tests. Needless to say, with a real application this is not the strategy you would want to follow!
That’s all for today, the bare bones behaviour provided by
Pow is pretty impressive, especially considering how easy it is to get set up. There is more goodness on the horizon however, next time we’ll look at how easy it is to add session persistence, registration confirmations and forgot password functionality.
Thanks for reading and I hope you enjoyed the post!