Simple email password Authentication
• elixir and guardian
Update: 30-08-20 updated for the 0.6.0 API
I’ve been head down with thinking about Guardian and how the far out cases it could be used for will work together. Service2Service, Single sign on, OAuth provider, stuff like that. It occured to me that there is a bunch of really easy to handle things that from the outside might look a little daunting. With that in mind, I wanted to walk through setting up an application for simple, every-day email/password authentication. Almost the simplest auth setup around.
A quick top level overview for the uninitiated. Guardian is an authentication library that uses JSON Web Tokens (JWT) as it’s base unit of authentication. It’s a signed collection of claims that can be used in a session or an Authorization header. They’re great, but this post isn’t about them.
I don’t want to get too bogged down in how to create a User resource. This is going to vary for you, but if you want to see an example of setting up a simple User model with email/username using BCrypt you can checkout the one I use in my example application.
This uses a simple email/encrypted password, where the password is hashed with BCrypt (using Comeonin).
So lets assume that you have created a user and you’re ready to get going. Lets get setup.
Installing Guardian
config.exs
web/routes.ex
We’ve setup a pipeline for authenticating browser requests (i.e. requests from the session). Note that this will not actually kick anyone from the app, that will come later.
You’ll need a serializer. I put mine in lib/phoenix_guardian/guardian_serializer.ex
The serializer just fetches your resource, or given a resource, it serializes it into the token.
Logging in
We added the SessionController into the routes. This just provides the login form, and handles the result. It is also where the magic happens. Inside this controller, you’re issued a JWT into your session.
There’s a couple of methods, but most of what’s happening is straight forward.
A user lands on the “new” action and we generate a form. We use the
User.login_changeset
with the form. It’s a simple changeset from the user.ex model:
This will just give us a nice error message and interface for checking the password.
Once the form is posted to the create
method, we’ll check the
login_changeset
and make sure it’s a good email/pass match.
Once there, we do the ‘logging in’ part.
This line invokes your serializer, generates your token with an expiry of what
you configured (10 days for this example), pushes it into the session and makes
it available on the request for further use. The :token
option is essentially
a label to identify the type of token (used in the :aud
field). This can be
anything but should be consistent.
Protecting your urls
So, now we have a logged in user, lets protect something.
In the user_controller.ex
I’ve cut most of it, but you can see in the edit action how we fetch the currently logged in user.
This illustrates a very simple use of Guardian. From here there are a lot of places to go.
- api vs session credentials
- custom ‘claims’ in the JWT
- permissions
- hooks
- mashups with existing frameworks
There’s a lot of places to go. I want to make sure the road to getting in is a simple as possible.