# SIWW MetaMask login fails with "Invalid request origin" on devnet localhost despite allowlisted domain

**URL:** <https://builder.metamask.io/t/siww-metamask-login-fails-with-invalid-request-origin-on-devnet-localhost-despite-allowlisted-domain/3029>\
**Category:** Embedded Wallets (Web3Auth)\
**Tags:** web3auth\
**Created:** [March 28, 2026, 7:03am UTC](https://builder.metamask.io/t/siww-metamask-login-fails-with-invalid-request-origin-on-devnet-localhost-despite-allowlisted-domain/3029 "2026-03-28T07:03:09Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![angeloaad](https://yyz1.discourse-cdn.com/flex011/user_avatar/builder.metamask.io/angeloaad/32/2904_2.png) [@angeloaad](https://builder.metamask.io/u/angeloaad)\
**Post date:** [March 28, 2026, 7:03am UTC](https://builder.metamask.io/t/siww-metamask-login-fails-with-invalid-request-origin-on-devnet-localhost-despite-allowlisted-domain/3029/1 "2026-03-28T07:03:10Z")

</div>

**Describe your issue or question:**

We are experiencing a sudden authentication failure on our development environment. Our MetaMask wallet login flow (SIWW - Sign In With Wallet) was working reliably for 4 months, but starting today (March 26, 2026), all authentication attempts are failing with a 401 “Invalid request origin” error from `authjs.web3auth.io/siww/verify`. Critically: **no code changes were made** and **production still works fine**.

**What are you trying to build or integrate?**

We’re building a Web3-authenticated SaaS dashboard. Users authenticate by connecting their MetaMask wallet via Web3Auth Modal, which signs a message and returns a JWT for our backend. This flow is working perfectly in production.

**What problem or error are you facing?**

- **Environment:** Devnet, localhost:5173
- **Error:** `401 Unauthorized` from `authjs.web3auth.io/siww/verify`
- **Response:** `{"error":"Invalid request origin","success":false}`
- **Status:** `http://localhost:5173` is already in the Web3Auth dashboard’s “Allowlist for Devnet Environment”
- **Production Status:** Identical code and same devnet client\_id work fine in production (`https://` domain)
- **Regression:** This worked every day for 4 months until the past few days

**Tech stack:**

- Frontend: React 19.1.1 with TypeScript
- Web3Auth SDK: `@web3auth/modal` v10.15.0
- Wallet: MetaMask
- Network: Sapphire Devnet
- Build tool: Vite

**Code snippets:**

Web3Auth initialization (unchanged):

```auto
export const web3AuthOptions: Web3AuthContextConfig['web3AuthOptions'] = {
  clientId: import.meta.env.VITE_WEB3AUTH_DEVNET_CLIENT_ID,
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,
  uiConfig: {
    widgetType: 'modal',
  },
};

```

Login handler (unchanged):

```auto
const { connect } = useWeb3AuthConnect();
await connect(); // This is where the SIWW call fails

```

**Exact error and logs:**

Request to `https://authjs.web3auth.io/siww/verify`:

```auto
POST /siww/verify HTTP/1.1
Host: authjs.web3auth.io
Origin: http://localhost:5173
Client_id: BMOk8NhyqVmonRctwP2B11x4i6spqAu75HsXa9QQK2A5bwQyPQ9mDpthOoiLAMqdi7I1BjrZuuwr2akUf3z7tq0
Web3auth_network: sapphire_devnet
Wallet_provider: metamask

Response: 401 Unauthorized
{"error":"Invalid request origin","success":false}

```

**Package details:**

- `@web3auth/modal ^10.14.1 (installed 10.15.0)
- `@web3auth/auth`: v10.8.0 (dependency)
- Project: Kryptac (sapphire\_devnet)

**Additional context:**

1. We verified the allowlist configuration multiple times and even removed/re-added `http://localhost:5173`
2. The production deployment uses the same client\_id and same code but with an `http://` domain — it works without issues
3. This suggests the devnet SIWW service may have either:

- Enforced HTTPS-only origins (which would break HTTP localhost)
- Had a configuration change or incident in the past couple of days
- Changed how it validates the `Origin` header

Could you advise if there was a recent change to the SIWW endpoint or devnet infrastructure today?

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex011/uploads/metamaskbuilderhub/original/2X/9/92b599d3131e78cf3d3ff01b80e54d69d266f8df.png) [@system](https://builder.metamask.io/u/system)\
**Post date:** [March 28, 2026, 7:04am UTC](https://builder.metamask.io/t/siww-metamask-login-fails-with-invalid-request-origin-on-devnet-localhost-despite-allowlisted-domain/3029/2 "2026-03-28T07:04:46Z")

</div>

This is an error report (SIWW auth failure). Thanks — you provided good detail (SDK: MetaMask Embedded/Web3Auth, @web3auth/modal v10.15.0, React/Vite, devnet localhost:5173, request/response). Quick summary of what I checked and next steps:

Findings

- Docs/KB: Sapphire Devnet should allow localhost origins; Sapphire Mainnet does not. I didn’t find any KB entry or known incident saying [authjs.web3auth.io](http://authjs.web3auth.io) changed origin rules recently.

Immediate checks (do these in order)

1. Confirm the clientId is tied to a Sapphire Devnet project in the Web3Auth dashboard (clientId vs environment mismatch is a common cause). Ensure web3AuthNetwork === “sapphire\_devnet” in runtime.
2. Exact allowlist match: make sure the dashboard entry exactly matches the Origin header (no trailing slash). Add these variants too: [http://localhost:5173](http://localhost:5173) and [http://127.0.0.1:5173](http://127.0.0.1:5173).
3. Recreate the allowlist entry (delete then add) or create a fresh devnet project/client\_id and allowlist the origin to rule out a dashboard config corruption.
4. Verify the env var at runtime (VITE\_WEB3AUTH\_DEVNET\_CLIENT\_ID) — confirm the built app is actually using the expected dev clientId (build-time env mismatch can happen with Vite).
5. Test with a direct request to verify endpoint to isolate browser vs server: curl -v -X POST [https://authjs.web3auth.io/siww/verify](https://authjs.web3auth.io/siww/verify) -H “Origin: [http://localhost:5173](http://localhost:5173)” -d ‘{}’
6. Check anything that might rewrite Origin (reverse proxy, dev tooling, or browser extension). Try an incognito profile with no extensions.
7. Quick workaround: try serving your dev site over HTTPS (localhost with a local cert / mkcert) or use 127.0.0.1 to see if behaviour changes.

If those don’t fix it

- If a new client\_id + allowlist works, the original client config may have been changed/rotated on the server side — please create a new devnet client and test.
- If a new client\_id also fails, please tell me if you want me to escalate to the MetaMask Embedded/Web3Auth team. For escalation I’ll need your devnet client\_id, the first failing timestamp (UTC), and one full failing request/response (you already included a good example).

What I can confirm from KB: devnet should allow localhost; no KB evidence of a recent origin-policy change. If you want, I can open an internal ticket for you — say the word and share the client\_id + timestamp and I’ll escalate to the team for immediate investigation.

> Note: This response was generated by an AI bot and may require further verification. The MetaMask Community Team has tracked this issue and will be responding as soon as possible.

> Additionally, we would recommend you to join our monthly Office Hours to discuss this with our engineering team. [MetaMask Developer Office Hours](https://builder.metamask.io/t/metamask-developer-office-hours/2544/1)

---

<div class="post-metadata">

**Author:** ![angeloaad](https://yyz1.discourse-cdn.com/flex011/user_avatar/builder.metamask.io/angeloaad/32/2904_2.png) [@angeloaad](https://builder.metamask.io/u/angeloaad)\
**Post date:** [March 28, 2026, 3:00pm UTC](https://builder.metamask.io/t/siww-metamask-login-fails-with-invalid-request-origin-on-devnet-localhost-despite-allowlisted-domain/3029/3 "2026-03-28T15:00:48Z")

</div>

We’ve isolated the root cause of the 401 “Invalid request origin” error on devnet. The `@web3auth/modal` SDK constructs the SIWW payload with `"audience"` set to `window.location.hostname` (e.g., `"localhost"`), but the `authjs.web3auth.io/siww/verify` endpoint validates this field against the full allowlisted origin URL (e.g., `http://localhost:5173`). When the origin uses a non-standard port, the hostname alone doesn’t match the allowlist entry, and the server rejects the request.

This is **not a configuration issue**. Our allowlist is correct, CORS passes, and the same client\_id works on our production deployment (`http://34.1.44.49`, default port 80). The bug specifically affects origins with non-standard ports (e.g., `:5173`) because the SDK strips the protocol and port from the audience.

* * *

**Proof (reproducible via curl)**

Using our devnet client\_id `BMOk8NhyqVmonRctwP2B11x4i6spqAu75HsXa9QQK2A5bwQyPQ9mDpthOoiLAMqdi7I1BjrZuuwr2akUf3z7tq0`:

**Test 1 — What the SDK sends (bare hostname) → 401 FAILS:**

```auto
curl -s -X POST "https://authjs.web3auth.io/siww/verify" \
  -H "Content-Type: application/json; charset=utf-8" \
  -H "Origin: http://localhost:5173" \
  -H "client_id: BMOk8NhyqVmonRctwP2B11x4i6spqAu75HsXa9QQK2A5bwQyPQ9mDpthOoiLAMqdi7I1BjrZuuwr2akUf3z7tq0" \
  -H "wallet_provider: metamask" \
  -H "web3auth_network: sapphire_devnet" \
  --data-raw '{"signature":{"s":"0xfake","t":"eip191"},"message":"test","issuer":"metamask","audience":"localhost","timeout":604800}'

```

Response: `401 — {"error":"Invalid request origin","success":false}`

**Test 2 — Full origin with port → origin check PASSES:**

```auto
curl -s -X POST "https://authjs.web3auth.io/siww/verify" \
  -H "Content-Type: application/json; charset=utf-8" \
  -H "Origin: http://localhost:5173" \
  -H "client_id: BMOk8NhyqVmonRctwP2B11x4i6spqAu75HsXa9QQK2A5bwQyPQ9mDpthOoiLAMqdi7I1BjrZuuwr2akUf3z7tq0" \
  -H "wallet_provider: metamask" \
  -H "web3auth_network: sapphire_devnet" \
  --data-raw '{"signature":{"s":"0xfake","t":"eip191"},"message":"test","issuer":"metamask","audience":"http://localhost:5173","timeout":604800}'

```

Response: `500 — {"error":"Message did not match the regular expression.","success":false}` (500 is expected — fake signature. The important thing is it’s **not a 401** , meaning the origin check passed.)

**The only difference** between these two requests is the `audience` value in the JSON body. This proves the server validates `audience` against the allowlist.

* * *

**Why production works but localhost doesn’t**

Our production deployment at `http://34.1.44.49` (default port 80) works because:

- SDK sends `"audience": "34.1.44.49"` (hostname)
- Allowlist has `http://34.1.44.49`
- No port mismatch — port 80 is implicit in both

Our dev environment at `http://localhost:5173` (non-standard port) fails because:

- SDK sends `"audience": "localhost"` (hostname only, port stripped)
- Allowlist has `http://localhost:5173`
- `"localhost"` ≠ `"localhost:5173"` — the non-standard port is lost

The SDK appears to use `window.location.hostname` instead of `window.location.origin` (or at minimum `window.location.host` which includes the port) when constructing the `audience` field.

* * *

**What the SDK sends (captured from browser DevTools → Copy as cURL):**

```auto
{
  "signature": { "s": "0x8d0e0c...", "t": "eip191" },
  "message": "http://localhost:5173 wants you to sign in with your Ethereum account:\n0xeb0eb3bcf131ac2ea1afabfffbcee9056a4886cb\n\n\nURI: http://localhost:5173/\nVersion: 1\nChain ID: 11155111\nNonce: b3eaf74a...\nIssued At: 2026-03-28T14:06:46.927Z",
  "issuer": "metamask",
  "audience": "localhost",
  "timeout": 604800
}

```

Note: the `message` field correctly uses the full origin (`http://localhost:5173`), but the `audience` field only has the bare hostname (`localhost`). These are inconsistent.

* * *

**Environment:**

- SDK: `@web3auth/modal` ^10.14.1 (installed: 10.15.0)
- `@web3auth/auth`: 10.8.0 (dependency of modal)
- Network: Sapphire Devnet
- Client ID: `BMOk8NhyqVmonRctwP2B11x4i6spqAu75HsXa9QQK2A5bwQyPQ9mDpthOoiLAMqdi7I1BjrZuuwr2akUf3z7tq0`
- Wallet: MetaMask (browser extension)
- Frontend: React 19.1.1, Vite (dev server on port 5173), TypeScript
- OS: Windows 11, Chrome 146
- Production URL: `http://34.1.44.49` (works)
- Dev URL: `http://localhost:5173` (fails)

**Timeline:**

- Working: ~4 months (Nov 2025 – Mar 25, 2026)
- Broken: Starting March 26, 2026
- No code changes to the authentication flow

**Allowlisted origins (all present in dashboard):**

- `http://localhost:5173`
- `http://127.0.0.1:5173`
- `http://192.168.0.104:5173`
- `localhost:5173`
- `http://localhost`

**Request:** Could you confirm whether there was a server-side change to how `authjs.web3auth.io/siww/verify` validates the `audience` field, or an SDK change in how `audience` is constructed? The fix would be either:

1. SDK sends `window.location.host` or `window.location.origin` instead of `window.location.hostname`
2. Server-side matching accounts for non-standard ports when comparing audience to the allowlist

---

<div class="post-metadata">

**Author:** ![yashovardhan](https://yyz1.discourse-cdn.com/flex011/user_avatar/builder.metamask.io/yashovardhan/32/1526_2.png) [@yashovardhan](https://builder.metamask.io/u/yashovardhan)\
**Post date:** [March 29, 2026, 12:56pm UTC](https://builder.metamask.io/t/siww-metamask-login-fails-with-invalid-request-origin-on-devnet-localhost-despite-allowlisted-domain/3029/4 "2026-03-29T12:56:37Z")

</div>

Hey @angeloaad

Thanks for raising this. I’m unable to reproduce the issue, however I’ll ask the engineering team once to take a look as well.

---

<div class="post-metadata">

**Author:** ![angeloaad](https://yyz1.discourse-cdn.com/flex011/user_avatar/builder.metamask.io/angeloaad/32/2904_2.png) [@angeloaad](https://builder.metamask.io/u/angeloaad)\
**Post date:** [March 30, 2026, 3:54am UTC](https://builder.metamask.io/t/siww-metamask-login-fails-with-invalid-request-origin-on-devnet-localhost-despite-allowlisted-domain/3029/5 "2026-03-30T03:54:29Z")

</div>

Thank you Yashovardhan it means a lot!, I am waiting for a response from the team!

---

<div class="post-metadata">

**Author:** ![angeloaad](https://yyz1.discourse-cdn.com/flex011/user_avatar/builder.metamask.io/angeloaad/32/2904_2.png) [@angeloaad](https://builder.metamask.io/u/angeloaad)\
**Post date:** [March 31, 2026, 4:15pm UTC](https://builder.metamask.io/t/siww-metamask-login-fails-with-invalid-request-origin-on-devnet-localhost-despite-allowlisted-domain/3029/6 "2026-03-31T16:15:32Z")

</div>

Hello @yashovardhan how are you?

Any updates on the issue?

---

<div class="post-metadata">

**Author:** ![angeloaad](https://yyz1.discourse-cdn.com/flex011/user_avatar/builder.metamask.io/angeloaad/32/2904_2.png) [@angeloaad](https://builder.metamask.io/u/angeloaad)\
**Post date:** [April 4, 2026, 7:43pm UTC](https://builder.metamask.io/t/siww-metamask-login-fails-with-invalid-request-origin-on-devnet-localhost-despite-allowlisted-domain/3029/7 "2026-04-04T19:43:51Z")

</div>

Hi team,

Following up on this issue — the login flow is now working again as of today (April 4,  
2026) on both [http://localhost](http://localhost) and [http://localhost:5173](http://localhost:5173), without any changes on our end.

To summarize the timeline:

- Working: ~4 months continuously (Nov 2025 – Mar 25, 2026)
- Broken: March 26 – April 3, 2026 (9 days)
- Working again: April 4, 2026 — no code or config changes on our side

Since we made zero changes to resolve this, something changed on your infrastructure  
between March 26 and April 4. We’d like to understand what happened for a few reasons:

1. It could break again. If we don’t know the root cause, we have no way to anticipate or  
protect against a recurrence.
2. We lost 9 days of development time debugging an issue that was outside our control.
3. The root cause we identified still stands — the SDK sends audience: “localhost” (bare  
hostname) in the SIWW payload. If your server started accepting this again, we’d like to  
know if that was intentional or a side effect of something else.

Specific questions:

- Was there an incident or maintenance on the [authjs.web3auth.io/siww/verify](http://authjs.web3auth.io/siww/verify) endpoint  
between March 26–April 4?
- Was a fix or rollback deployed? If so, what was changed?
- Is there a status page or incident log we should be monitoring so we’re not blindsided if  
this happens again?
- Is the devnet SIWW service considered stable for ongoing development, or should we expect  
periodic disruptions?

We’d appreciate a clear answer so we can make an informed decision about whether to  
continue relying on devnet or migrate to mainnet.
