I’ve loved working on Guardian, but one thing has bothered me. When you logout,
vanilla Guardian (and all vanilla JWT implementations) don’t actuall invalidate
the token. All the information for the token is stored inside the token itself.
This can lead to short term expiry keys to try and keep a handle on it. Even
with this, you can’t actually revoke a token, so when someone logs out, their
token is still valid.
Initially my thought was to try and tie the token to the CSRF token, but this
turned out not to be such a good idea (and practially impossible with masked CSRF tokens). Instead I wanted a way to keep a tight leash on tokens, when you log out they should no longer be valid. I didn’t want to load up Guardian with a bunch of database assumptions and baggage for everyones app though so it had to stay out of Guardian core.
The result is GuardianDb. This is a
simple plugin that integrates via Guardian.Hooks.
With it:
Every token is stored in the database (keyed by the jti - uuid)
When it is encoded, a database entry is created
Every time you verify (page request) a token it is checked. If the entry is
missing, it does not verify
When you logout, or call Guardian.revoke! the entry is removed
You can also clear out stale tokens by
using GuardianDb.Token.purge_expired_tokens!
Setup is simple (and included in the README.md). Generate the migration and then add to your config:
You’ll need Guardian 0.6.1 or greater to have the right hooks available.
I’ve been getting some feedback that some of the modules and function aren’t
named such that their behaviour is immediately apparent, so I’ve renamed them.
The rename comes in with 0.6.0 and shouldn’t impact everyone.
The changes are:
The function signatures and module behaviour remains the same, it’s just a
rename.
Some time ago I introduced Hooks to Guardian. Hooks are a mechanism for you to
plug-in to lifecycle of authentication. These can be useful to extend or
customize the behaviour of Guardian within your application.
A Guardian.Hook is implemented as a behvaiour with default implementations of
each callback so you only need to implement what you’re interested in. The
available hooks are:
To create your own module just use the Guardian.Hooks module.
before_encode_and_sign
Runs before the jwt is generated. This can be used to add claims, or halt and
return an error.
after_encode_and_sign
This runs after the JWT has been encoded. Returning an error will not halt, but
can be used to to extend behaviour. For example store the token in a DB.
after_sign_in
Runs after a token is signed in (via a session). Use this to record information
about logins etc.
When you’re verifying tokens with Guardian, for API access you probably want to
use the Authorization header.
Usually these headers look something like
The bearer part is known as the realm. You might want to use different realms.
I remember writing and OAuth provider, and as part of renewing your token the
API required that the client and user tokens were set. For example, the client
being the application requesting the renual, and the user for the user who owns
the token.
These authentication headers can both be set on the same response.
Guardian can handle the easy case of token or many if that’s what you need.
These can go in your route file to form a plugin, or you can use them directly
in a controller.
Using the above as an example, you can include them in your pipelines
Inside your controller action, you can access each set in the usual ways:
Adding realm support is important for supporting robust API support. Having it
integrated seamlessly with Guardian should make it dead simple.
Recently masked CSRF tokens have shown up in Phoenix. Masked CSRF tokens are an
important feature to prevent against the BREACH attack.
Unfortunately masked tokens are incompatible with the way Guardian was using
them. It’s not all bad though, working through it, it turns out that the way
Guardian was putting the CSRF into the JWT wasn’t actually buying much in terms
of security. Since you need both pieces of information to connect to a channel,
you essentially have the lock and key and can reply the token.
After reviewing it I’ve decided to remove the functionality from Guardian. From
here it’s clear that there needs to be a more robust solution for revoking
tokens. That’ll be the focus of the next round of work on Guardian.
Part of the beauty of using JWT is that they have an expiry time built into
them. In my examples I typically expire them in 30 days, but you can configure
(or overwrite) this to be any value.
So we’ve added Guardian, created a user and we so far have the ability to create
a ‘login’ where they’re logged into the session, but what about API endpoints.
One thing that Guardian can do easily is authenticate your application for API
endpoints. Lets take a quick look at how that works.
In your router, add:
The verify authorization plug will check the Authorization header for a token,
and the LoadResource one will load any resource found there.
Ok, so now protecting your API endpoints is just like your web endpoints:
The interaction with API clients is just the same as web session clients. I’ve
used a different failure method in my SessionController, but other than this the
token is fine.
How do I get my token?
So far, we’ve only used the sign_in function on Guardian.Plug.
This is great for web pages but not quite enough for APIs. Lets
have a look at how to get a token:
This will generate a JWT that you can provide to your client, valid for the
configured ttl. Once you get to the controller it’s the same API as the browser
based authentication.
Your client can hand it in via the “Authorization” header.
For bonus points, you can also use it for channel authentication!
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.
I’m really loving using JWT’s for authentication. They’re a great little self
contained set of information that I can use, with or without hitting the db.
One thing that was missing was permissions. Anyone who’s implemented OAuth will
be familiar with why these are needed on a per token basis. Imagine you head
over to a site to OAuth an app. That app will be authenticating as you, but
usually with a customizable list of permissions. One of the tricky parts of this
is that once you add OAuth, you have to make sure all your relevant endpoints
(including downstream s2s) are aware of those permissions and have some way to
get to them. Not a fun X hours/days tracking all that down. Don’t worry.
Guardian has your back so you can make your apps permission aware as early as
you like.
JWTs need to be encoded so that they fit into the header of an HTTP request so
keeping them on the small side is pretty important. That’s why guardian encodes
all permissions into a bitsting for you.
Enough! Lets see it.
Config
You’ll need to include your list of known permissions in the config. Don’t worry
if you have to add some, Guardian will handle unknown permissions by ignoring
them.
Seems pretty straight forward right? The :default and :admin represent
different sets of permissions. You can have as many sets as you like. I’d lean
towards more permissions per set, than more sets though.
A word of caution. Guardian encodes permissions into bitstrings. The position
of the permission in the list is what determines it’s position in the bits.
Couple of things to keep in mind:
Re-ordering is bad
Renames are fine
Removals need to keep their place in the list
Ok, now that we’ve got the caveats out of the way, lets use it.
Sign in
You can encode these puppies right when you sign in.
Simple right. The same thing is true when encoding manually.
But what if I add a permission and I want the admin to have access to all the
things? (I hear myself asking myself).
By using the Guardian.Permissions.max/0 function, you get it all.
Checking permissions
To check them, you’ll need the claims.
Lets have a look then.
There’s also a plug version.
This will do an all? check on the permissions for any that you specify.
One thing to bear in mind with these permission sets. You shouldn’t feel locked
in stone on them. If you make a set and then find that you’d like to have a
different set, just deprecate the first one and create a new one. No problem.
Lastly, just in case you want to get right down into it.
For some reason, the first thing I look for when I’m building an application is
authentication. For me things are interesting when there’s something going on on
my apps, and that usually means letting people login.
I’ve been enjoying Elixir and so far there hasn’t been anything for
authentication that suited what I wanted. Using Phoenix is so nice, and make
things that are difficult or nearly impossible with other frameworks easy
(looking at you Channels).
One of the things that I really like about Elixir/Eralng, is that making all
elements of you application live in your application is (mostly) reasonable. Web
requests, web-sockets, mail even raw TCP sockets are all on the table. Time for
something new in auth.
Guardian is based on JWT. They are the self contained package of information that contains all the information you need for your authentication needs. For those unfamiliar I suggest having a look at the Registered Claim Names. These little packets of goodness can be used in a session, authorization header, passed in body params - they can even be used on raw sockets.
Lets look at what Guardian is not (for the moment).
It does not have any requirements around your model
It does not try to implement (or assist you to implement) checking login/emails
It does not try to do oAuth
Not to say that strategies won’t come sometime in the future, but for the moment
I’m not convinced that they’re actually within scope of the library. Guardian
strives to provide mechanisms for seamless authentication across different
access patterns, devices and S2S communications. How you determine that a user
is who they say they are is, at the moment beyond the scope.
So what’s it good for?
Guardian provides a mechanism for verifying previously asserted claims that
someone is who they say they are. Do this for browser based, api, channel,
socket communications or just because you can. The initial login is trivial,
it’s the other parts of the system where things get interesting.
Since Guardian is based on JWT, you can share the tokens with other systems that
you trust. The same shared secret will allow another system to verify the token
which is great for S2S systems. Your Elixir application can mint the credentials
(JWT) and other systems can verify them without a call to your Elixir
application, or they can mint credentials and have them used by your Elixir app.
Screw language differences.
Ok so lets see it then
I’m going to pull the code from my demo application: PhoenixGuardian.
Configuration
Add Guardian to your mix.deps:
Guardian relies on Joken for it’s JWTs. Guardian will bring it in, but you’ll
need to configure it.
A couple of things to note.
Jokens config_module should be set to Guardian.JWT
verify_issuer Set this to true if you want to only accept tokens generated by yourself (even if another app has your secret)
Please have different secret_keys per environment!
Guardian.Serializer
You’ll need the serializer so your app can serialize into and out of the token.
Don’t worry, this is Elixir, they’re easy.
Need to support different model types? Just add a pattern match in your serializer!
So, at this point, we’re setup to use Guardian, we just need to decide where
and how we’re going to apply it. I’ll show you the pieces.
Plug
Guardian comes with Plug integration. I’m going to focus on Phoenix but any plug
will work.
There are three phases to Guardians plug integration.
Verifying the token
Loading the resource
Requireing a verified token
These two pipelines will verify the token (if present) and load the resource if
there was a verified token found. If the token isn’t there or is invalid,
nothing bad happens, the load resource won’t do anything.
When we want to ensure that someone is authenticated we can ensure they have a
verified token.
Ok, so there’s some stuff going on there. Lets break it down.
The Guardian.Plug.EnsureAuthenticated checks to make sure there was a valid token
found. If it finds one we move on.
If the plug cannot find a verified token for the connection, it calls the
on_failure function. This function should be arity 2 and receive a Plug.Conn.t and it’s params. It’s up to this function to handle what should happen when things go south.
We could have put this plug in the pipeline, the only reason I didn’t do that
for this controller was because I wanted more control over the actions it fires
for, hence the when not action stuff.
Signing In.
Ok so, this is all good and well. We’ve configured it, setup a serializer, and
created our pipelines, how to sign in?
See that tiny line in the middle there. Guardian.Plug.sign_in(user, :csrf).
That’s it. Once you do that, your token is generated, pumped into the connection
and session and off you go.
The :csrf determines the tokens type (stored in the :aud field). This can be
anything you want it to be (e.g. ‘token’, ‘csrf’, ‘api’, ‘oauth’ etc).
Logout
Channels
Ok so, I did say you could use this for channels right. Here it is:
some_html.html
some_javascript.js
phoenix_guardian/user_channel.ex
When Guardian finds a valid token, it extracts the claims and the resource, and
calls join with them in the map. The keys to pattern match on for
authenticated joins are claims and resource.
When Guardian cannot verify the token, it will call handle_guardian_auth_failure with the reason it failed.
Well, thats a whirlwind tour of Guardian as it stands today. There’s a lot more
to say, but for the first post I think that will do.
Last week I was reading my friends blog Robot Dan
and came across his sudoku post.
I’ve never written a sudoku solver before, naturally I thought of writing it in
Elixir. I spent the evening playing around trying to come up with something that
was at least somewhat idomatic.
My first solution was a very similar implementation to what Dan had on his site.
It works ok. I found a harder board that made it take a bit longer.
Interestingly I found that the memory usage was flat for easy or hard. I’m
guessing that I got the tail recursion correct.
I wanted to do something a little more Elixiry though. When the recursive
function selects all possible values for a cell, and then recurses, that’s the point that I thought
I might be able to shoot out a bunch of processes and do all the calculations in
parallel. A branching recursive parallel implementation. Sounded fun!
I implemented it using Elixir Tasks and process dictionaries.
Unfortunately I went wrong somewhere. I ran out of processes, or simply timed
out. I even increased the number of processes to 5M without helping. It maxed
out in RAM, CPU and times out.
I think I’ll stick with the recursive solution, but I’ve included the other
below.