What is your method to reimplement authentication in your new projects

Hi,

After starting several projects in phoenix I had to add to the each of one authentication. Every time I had to parse this tutorial Phoenix: simple authentication & authorization in step-by-step tutorial form on medium(that is a little outdated) and git log -p uye3rt7346rt4376 to get inspired by my old projects, and copy/paste. So I needed to make myself some guide.

I use my gist on github to keep the important files and some blog I maintain(you can find the link to my tutorial in the gist).

My question is, what is your easy method to reimplement authentication in your new projects.

I can modify my gist and tutorial in case you give me constructive feedback :slight_smile:

I made AccessPass for this reason. I may be useful to you. I currently use it in all my new project and plan to continue to work on it based on what people want.

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

And here is a quick blog post to give you an idea of how easy it is:

as for your gist. It may make sense to put it into a hex package if you think others will fine use it it.

2 Likes

My gist can only be used as a reference as every project has it’s own specifications.

I have a hard time grasping new tech, AccessPass might be good, but I would like to see some detailed tutorial like the one from medium Phoenix: simple authentication & authorization in step-by-step tutorial form without the post related stuff. I just don’t have the image in my head of how several things would work.

Do you have a hard time customizing it for specific requests?

1 Like

The blog above it pretty much step by step although it is “slightly” out of date as accessPass now uses bamboo for mail. As for customizing it for specific requests their are quite a few hooks I have built in with more to come for times I need to do things different then what is provided out of the box.

you can see some more information on that here:

https://hexdocs.pm/access_pass/configuration_options.html#content

The only thing that admittedly sucks for now is it requires a certain schema. That will be changing in the next version of AccessPass.

But it may not be much of a help to you as AccessPass only provides the logic for authentication. Not the view. You could certainly integrate it into your applications views though.

But minus the schema being required AccessPass is a pretty “general” way to handle authentication so if you have a scenario in your head you are trying to handle let me know and we can try and see if AccessPass will work for it.

I have something that’s close to phxauth, but is entirely own rolled and not generalised. but I have a nagging feeling in my brain about it. Channel and API auth for some frontend JS bothers me a little. I periodically look at the number of packages out there but none seem to stand out. Admittedly I haven’t looked at AccessPass yet.

Your gist and linked article has at least 1 issue thst jumps out at me (forgive me if I missed something, I’m typing this just before bed) If a user changes their credentials in your example any existing logged on sessions will carry on working. You or the user have no means to effective reject the other logged in sessions.

A relatively simple patch is to add a password_last_changed time stamp or generate some kind of token against the user that’s always changed when the password changes, or using a part of the salt like devise does.

You mean if the user changes his password in another browser? In a context with no channels involved, how will I tell if that happens? I am wondering why would I even want to log out the other sessions… thanks for your observation

Let’s take my partner as a classic, real life, example. She uses a small number of fixed passwords and randomly picks one for each service. She doesn’t use password wallets, despite best efforts from those around her.

One day one service she uses gets owned and suddenly one or more of her passwords are in a leaked password list with her email.

If a malicious user logs in to your service before she changes her password, the malicous user can continue using the account as long as they stay logged in. No matter how many times she changes her password. If you’re exchanging services or goods for money, this is a real problem.

There are several “fixes”, none that need channels. Easiest to understand and implement with what you have is to store a “last date time password changed” in both the database and token (the token you’re generating using guardian should have both the user id and this date). If they don’t match then the user changed their password and that session shouldn’t be consider valid and instantly logged out at next request.

There are alternatives, which include, but not limited to; random strings instead of date times, totally random in a sessions database instead of just user ids in the token, or recording tokens generated by guardian and then checking if you need to revoke them later.

Hope that helps :slight_smile:

User management and security is hard to get right. I rather like to focus on my own application so I delegate authentication and authorization to a SaaS provider. Given the link below, I think it’s clear what I use:

Ringo

I see, so at each request I have to check if things changed. I guess that includes ajax calls too.

You do that when you call Repo.get User in your guardian serialiser anyway. It’s a small change to that query, and more often than not you might want to check the user hasn’t been disabled, roles or some other attribute changed, look up their name for a greeting, etc etc.

So my opinion is that for most apps you’ll be talking to the DB anyway to fetch the user account for at least something, so the overhead is irrelevant. Plus if you depend on the DB entirely for the functionality of your app if the DB isn’t there it’s not going to work anyway :slight_smile: If you end up assigning current user to conn.assigns then you can just check the DB and set the current user in the same step.

If you have lots of micro services then ”proper” tokens can be more important. most people don’t have micro services though.

As with all things you need to build for your product and environment. It’s up to you if you believe one choice is more appropriate than any other :man_shrugging: