Repository: couchers-org/couchers
Issue: AttributeError: 'SignupFlow' object has no attribute 'token'

Sentry Issue: [BACKEND-2B](https://sentry.io/organizations/couchers/issues/2507366629/?referrer=github_integration)

```
AttributeError: 'SignupFlow' object has no attribute 'token'
  File "couchers/interceptors.py", line 226, in tracing_function
    res = prev_func(request, context)
  File "couchers/interceptors.py", line 150, in user_unaware_function
    return user_aware_function(req, context)
  File "couchers/servicers/auth.py", line 163, in SignupFlow
    send_signup_email(existing_flow)
  File "couchers/tasks.py", line 25, in send_signup_email
    signup_link = urls.signup_link(token=flow.token)
```

Changed files:
app/backend/src/tests/test_auth.py, app/backend/src/couchers/tasks.py

diff --git a/app/backend/src/couchers/tasks.py b/app/backend/src/couchers/tasks.py
index ae706683a..40d0906d8 100644
--- a/app/backend/src/couchers/tasks.py
+++ b/app/backend/src/couchers/tasks.py
@@ -22,7 +22,7 @@ def send_signup_email(flow):
     email_sent_before = flow.email_sent
     if flow.email_verified:
         # we just send a link to continue, not a verification link
-        signup_link = urls.signup_link(token=flow.token)
+        signup_link = urls.signup_link(token=flow.flow_token)
     elif flow.email_token and flow.token_is_valid:
         # if the verification email was sent and still is not expired, just resend the verification email
         signup_link = urls.signup_link(token=flow.email_token)
diff --git a/app/backend/src/tests/test_auth.py b/app/backend/src/tests/test_auth.py
index b0e7326db..e2e9ee847 100644
--- a/app/backend/src/tests/test_auth.py
+++ b/app/backend/src/tests/test_auth.py
@@ -779,4 +779,44 @@ def test_complete_signup(db):
         assert e.value.details() == errors.INVALID_COORDINATE
 
 
+def test_signup_token_regression(db):
+    # Repro steps:
+    # 1. Start a signup
+    # 2. Confirm the email
+    # 3. Start a new signup with the same email
+    # Expected: send a link to the email to continue signing up.
+    # Actual: `AttributeError: 'SignupFlow' object has no attribute 'token'`
+
+    testing_email = f"{random_hex(12)}@couchers.org.invalid"
+
+    # 1. Start a signup
+    with auth_api_session() as (auth_api, metadata_interceptor):
+        res = auth_api.SignupFlow(auth_pb2.SignupFlowReq(basic=auth_pb2.SignupBasic(name="frodo", email=testing_email)))
+    flow_token = res.flow_token
+    assert flow_token
+
+    # 2. Confirm the email
+    with session_scope() as session:
+        email_token = (
+            session.execute(select(SignupFlow).where(SignupFlow.flow_token == flow_token)).scalar_one().email_token
+        )
+
+    with auth_api_session() as (auth_api, metadata_interceptor):
+        res = auth_api.SignupFlow(
+            auth_pb2.SignupFlowReq(
+                flow_token=flow_token,
+                email_token=email_token,
+            )
+        )
+
+    # 3. Start a new signup with the same email
+    with auth_api_session() as (auth_api, metadata_interceptor):
+        with pytest.raises(grpc.RpcError) as e:
+            res = auth_api.SignupFlow(
+                auth_pb2.SignupFlowReq(basic=auth_pb2.SignupBasic(name="frodo", email=testing_email))
+            )
+        assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
+        assert e.value.details() == errors.SIGNUP_FLOW_EMAIL_STARTED_SIGNUP
+
+
 # tests for ConfirmChangeEmail within test_account.py tests for test_ChangeEmail_*