OpenHands / OpenHands/enterprise

OAuth Email Verification Trap: Users Can Change to Unverified Emails

Open
#49 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Python
Stars
4
Forks
2
Avg merge
1d 22h
Merged PRs (30d)
101

Description

OAuth Email Verification Trap: Users Can Change to Unverified Emails

Problem Description

When users authenticate via OAuth (GitHub/Google), their email is initially verified by the OAuth provider. However, the system allows users to change their email address to any arbitrary email in the Enterprise Server UI. When they do this:

  1. The new email is set as their account email
  2. email_verified is set to false
  3. A verification email is sent to the new address
  4. The user interface provides no way to resend this verification email

If the user misses the verification email (spam folder, typo in address, etc.), they become stuck in a state where:

  • Their account shows email_verified: false
  • They cannot verify their email because there's no resend button in the UI
  • Depending on the client (Agent Canvas), they may lose access to features

This creates a permanent trap - once a user changes their email and misses the verification, they have no self-service recovery path.

Additional Complexity: GitHub Multiple Email Addresses

GitHub allows users to have multiple email addresses, each with independent verification status. Users can:

  • Add multiple emails to their GitHub account
  • Set any email as "primary"
  • Change which email is primary at any time

The primary email is what GitHub returns during OAuth, along with its verification status. This creates scenarios where:

  • A user's GitHub primary email is unverified → OAuth returns email_verified: false
  • A user changes their GitHub primary email → their OpenHands email verification status changes on next login
  • A user has verified emails in GitHub that aren't being used in OpenHands

Currently, OpenHands doesn't capture or expose the user's other GitHub emails, limiting their flexibility.

Current Behavior

OAuth Login Flow:

1. User authenticates with GitHub
2. GitHub returns user info including:
   - email: user's primary email in GitHub
   - email_verified: verification status of that primary email
3. OpenHands stores this email and verification status
4. User has access to the system

Email Change Flow (via Enterprise Server UI):

1. User navigates to settings and changes email
2. Backend sets email_verified = false in both:
   - Keycloak (emailVerified: false)
   - OpenHands database (email_verified: false)
3. Verification email is sent to new address
4. User must click verification link to restore email_verified = true

The Problem:

  • No UI exists to resend the verification email
  • User cannot recover if they miss the initial email
  • Admin intervention may be required to fix stuck accounts

Proposed Solution (High Level)

Option 1: Capture All OAuth Provider Emails

When a user authenticates via OAuth:

  1. Fetch all their emails from the OAuth provider (e.g., GitHub's /user/emails API)
  2. Store all verified emails from the provider
  3. Let users switch between their verified OAuth emails
  4. Only allow switching to emails that are already verified by the provider
  5. Keep manual email changes for users who want to use non-GitHub emails (with verification)

Benefits:

  • Leverages OAuth provider's email verification
  • Gives users flexibility to choose which GitHub email to use
  • Prevents the unverified email trap for OAuth users
  • Stays in sync with GitHub when users add/remove/verify emails there
Option 2: Add Email Verification Recovery UI

At minimum, add UI elements to:

  1. Show current email verification status clearly
  2. Provide a "Resend Verification Email" button
  3. Allow users to revert to a previously verified email

Benefits:

  • Simpler implementation
  • Provides escape hatch for trapped users
  • Works for both OAuth and password authentication users
Recommended: Combination Approach
  • Implement Option 1 (capture OAuth emails) for OAuth users
  • Add resend verification UI for manual email changes
  • This provides both prevention and recovery

Impact for Agent Canvas

Agent Canvas currently disables navigation links when email_verified === false. This is more strict than the Enterprise Server backend (which allows all API operations regardless of email verification status).

The combination of:

  1. No email verification recovery UI in either Enterprise Server or Agent Canvas
  2. Agent Canvas blocking navigation for unverified emails
  3. Users being able to change to unverified emails

Creates a situation where OAuth users can accidentally lock themselves out of Agent Canvas features by changing their email address.

Related Code Locations

  • Email change endpoint: /workspace/OpenHands/enterprise/server/routes/email.py
  • OAuth login flow: /workspace/OpenHands/enterprise/server/routes/auth.py (around line 400)
  • User settings model: /workspace/OpenHands/enterprise/storage/user_settings.py
  • Token manager (fetches OAuth user info): /workspace/OpenHands/enterprise/server/auth/token_manager.py

User Impact

Current State:

  • Users who change their email and miss verification are permanently stuck
  • No self-service recovery mechanism exists
  • Requires manual database/Keycloak intervention to fix

Desired State:

  • Users can choose from their verified OAuth emails without re-verification
  • If users add custom emails, they have clear visibility and recovery options
  • No permanent trap states exist in the system

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with enterprise/server/routes/email.py and enterprise/server/routes/auth.py around the OAuth flow, then inspect storage/user_settings.py and server/auth/token_manager.py. Clarify which proposed recovery approach is selected; done should prevent users from being permanently stuck and provide a self-service path for unverified email accounts.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
authentication
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.