Skip to content

Invites are silently dropped for existing users (sign-in path), forcing them into the "Create project" onboarding wizard #385

Description

@jonstuebe

Summary

When an invited person authenticates as an existing user (rather than creating a brand-new account through the invite link), the inviteId is never consumed. They end up belonging to zero organizations and are redirected into the "Create project" onboarding wizard instead of joining the org they were invited to.

Related: #363

Expected behavior

Accepting an invite should add the user to the inviting organization regardless of whether they are a new or existing user, and regardless of whether they go through sign-up or sign-in.

Actual behavior

The invite is only applied during new-account creation. Existing/returning users who authenticate are added to no organization, so index.tsx redirects them to /onboarding/project (the Create Project wizard).

Root cause

Membership is created exclusively by connectUserToOrganization({ user, inviteId }). It is called in only three places:

  1. inviteUser mutation (packages/trpc/src/routers/organization.ts) — only when the invited email already has an account at invite time (userExists).
  2. signUpEmail (packages/trpc/src/routers/auth.ts) — new email signup, with inviteId.
  3. OAuth handleNewUser (apps/api/src/controllers/oauth-callback.controller.tsx) — new OAuth signup, with the inviteId cookie.

It is not called in:

  • handleExistingUser (apps/api/src/controllers/oauth-callback.controller.tsx) — the inviteId cookie is read at the top of githubCallback / googleCallback, but it is never passed into the handleExistingUser branch, so it's silently dropped.
  • signInEmail (packages/trpc/src/routers/auth.ts) — no inviteId parameter exists on this procedure.

In addition, the invite email links to /onboarding?inviteId=…, but that page's "Already have an account? Sign in" link points to /login with no inviteId, so a returning user loses the invite the moment they click it.

Steps to reproduce

  1. User A already has an OpenPanel account (or signs up independently).
  2. Admin invites User A's email to an organization.
    • (If User A's account exists at this exact moment, inviteUser auto-adds them and the bug is masked.)
  3. From the invite email, User A opens /onboarding?inviteId=… and clicks "Sign in", or signs in with a GitHub/Google account whose email already exists.
  4. User A is authenticated via handleExistingUser / signInEmail. The inviteId is ignored.
  5. With zero org memberships, index.tsx redirects User A to /onboarding/project (Create Project wizard) instead of the invited org.

Suggested fix

Honor inviteId on the existing-user paths as well:

  • Pass the inviteId cookie into handleExistingUser and call connectUserToOrganization there.
  • Add an optional inviteId to signInEmail and consume it on success.
  • Carry the inviteId through the "Sign in" link on /onboarding so it isn't lost when a returning user authenticates.

Environment

  • Self-hosted OpenPanel

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions