AccessPass - a opinionated authorization library

authentication
Tags: #<Tag:0x00007f114035da10>

#1

I spent the last couple weeks writing my own authorization library that provides all the basics like login,logout,register,forgot password,forgot username and email confirmation. I found myself re implementing auth every time I started a project because I did not quite like the options out there(hence why the lib is quite opinionated).

AccessPass is token based(kind of actually you send id’s in place of tokens) that is backed by a genserver for refresh tokens / access tokens.

This is my first hex package published so I would love some feedback.

The one thing left to do for me is write tests.

https://hexdocs.pm/access_pass/introduction.html

Thanks!


#2

@jordiee AccessPass looks cool. I have been looking for an authentication library, and this one looks promising. I would be curious to read about how it’s opinionated – what aspects of exising auth libraries you have borrowed and which ones you didn’t like. On a different note, does it support JWT tokens?


#3

Hi anandtrex. As for how it is opinionated as of right now it locks you into using postgres as your database. It currently does not support JWT but I may change it in the future to add your own token generation. Right now “tokens” in essence are base64 uuids that are sent back and used as lookup keys for a session. The defaults out of the box may be different for some people but most things are overridable.

As for what I took from other libraries I really liked addict for elixir but wanted things to work slightly different in the sense that I wanted it to be token based and I wanted tokens to be revokable. I did some research on best methods of security a while back and have for quite some time now been doing short lived access_tokens(5 minute default) and long lived refresh tokens(default no expire). That way if someone did manage to get their hands on an access token it would only be valid for a couple more minutes.

The goals for accessPass were actually quite simple. I wanted a “token” based authentication system that could be dropped into applications and gave all the basics(login, logout, register, forgot password, confirmation email, ect) while keeping the library very fast and very secure.


#4

^ for any suggesting/issues/pull requests. They are always welcome!


#5

Hi @jordiee I guess just having a dependency on postgres is not too opinionated :slight_smile: . I think having one lightweight library that works out of the box for APIs is good for the ecosystem.

If I understand from your documentation correctly, you store the auth and refresh tokens in a GenServer and serve it from there. This means that whenever the service is restarted, the user would have to authenticate again. And I’m guessing it wouldn’t be too easy to scale it horizontally. I wonder if it would be a good idea to persist the refresh token in the database, so that other instances of the service can be spun up, which would have access to the refresh token through the database. As long as the reverse proxy in front of the service is sticky enough, it would be possible to have many instances of the service running with the ability to switch the user from one to the other.
I’m interested in hearing your thoughts on this. I don’t have a lot of experience with auth so I might be missing something here.


#6

That is correct to some extent. I actually made some changes recently so that the primary storage is ETS but all writes to ets are serialized through a genserver. I did this so that doing access_token checks was not a bottleneck and getting serialized. As for losing all tokens when servers is restarted this is correct in that if the service is restarted or crashes all tokens will also go with it. If you do not want tokens to go when restarting the server maybe look into hot updates but as for crashes…when designing the system. I weighed out if it would be worth it to back up the ets table on crash but decided against it. I decided against it because something that leads to a crash…in all honesty is most likely a bug that needs to be fixed. The storage should not crash if it is bug free. So I would rather it crash and I/or some else put a pull request in to fix the bug.

As for having it backed by a db. I decided against this because speed was a huge concern for me. I have implemented auth systems before that stored tokens in a db and it was noticeable to have to hit a database on every call that is authorized. I ended up switching them to redis in the end but with elixir and ets it does not seem needed.

As for scaling horizontally right now you are correct in that it would be hard to do. I am potentially going to look into mnesia rather then ets to have a shared table of tokens. But for now if you are worried about scaling applications horizontally separate of AccessPass I suggest setting up a normal phoenix app and just having accesspass run on it. From their all of your services that need auth can delegate calls via http to your “auth server” as for authorizing individual routes this way you can use the /check endpoint in much of the same way the plug is used. The downside to doing it all this way is it is slower because it goes over the network but the pro is you can scale your application separate of accesspass