phx.gen.auth will generate some useful pieces, but not the whole thing. I recommend running it and reading the code it produces.
The role separation could be represented in a lot of different ways. It may even be better represented in multiple ways. For instance:
“admin” vs “non-admin” could be a flag on a shared User schema, or it could be two separate auth setups for Users and Admins.
The latter can be useful in domains where making “a user cannot become an admin via hacking” difficult is important.
on the other hand, “free” vs “paid” is more likely to make sense as one schema, since the main purpose of free accounts is to convert into paid
for paid users, there’s also the question of where to put payment info / plan details. I’d strongly consider keeping those separate from the User schema used for authentication, since customers love to ask “can I have one payment for my ten employees to all have accounts”. Even if you don’t allow for multiple users per account in this initial setup, it will be easier to change a has_one :user to has_many :users (versus splitting apart the functionality in a working app).