Skip to content

[PM-40152] feat: Require verified email to accept organization invite link#7949

Merged
r-tome merged 1 commit into
mainfrom
ac/pm-40152-invite-link-require-email-verification
Jul 14, 2026
Merged

[PM-40152] feat: Require verified email to accept organization invite link#7949
r-tome merged 1 commit into
mainfrom
ac/pm-40152-invite-link-require-email-verification

Conversation

@r-tome

@r-tome r-tome commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

🎟️ Tracking

Resolves PM-40152

📔 Objective

The invite-link accept flow (AcceptOrganizationInviteLinkCommand) gated organization membership on the accepting user's email domain being in the link's AllowedDomains, but never asserted the email was verified. Unlike the email-invite flow — where the token delivered to the mailbox proves ownership — the invite link carries no per-email token, so the domain allowlist was the only binding between the user and an allowed domain. An account holding an unverified email at an allowed domain could therefore join the organization.

This PR adds a !user.EmailVerified guard in the read-only validation phase of the accept command, before any OrganizationUser is created or seat is consumed. Unverified users receive a new EmailNotVerified error (HTTP 400). New unit tests cover the rejection and confirm no membership/seat side effects occur.

SSO JIT-provisioned users are not affected: the JIT flow creates an org user in an invited state and accepts them via IAcceptOrgUserCommand (through the MP, TDE, or Key Connector paths), never through AcceptOrganizationInviteLinkCommand.

Surfaced by the AppSec review of the invite-link tech breakdown.

@r-tome r-tome added the ai-review Request a Claude code review label Jul 9, 2026
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

🤖 Bitwarden Claude Code Review

Overall Assessment: APPROVE

This PR adds a !user.EmailVerified guard to AcceptOrganizationInviteLinkCommand, closing a gap where an account holding an unverified email at an allowed domain could join an organization. The guard sits in the read-only validation phase, before any OrganizationUser is created or seat consumed, and returns a new EmailNotVerified (HTTP 400) error that follows the existing error-record pattern. A new unit test verifies the rejection and confirms no membership or seat side effects occur, and SetupHappyPath now sets EmailVerified = true so existing tests remain valid under the new guard.

Code Review Details

No findings. The guard is correctly ordered ahead of state mutation, User.EmailVerified is a non-nullable bool so the check is safe, and the SSO JIT-provisioning concern was investigated and ruled out (JIT users accept via IAcceptOrgUserCommand, not this command).

… link

The invite-link accept flow bound a user to an organization solely via the
email-domain allowlist, without asserting the email was verified. Unlike the
email-invite flow, the link carries no per-email token proving ownership of the
address, so the allowlist was the only binding. Assert EmailVerified in the
read-only validation phase, before any seat is consumed, so an account that
never proved ownership of an email at an allowed domain cannot join.
@r-tome r-tome force-pushed the ac/pm-40152-invite-link-require-email-verification branch from 51f50d3 to 2e4fd20 Compare July 9, 2026 15:59
@r-tome r-tome changed the title [PM-40152] fix: Require verified email to accept organization invite link [PM-40152] feat: Require verified email to accept organization invite link Jul 9, 2026
@r-tome r-tome added the t:feature Change Type - Feature Development label Jul 9, 2026
@r-tome

r-tome commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

@JaredSnider-Bitwarden tagging you here because this PR requires EmailVerified to be true before a user can accept an invite link. SSO-provisioned accounts don't seem to get EmailVerified = true, so I want to check whether a user coming through the SSO route could get blocked at accept. I'm keeping this as a draft until we align.

@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 61.45%. Comparing base (19c6afb) to head (2e4fd20).
⚠️ Report is 18 commits behind head on main.

Files with missing lines Patch % Lines
...Console/OrganizationFeatures/InviteLinks/Errors.cs 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7949      +/-   ##
==========================================
+ Coverage   61.43%   61.45%   +0.01%     
==========================================
  Files        2245     2245              
  Lines       98830    98859      +29     
  Branches     8941     8946       +5     
==========================================
+ Hits        60715    60749      +34     
+ Misses      35965    35960       -5     
  Partials     2150     2150              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@r-tome

r-tome commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

@JaredSnider-Bitwarden tagging you here because this PR requires EmailVerified to be true before a user can accept an invite link. SSO-provisioned accounts don't seem to get EmailVerified = true, so I want to check whether a user coming through the SSO route could get blocked at accept. I'm keeping this as a draft until we align.

Investigated by Auth. SSO JIT-provisioned users are not affected. The JIT flow creates the org user in an invited state and accepts them via IAcceptOrgUserCommand (through the MP, TDE, and Key Connector paths), not through AcceptOrganizationInviteLinkCommand. Marking ready for review.

@r-tome r-tome marked this pull request as ready for review July 13, 2026 16:26
@r-tome r-tome requested a review from a team as a code owner July 13, 2026 16:26
@r-tome r-tome requested a review from jrmccannon July 13, 2026 16:26
@r-tome r-tome merged commit d6cb0a1 into main Jul 14, 2026
52 of 55 checks passed
@r-tome r-tome deleted the ac/pm-40152-invite-link-require-email-verification branch July 14, 2026 10:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review Request a Claude code review t:feature Change Type - Feature Development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants