# Ethereum wallet authentication

Openfort Auth supports [Sign-In With Ethereum (SIWE)](https://eips.ethereum.org/EIPS/eip-4361) for EVM-compatible wallets including MetaMask, Rainbow, Coinbase Wallet, and WalletConnect-compatible wallets.

:::info\[EVM chains only]
SIWE authentication supports EVM-compatible chains (Ethereum, Polygon, Arbitrum, Base, and others). Other wallet authentication standards like SIWS (Sign-In With Solana) aren't currently supported.
:::

## Overview

SIWE enables passwordless authentication where users prove ownership of their Ethereum address by signing a message. Use SIWE to:

* Authenticate crypto-native users who have existing wallets
* Link external wallets to Openfort accounts
* Provide an alternative to email or social login

## Configuration

### Enable SIWE authentication

1. Go to the [Openfort dashboard](https://dashboard.openfort.io/providers).
2. Under **Authentication providers**, locate **external wallet**.
3. Enable the provider.

:::note
SIWE authentication is enabled by default for new projects.
:::

:::info
For production applications, [configure allowed domains](/docs/configuration/allowed-domains) to prevent unauthorized use of your API key.
:::

## How it works

SIWE authentication consists of two steps:

1. **Request a nonce** — Your application requests a unique, single-use nonce from Openfort
2. **Verify the signature** — The user signs a SIWE message with their wallet, and your application submits the signature for verification

Openfort verifies the signature, validates the nonce, and creates a session.

## Validation

All SIWE requests go through three validation checks:

| Check | Requirement | Error |
|-------|-------------|-------|
| API key | Valid `x-project-key` header | `401 UNAUTHORIZED` |
| Origin | Request origin matches allowed origins (production) | `401 UNAUTHORIZED` |
| Provider | **Web3 wallet** enabled | `400 PROVIDER_DISABLED` |

Nonces are single-use and expire after 5 minutes.

### SIWE message requirements

The SIWE message must include the exact canonical statement:

```
By signing, you are proving you own this wallet and logging in. This does not initiate a transaction or cost any fees.
```

The API also validates:

* URI matches the domain in the message
* Domain matches your project's allowed origins (production)
* Chain ID is supported

## Link wallets to existing accounts

Users can link external wallets to existing Openfort accounts. This allows users who signed up with email or social login to also authenticate with their wallet.

See [useWalletAuth](/docs/products/embedded-wallet/react/hooks/useWalletAuth) for implementation details.

## Next steps

* [useConnectWithSiwe](/docs/products/embedded-wallet/react/hooks/useConnectWithSiwe) — React hook for SIWE authentication
* [Configure allowed domains](/docs/configuration/allowed-domains) — Set up origin restrictions for production

## Troubleshooting

### Invalid API key

Verify the `x-project-key` header is present and correct. Use `pk_live_*` keys for production and `pk_test_*` for development.

### Provider disabled

Navigate to **Configuration** > **Providers** in the dashboard and enable **Web3 wallet**.

### Origin rejected

Add your domain to **Allowed Origins** in the dashboard. Note that `https://example.com` and `https://www.example.com` are treated as separate origins. For local development, specify the port: `http://localhost:3000`.

### Nonce expired

Request a fresh nonce before each sign-in attempt. Don't cache or reuse nonces.
