I’m fairly new to both Elixir and Phoenix, although I have quite a bit of experience with other languages and frameworks and I’m usually able to figure things out.
I’m working with Phoenix 1.7, liveview and gen.auth. I don’t want users to be able to register. Instead, when you staff members join, an administrator would set up user accounts for them. I would have thought this would be a farily common use case, but maybe I’m wrong, because I haven’t found much searching.
I get that I can remove/comment out the registration endpoint. And I need to create endpoints for an admin to manage users. What I’m now sure about is how to go about the confirmation. Looking at the code, removing confirmed_at from the model doesn’t seem like the right way forward. Or is it?
I’m guessing somebody else has been in the same situation and solved it. How did you go about it? What would be the most straight-forward way to disable self-registration and not require user confirmation?
phx_gen_auth is meant to give you the bare-minimum needed to get going with auth. If you are looking for more fully-featured auth, you can look at Pow although its LiveView support isn’t all there yet but it’s coming.
Otherwise, I recently did what you’re describing in phx_gen_auth by repurposing the reset password form and the confirmation token. I did the following:
Removed the registration form and anything related to it
Added a user creation form to my admin area which:
sets a long random password with :crypto.strong_rand_bytes/1
sends the user their confirmation email with the token link
Changed the confirmation page to display the reset password form and only mark the user as confirmed when they have set their new password.
Ensure users can’t login until they have been confirmed (this is not done by default by the generator)
One gotcha is that if you are generated auth using LiveView and you want to auto-login the user after they have set their new password, the confirmation page should use a controller, not a LiveView. This is because you can’t set session data over websockets.
I know other people around here have done something similar approaches if you search around. If you choose to go this route then I’d be happy to try and answer any questions!
Yes, I had also seen Pow and I found it interesting. I was a bit confused about whether I should try to stick with the built-in batteries or add external ones. You have motivated me to give Pow a try and to compare the results for myself.
Your registration flow is pretty much exactly what I’m also looking to do. And thanks also for pointing out that gotcha. That is typically the kind of thing I’d overlook and spend hours trying to figure out why it’s not working.
You can read the motivations behind phx_gen_auth here. If that resonates with you then I would stick with it, otherwise using something else is perfectly acceptable. There is certainly no notion that one is better than the other, it all depends on your needs and usage!
Good point. I’m not planning on getting rid of it, just leaving it out of the user creation flow (at least for the time being). It may make its way back in eventually, as per the flow @sodapopcan outlined.
Ha, you called me out on two little sticking points I had with my answer
The first I just don’t like how I worded it, but “a starting point” is what I meant by “get going with.” If all you need is an email/password auth system, it’s perfect (with a few tweaks like checking confirmation field and probably adding the user’s name). And just in case: I also didn’t mean “bare minimum” to be reductive in any way!
Secondly yes, you should keep the confirmation step around if having an account lets you do sensitive things! In my case, my client has email correspondence with everyone she invites, there is no sensitive data available, and there are no financial features, so I didn’t want to add that extra step.
Sorry to necro this thread but I’m writing a little debrief on this.
I was thinking about this more. As far as I can tell, the main security risk here is that someone intercepts the invite email, likely by already having access to that email account. So sending out a “regular” confirmation email afterwards is not going to help. It seems we’re guarding against a rare scenario where someone is able to intercept the invite but not the confirmation email. So long as we’re ensuring you may not log in without being confirmed, “auto-confirming” after setting up a new password should be enough. Am I missing something?
How does the admin provide passwords for the users they setup? How do you do this securely?
Are you using local password or an external authentication service such as social login via Google, Facebook, Apple etc?
If you are using a local password an alternative approach than say sharing passwords with these user’s would be to set a random pre-expired password and to send a confirmation link to the user. When the user comes back, force a first time password reset, this way you’re using time limited confirmation links and only the user knows their password going forward. You generally always want to avoid the admins having visibility of user passwords.
If you have also established secret/answer challenge questions, this would also be the right time to use them.
Hey Andrew! I outlined here how I’m doing it (I’m not OP of this thread, I was answering the question).
I’m just doing plain ol’ username/password with confirmation email and reset password repurposed for the invite. LKK mentioned that it might be a good idea to make them confirm their email anyway. That made sense to me but thinking about it more, since the invites are sent from the app to a known email, ie, users aren’t requesting an invite I’m now not seeing how requiring an extra confirmation step on top of that is really that much more secure. If users are requesting invites then it probably makes sense, though they would still need access to the email to get the invites so it doesn’t seem all that much more secure.
I’m not sure, to be honest. I’m a developer that follows a spec I’ve been given. I have fairly little insight into how the client actually uses the software. I’d have to talk to the training or devops guys. They interact with the clients.
Local, only. Once you get out of the major cities, Internet here can be really flaky. In some places it can be completely off for days and even when it’s not, it can be really unreliable.
Good idea, apart from the fact that it again relies on external resources. We could of course fire up a local postfix server. Just seems a little more trouble than its worth. Somebody’s going to have to administer the server.
It’s not in any spec yet, but it might be something for the future.
While it may not be exactly what you’re seeking, I humbly believe that it could potentially serve a similar purpose in certain scenarios. For example, in my case, I didn’t want to allow public self-registration on a platform reserved only for administrators. I was largely inspired by the blog post I cited, to extend the authentication system generated by phx.gen.auth for my own purposes. I made some modifications of course but the bulk of the work comes from this article.
The main lines of what I set up:
A superadmin can generate a registration link (whose token expires in 24h) which he will copy and send to the future admin by a means of his choice.
The registration token which is saved in the database is scoped on information such as the role of the future user, the id of the superadmin who generated it. If you want you can put other information like the email of the future user, etc. In my case, I prefer to leave this to the concerned person himself when creating his account later.
I practically didn’t change anything in the code generated by phx.gen.auth but I just modified in my router.ex file the directive that pointed to the registration page so that it now uses an additional parameter which is nothing other than the registration token. The registration logic naturally will change a bit depending on what you have planned. You need to check if the token is valid and maybe customize and initialize the registration form according to the information you want to leave to the control of the user creating his account. For example, enter his own email and password that he will be the only one to know then. For the role in my case it’s not something he can control naturally so it is assigned to him automatically when creating the account.
I didn’t touch the confirmation logic because it can’t hurt. I prefer to automatically confirm my users if necessary. And incidentally, confirming an email, for me, is also a bit for cases where someone makes a mistake by entering someone else’s email. And if we want to reinforce things a bit, we could invalidate this registration by deleting the account after a certain delay without confirmation for example.
There you go. ^^
Hoping that you also find some utility to the links that I shared above.
Yeah I was only targeting admin created users, it would just send a link to the new users email and that user can use that to complete the registration and set their password pretty much what @Kurisu has shown.