goauthentik / authentik

The authentication glue you need.
https://goauthentik.io
Other
13.47k stars 899 forks source link

Verify email when changed from user settings #4097

Open fuomag9 opened 1 year ago

fuomag9 commented 1 year ago

Is your feature request related to a problem? Please describe. I need to avoid user setting a mail they don't own, bypassing the enrollment email verification check (as they can use a verified one during signup and then set an unverified later in the settings)

Describe the solution you'd like Bind a flow to email change in settings, so email can be verified.

Describe alternatives you've considered None, currently my only alternative is to disable email changes :(

Additional context None

astro-stan commented 1 year ago

authentik applies a DIY approach to autnetication, authorization and user management. You can enhance the user settings flow and make it do almost whatever you like.

For example, you can add an email verification stage to the user settings change flow. Similar to the enrollment flow, you should add it after the user info prompt stage but before the user write stage. Doing so will prompt the user to verify their email and if they can't no changes will be saved.

However, as far as I know it is not currently possible (as far as I know and have tested) to conditionally add the email verification stage based on whether the email property has been changed in the prompt stage before it. In my testing adding a policy binding to the email verification stage binding does not see the context generated by the previous prompt stage, thus it is not possible to skip the email stage based on the context. All of this means that your users will need to verify their email every time they change any of their user settings.

Disclaimer: I am just another user of authentik.

fuomag9 commented 1 year ago

I'm still "new" to authentik but I guess that as a temporary fix it's still way better than nothing! (As the user can now at least change email, and I guess changing the name is probably a "rare" thing to do that won't annoy them too much if they have to verify the email as well)

Thank you btw, and I hope things can be improved (or figured out)

fuomag9 commented 1 year ago

Another place that could need email verification "attached" is when users are manually created by admins. (in keycloak you can attach "actions" to users that they have to do such as having to reset their passwords or verify their email)

astro-stan commented 1 year ago

I would strongly encourage you to spend a few hours reading through the documentation. authentik can be a very flexible and powerful tool but it definitely has a steeper learning curve than some of the competition.

fuomag9 commented 1 year ago

I would strongly encourage you to spend a few hours reading through the documentation. authentik can be a very flexible and powerful tool but it definitely has a steeper learning curve than some of the competition.

Docs are very lacking in some aspects unfortunately :(

astro-stan commented 1 year ago

Another place that could need email verification "attached" is when users are manually created by admins. (in keycloak you can attach "actions" to users that they have to do such as having to reset their passwords or verify their email)

If you are looking for general help and you cannot find it in the docs you should consider joining the discord channel .

But to try to answer your question:

I think you can add an email verification stage to the authentication flow and set it to activate users on successful verification. Then attach a policy binding to the stage. The policy binding should be an expression policy that checks if the user is active request.user.is_active. The policy should fail if the user is active (thus skip the email verification stage from the flow). Then your admin should create the users as inactive. On second thought that won't work - your users will not be able to authenticate. BUT you can add new users to certain group (or even add some custom property to an individual user). Then check for that in the expression policy. If present, show an email verification stage and when completed remove the group/property from the user.

Alternatively - you can consider implementing an enrollment flow with an invitation stage. This will allow you to preset certain user properties (much like an admin creating a new user manually).

astro-stan commented 1 year ago

authentik applies a DIY approach to autnetication, authorization and user management. You can enhance the user settings flow and make it do almost whatever you like.

For example, you can add an email verification stage to the user settings change flow. Similar to the enrollment flow, you should add it after the user info prompt stage but before the user write stage. Doing so will prompt the user to verify their email and if they can't no changes will be saved.

However, as far as I know it is not currently possible (as far as I know and have tested) to conditionally add the email verification stage based on whether the email property has been changed in the prompt stage before it. In my testing adding a policy binding to the email verification stage binding does not see the context generated by the previous prompt stage, thus it is not possible to skip the email stage based on the context. All of this means that your users will need to verify their email every time they change any of their user settings.

Disclaimer: I am just another user of authentik.

Apologies, looks like I lied about this. I decided to try again and It IS possible to make email verification conditional. You need to use the same policy-binding-to-stage-binding technique. Just make sure that:

asifbacchus commented 11 months ago

Sadly, it appears this solution does not work (anymore?). The idea of the policy and email stage is correct, however, the email stage errors out with "No pending user" as per #6123.

Anyone have other ideas for verifying changed email addresses?

juliadin commented 6 months ago

Same here. I have two policies checking the user input regarding email I have to review the policies first though because I seem to have some concepts wrong in working with prompt data

and it errors out with 'no pending user' when trying to send the email in a Settings flow

juliadin commented 6 months ago

I have a not so shiny workaround that is potentially even dangerous.

I have created three policies to detect and verify a changed email address. I have a custom settings page but that doesn't matter regarding the email verification. The settings page's email field has the 'field' email and type email as well.

The reasining was: if the email stage tries to find a 'pending user' because it is probably more likely to be used for password resets or account activations (after an identification stage was run which sets a pending_user) ... then let's make one.

Email Stage is set to 'all policies must allow' - playing with the return values you could do it differently.

# detect changed email address
current = ''
new = ''

try: 
  current = request.user.email
except:
  current = ''

prompt_data = request.context.get("prompt_data")
new = prompt_data.get('email','')

ak_message(f'{current},{new}')

if current != new:
  # changed email
  return True

# same email as before
return False
# if there is a request user but no pending user, copy it to the flow context (is this dangerous?)

if not request.context.get('pending_user'):
  if not request.user:
    ak_message('not authenticated')
    return False
  context['flow_plan'].context['pending_user'] = request.user
  ak_message('pending user copied')
  return True
ak_message('pending user alredy present')
return True
# change destination address for the email stage according to https://docs.goauthentik.io/docs/flow/stages/email/
request.context["flow_plan"].context["email"] = request.context["prompt_data"]["email"]
return True

I verified in the admin interface that in none of the cases, the values were applied before validating the email address by interacting with the link. Sometimes, after going to the user settings page after having clicked a validation link, the interface tells me that no flow has been configured for user settings. Logging out and in again fixes this. Reloads don't.

I am running the 2024.4 release from yesterday

juliadin commented 6 months ago

Just to add: it does not work with anonymous flows (e.g. before writing a user at enrollment to check the mail address) because some part of the process expects a 'User' object and the user I am copying seems to be an 'AnonymousUser' object. I didn't expect it to, but it would have been nice to have that working.