Skip to content

Strip URL scheme from login domain#8706

Closed
0xFirekeeper wants to merge 3 commits intomainfrom
firekeeper/siwe-fix
Closed

Strip URL scheme from login domain#8706
0xFirekeeper wants to merge 3 commits intomainfrom
firekeeper/siwe-fix

Conversation

@0xFirekeeper
Copy link
Member

@0xFirekeeper 0xFirekeeper commented Mar 16, 2026

Add stripUrlScheme utility and use it to normalize domains by removing http/https schemes. Apply this to createLoginMessage, generateLoginPayload, and verifyLoginPayload so payload.domain is stored and compared without a URL scheme (per EIP-4361). Update tests to cover scheme stripping and backward compatibility when verifying payloads.


PR-Codex overview

This PR focuses on ensuring compliance with EIP-4361 by stripping the URL scheme from domain fields in the authentication process, enhancing backward compatibility for legacy payloads.

Detailed summary

  • Added stripUrlScheme function to remove URL schemes and trailing paths from domain strings.
  • Updated generateLoginPayload to use stripUrlScheme for the domain field.
  • Modified verifyLoginPayload to normalize domains by stripping URL schemes.
  • Enhanced tests for stripUrlScheme to cover various scenarios.
  • Updated tests for generateLoginPayload and verifyLoginPayload to ensure correct behavior with both scheme-stripped and legacy payloads.

✨ Ask PR-Codex anything about this PR by commenting with /codex {your question}

Summary by CodeRabbit

  • Bug Fixes

    • Login payloads now strip URL schemes from domain fields for EIP-4361 compliance.
    • Domain verification normalizes domains by removing URL schemes before comparison.
    • Verification includes fallback handling for legacy payloads that include schemes.
  • Tests

    • Added unit tests covering URL scheme stripping and legacy-domain verification.
  • Chores

    • Added a changeset documenting a minor release.

Add stripUrlScheme utility and use it to normalize domains by removing http/https schemes. Apply this to createLoginMessage, generateLoginPayload, and verifyLoginPayload so payload.domain is stored and compared without a URL scheme (per EIP-4361). Update tests to cover scheme stripping and backward compatibility when verifying payloads. Also adjust biome.json formatter line ending to CRLF.
@0xFirekeeper 0xFirekeeper requested review from a team as code owners March 16, 2026 09:04
@vercel
Copy link

vercel bot commented Mar 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs-v2 Error Error Mar 16, 2026 10:21am
nebula Ready Ready Preview, Comment Mar 16, 2026 10:21am
thirdweb_playground Ready Ready Preview, Comment Mar 16, 2026 10:21am
thirdweb-www Ready Ready Preview, Comment Mar 16, 2026 10:21am
wallet-ui Ready Ready Preview, Comment Mar 16, 2026 10:21am

@changeset-bot
Copy link

changeset-bot bot commented Mar 16, 2026

🦋 Changeset detected

Latest commit: 74fde1d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
thirdweb Minor
@thirdweb-dev/nebula Patch
@thirdweb-dev/wagmi-adapter Patch
wagmi-inapp Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions bot added packages SDK Involves changes to the thirdweb SDK labels Mar 16, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 16, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 55414521-2f73-4d86-a849-f673ee742393

📥 Commits

Reviewing files that changed from the base of the PR and between 5535038 and 74fde1d.

📒 Files selected for processing (4)
  • packages/thirdweb/src/auth/core/generate-login-payload.test.ts
  • packages/thirdweb/src/auth/core/generate-login-payload.ts
  • packages/thirdweb/src/auth/core/strip-url-scheme.test.ts
  • packages/thirdweb/src/auth/core/strip-url-scheme.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/thirdweb/src/auth/core/generate-login-payload.test.ts
  • packages/thirdweb/src/auth/core/strip-url-scheme.test.ts
  • packages/thirdweb/src/auth/core/strip-url-scheme.ts
  • packages/thirdweb/src/auth/core/generate-login-payload.ts

Walkthrough

Adds a utility to strip http(s):// schemes and trailing paths from domain strings and integrates it into SIWE login payload generation and verification. Verification normalizes domains and retries legacy verification when needed; tests and a changeset were added.

Changes

Cohort / File(s) Summary
Changeset Documentation
/.changeset/hot-donkeys-itch.md
Adds release notes describing the domain URL-scheme stripping change for EIP-4361 compliance.
URL Scheme Stripping Utility
packages/thirdweb/src/auth/core/strip-url-scheme.ts, packages/thirdweb/src/auth/core/strip-url-scheme.test.ts
New stripUrlScheme(domain: string) implementation and unit tests covering http/https removal, trailing paths, ports, queries, fragments, and edge cases.
Login Payload Generation
packages/thirdweb/src/auth/core/generate-login-payload.ts, packages/thirdweb/src/auth/core/generate-login-payload.test.ts
Integrates stripUrlScheme when computing domain and when defaulting uri; updates tests to expect normalized domain and uri including scheme where appropriate.
Login Payload Verification
packages/thirdweb/src/auth/core/verify-login-payload.ts, packages/thirdweb/src/auth/core/verify-login-payload.test.ts
Normalizes payload and option domains by stripping schemes before building/verifying the signing message; adds fallback to verify legacy (non-normalized) message and tests for both normalized and legacy payloads.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Strip URL scheme from login domain' directly and accurately summarizes the main change: adding URL scheme stripping functionality to the authentication domain handling for EIP-4361 compliance.
Description check ✅ Passed The description covers the core changes well: the stripUrlScheme utility, its application across authentication functions, EIP-4361 compliance, backward compatibility, and test coverage, though it deviates from the template format.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch firekeeper/siwe-fix
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can disable the changed files summary in the walkthrough.

Disable the reviews.changed_files_summary setting to disable the changed files summary in the walkthrough.

Comment on lines +8 to +10
export function stripUrlScheme(domain: string): string {
return domain.replace(/^https?:\/\//, "");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regex pattern is case-sensitive and will fail to strip uppercase scheme variants like HTTP:// or HTTPS://. According to RFC 3986, URI schemes are case-insensitive. This will cause EIP-4361 non-compliance when users provide domains with uppercase schemes.

Impact: Domains like "HTTP://example.com" will not be stripped, violating EIP-4361 which requires the domain field to be an authority without scheme.

Fix: Make the regex case-insensitive:

export function stripUrlScheme(domain: string): string {
  return domain.replace(/^https?:\/\//i, "");
}
Suggested change
export function stripUrlScheme(domain: string): string {
return domain.replace(/^https?:\/\//, "");
}
export function stripUrlScheme(domain: string): string {
return domain.replace(/^https?:\/\//i, "");
}

Spotted by Graphite

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 16, 2026

size-limit report 📦

Path Size
@thirdweb-dev/nexus (esm) 105.66 KB (0%)
@thirdweb-dev/nexus (cjs) 319.47 KB (0%)

@codecov
Copy link

codecov bot commented Mar 16, 2026

Codecov Report

❌ Patch coverage is 96.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 52.73%. Comparing base (8e9c51e) to head (5535038).

Files with missing lines Patch % Lines
...ges/thirdweb/src/auth/core/verify-login-payload.ts 95.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8706      +/-   ##
==========================================
+ Coverage   52.72%   52.73%   +0.01%     
==========================================
  Files         934      935       +1     
  Lines       62968    62988      +20     
  Branches     4135     4137       +2     
==========================================
+ Hits        33199    33219      +20     
  Misses      29671    29671              
  Partials       98       98              
Flag Coverage Δ
packages 52.73% <96.00%> (+0.01%) ⬆️
Files with missing lines Coverage Δ
...s/thirdweb/src/auth/core/generate-login-payload.ts 100.00% <100.00%> (ø)
...ackages/thirdweb/src/auth/core/strip-url-scheme.ts 100.00% <100.00%> (ø)
...ges/thirdweb/src/auth/core/verify-login-payload.ts 55.88% <95.00%> (+5.88%) ⬆️
🚀 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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
packages/thirdweb/src/auth/core/create-login-message.ts (1)

3-10: Move stripUrlScheme into its own utility module.

generate-login-payload.ts and verify-login-payload.ts now depend on the message-builder file just to reuse a small normalization helper. Pulling this into a dedicated auth utility keeps the dependency direction cleaner and avoids stacking multiple stateless helpers in one file. As per coding guidelines, **/*.{ts,tsx}: Limit each file to one stateless, single-responsibility function for clarity and testability.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/thirdweb/src/auth/core/create-login-message.ts` around lines 3 - 10,
Extract the stripUrlScheme function into its own auth utility module that
exports the same function signature (export function stripUrlScheme(domain:
string): string) and remove it from the message-builder file; then update
callers (generate-login-payload and verify-login-payload) to import
stripUrlScheme from the new utility instead of from the message-builder, leaving
behavior unchanged, and update any tests or imports that referenced the old
location accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.changeset/hot-donkeys-itch.md:
- Line 5: The changelog entry in .changeset/hot-donkeys-itch.md contains a
typo/awkward phrasing ("Stripe URL scheme from SIWE domain across all
touchpoints"); update that line to a clear, grammatical release note (for
example: "Switch Stripe URL scheme to use the SIWE domain across all
touchpoints" or "Use the SIWE domain for Stripe URL scheme across all
touchpoints") so the published release notes read correctly.

In `@packages/thirdweb/src/auth/core/create-login-message.ts`:
- Around line 8-10: stripUrlScheme currently only trims the http(s) prefix which
leaves trailing slashes and path segments (e.g. "https://example.com/" ->
"example.com/") that are invalid as SIWE authorities; update stripUrlScheme to
parse the input with the URL API (new URL(domain) or fallback) and return the
normalized authority (hostname plus optional port) with no trailing slash or
path, lowercased, and validate/throw if parsing fails so functions like
createLoginMessage and SIWE payload generation use a proper authority value.

In `@packages/thirdweb/src/auth/core/verify-login-payload.test.ts`:
- Around line 149-189: The test currently signs a payload generated by
generateLoginPayload (which already normalizes domain), so it doesn't cover
legacy signatures containing schemes; modify the test to build or obtain a
payload whose domain still includes the URL scheme (e.g., "https://example.com")
before signing — for example, call generateLoginPayload or clone its result and
then set payload.domain = "https://example.com" (or construct the payload object
manually) and pass that to signLoginPayload, then call
verifyLoginPayload(options) and assert verificationResult.valid is true and
verificationResult.payload.domain is normalized to "example.com"; reference
generateLoginPayload, signLoginPayload, verifyLoginPayload, and payload.domain
to locate and change the test.

In `@packages/thirdweb/src/auth/core/verify-login-payload.ts`:
- Around line 51-52: The domain normalization fixes the equality check but
verification still rebuilds the signed message with the normalized domain via
createLoginMessage(payload), so signatures created against the legacy
scheme-bearing first line will fail; update the verification logic in
verify-login-payload.ts (the function that calls createLoginMessage and performs
signature verification) to attempt verification against both message shapes: the
normalized message (using stripUrlScheme(payload.domain) as currently done) and
the legacy/raw-domain message (using the original payload.domain including
scheme), trying each in turn before rejecting; use createLoginMessage with both
domain variants and run the existing signature check for both to preserve
backward compatibility.

---

Nitpick comments:
In `@packages/thirdweb/src/auth/core/create-login-message.ts`:
- Around line 3-10: Extract the stripUrlScheme function into its own auth
utility module that exports the same function signature (export function
stripUrlScheme(domain: string): string) and remove it from the message-builder
file; then update callers (generate-login-payload and verify-login-payload) to
import stripUrlScheme from the new utility instead of from the message-builder,
leaving behavior unchanged, and update any tests or imports that referenced the
old location accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f26a9879-e385-453a-889a-3b98f3c80568

📥 Commits

Reviewing files that changed from the base of the PR and between 8e9c51e and 5f9a57e.

📒 Files selected for processing (7)
  • .changeset/hot-donkeys-itch.md
  • packages/thirdweb/src/auth/core/create-login-message.test.ts
  • packages/thirdweb/src/auth/core/create-login-message.ts
  • packages/thirdweb/src/auth/core/generate-login-payload.test.ts
  • packages/thirdweb/src/auth/core/generate-login-payload.ts
  • packages/thirdweb/src/auth/core/verify-login-payload.test.ts
  • packages/thirdweb/src/auth/core/verify-login-payload.ts

Move stripUrlScheme into its own module and add comprehensive tests. createLoginMessage no longer strips the scheme (uses payload.domain as-is), generate-login-payload imports the new util, and verify-login-payload now normalizes the domain before building the expected message for EIP-4361 compliance. verify logic also falls back to the legacy (scheme-included) message for backward compatibility with signatures from older SDKs. Updated/added tests to cover stripUrlScheme behavior and legacy payload verification.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/thirdweb/src/auth/core/strip-url-scheme.ts (1)

6-7: Consider edge cases with query strings and fragments.

The second regex /\/.*$/ only strips content starting from /. URLs with query strings (?key=val) or fragments (#section) but no path would not be fully normalized.

For typical SIWE domains this is unlikely to matter, but if you want full RFC 3986 authority extraction, you could extend the second replacement:

🔧 Optional refinement
 export function stripUrlScheme(domain: string): string {
-  return domain.replace(/^https?:\/\//, "").replace(/\/.*$/, "");
+  return domain.replace(/^https?:\/\//, "").replace(/[/?#].*$/, "");
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/thirdweb/src/auth/core/strip-url-scheme.ts` around lines 6 - 7,
stripUrlScheme currently removes only the path via replace(/\/.*$/, "") which
misses query strings or fragments when there is no path; update the
implementation in the stripUrlScheme function to strip everything after the
authority by matching any of "/", "?" or "#" (e.g. replace(/[\/?#].*$/, "") or
equivalently split on the first occurrence of "/", "?" or "#" and take the first
segment) so domains like "example.com?x=1" and "example.com#frag" are normalized
correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/thirdweb/src/auth/core/strip-url-scheme.ts`:
- Around line 6-7: stripUrlScheme currently removes only the path via
replace(/\/.*$/, "") which misses query strings or fragments when there is no
path; update the implementation in the stripUrlScheme function to strip
everything after the authority by matching any of "/", "?" or "#" (e.g.
replace(/[\/?#].*$/, "") or equivalently split on the first occurrence of "/",
"?" or "#" and take the first segment) so domains like "example.com?x=1" and
"example.com#frag" are normalized correctly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4ec61d45-a2f8-43bc-87a2-2bb660cc3017

📥 Commits

Reviewing files that changed from the base of the PR and between 5f9a57e and 5535038.

📒 Files selected for processing (6)
  • .changeset/hot-donkeys-itch.md
  • packages/thirdweb/src/auth/core/generate-login-payload.ts
  • packages/thirdweb/src/auth/core/strip-url-scheme.test.ts
  • packages/thirdweb/src/auth/core/strip-url-scheme.ts
  • packages/thirdweb/src/auth/core/verify-login-payload.test.ts
  • packages/thirdweb/src/auth/core/verify-login-payload.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • .changeset/hot-donkeys-itch.md
  • packages/thirdweb/src/auth/core/generate-login-payload.ts
  • packages/thirdweb/src/auth/core/verify-login-payload.test.ts

GenerateLoginPayload now defaults uri to a fully-qualified https://<domain> by using stripUrlScheme and prepending https://, ensuring the login payload contains a valid URL. stripUrlScheme was updated to remove query strings and fragments (in addition to scheme and trailing slashes). Tests were updated to expect the https URI and to cover query/fragment cases.
@0xFirekeeper 0xFirekeeper deleted the firekeeper/siwe-fix branch March 16, 2026 10:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

packages SDK Involves changes to the thirdweb SDK

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant