Confirmation link not working in custom sign-up flow

Hi there,
I am currently using the custom sign-up flow as a dependency for a login device for my app. However, something seems to be off with the email confirmation. When registering, the email gets send to the address properly, but when clicking on the link, it does not set the confirmed_email variable to True and also does not login the user. It simply shows the login page.
I tried this in debug mode and publication mode, both do not work.

Code Sample:
this is the login button click

def button_1_click(self, **event_args):
    custom_signup.login_flow.login_with_form()
    self.update_login_status()
    user = anvil.users.get_user()
    if user is None:
        alert("Login failed. Please try again.")
        return  # Exit the function if no user is logged in
    Globals.user_email = user["email"]

this is the confirmation link to be sent out. I tried with {anvil.server.get_app_origin(‘published’)}#?email={url_encode(user[‘email’])}&confirm={url_encode(user[‘link_key’])} in published mode and {anvil.server.get_app_origin()}#?email={url_encode(user[‘email’])}&confirm={url_encode(user[‘link_key’])} in debug mode. both fails.

@anvil.server.callable
def _send_email_confirm_link(email):
  """Send an email confirmation link if the specified user's email is not yet confirmed"""
  user = app_tables.users.get(email=email)
  if user is not None and not user['confirmed_email']:
    if user['link_key'] is None:
      user['link_key'] = mk_token()
    anvil.email.send(to=user['email'], subject="Confirm your email address", text=f"""
Hi,

Thanks for signing up for our service. To complete your sign-up, click here to confirm your email address:

{anvil.server.get_app_origin('published')}#?email={url_encode(user['email'])}&confirm={url_encode(user['link_key'])}

Thanks!
""")
    return True

This is the function that should identify the hashed content:

 
    
def do_email_confirm_or_reset():
  """Check whether the user has arrived from an email-confirmation link or a password reset, and pop up any necessary dialogs.
     Call this function from the 'show' event on your startup form.
  """
  h = anvil.get_url_hash()
  if isinstance(h, dict) and 'email' in h:
    if 'pwreset' in h:
      if not anvil.server.call('_is_password_key_correct', h['email'], h['pwreset']):
        alert("This is not a valid password reset link")
        return

      while True:
        pwr = PasswordResetDialog()
        if not alert(pwr, title="Reset Your Password", buttons=[("Reset password", True, 'primary'), ("Cancel", False)]):
          return
        if pwr.pw_box.text != pwr.pw_repeat_box.text:
          alert("Passwords did not match. Try again.")
        else:
          break
  
      if anvil.server.call('_perform_password_reset', h['email'], h['pwreset'], pwr.pw_box.text):
        alert("Your password has been reset. You are now logged in.")
      else:
        alert("This is not a valid password reset link")

        
    elif 'confirm' in h:
      if anvil.server.call('_confirm_email_address', h['email'], h['confirm']):
        alert("Thanks for confirming your email address. You are now logged in.")
      else:
        alert("This confirmation link is not valid. Perhaps you have already confirmed your address?\n\nTry logging in normally.")
 

This is the server function that should be called once the hased content had been validated:

 @anvil.server.callable
def _confirm_email_address(email, confirm_key):
  """Confirm a user's email address if the key matches; return True if it did."""
  user = get_user_if_key_correct(email, confirm_key)
  if user is not None:
    user['confirmed_email'] = True
    user['link_key'] = None
    anvil.users.force_login(user)
    return True
 

This is the link that got sent in the debug mode (I inserted a fake email-address for the Q&A here):
“https://my_app.anvil.app/debug/UHWIYGG2JYGP5H2OR62VFXI3A7VIRJAM%3DCA6OOJX4STN5V4DHZGIODP7K#?email=my_email%40gmail.com&confirm=IX5VAyvDiYACJ2”

This is the email link in publication mode (I inserted a fake email-address and app name for the Q&A here):
“https://my_app.anvil.app?email=my_email%40gmail.com&confirm=VBFMbrzvTgscj8”

Would be great, if anyone had an idea on how to fix this.

Have you tried printing out h after h = anvil.get_url_hash() to see what you’re getting? You could also use an alert so you don’t need to find it in the app logs.

1 Like

Thank you for your response. I tried and it does not print anything. However, the window that opens the login page through the email link is in normal browser mode and not in debug mode. Maybe that’s why. Yet also the anvil-log-file does not show anything.

Hello @new_pystronaut_45.

The example email link that you’ve provided for Publication mode

actually has no hashmark within it, so it would be correct for the get_url_hash() function not to return anything.

The _send_email_confirm_link(email) code that you shared

{anvil.server.get_app_origin('published')}#?email={url_encode(user['email'])}&confirm={url_encode(user['link_key'])}

should generate a URL that contains a hashmark – but it’s hard to know how to proceed without knowing which element you shared (the code or the link) is inaccurate.

p.s. Not sure that you need or want to pass the ‘published’ parameter to the anvil.server.get_app_origin call in this case.

Thank you for the response.

Sorry for the missing hashmark in the published app. This is because I tried around with adding and leaving it out. Even when having the hashmark in the published version, it did not work. So I suppose it is the bug must be in the code, since the links seem fine.

Got resolved.
I should have made Module1 the start-form and not Form1. Sorry for the buzz and thanks for the comments.

1 Like

Congratulations on solving your problem!

You may want to flag this one as solved. This will help others find your solution.