An OpenID Connect identity provider that authenticates users with their Ethereum wallets via Sign in with Ethereum (EIP-4361).
Any application that supports OIDC can use this provider to let users log in with their Ethereum address — no passwords, no email, no custodial accounts.
┌────────┐ ┌─────────────┐ ┌───────────────┐
│ App │────▶│ SIWE OIDC │────▶│ User's Wallet │
│(Client)│◀────│ Provider │◀────│ (MetaMask…) │
└────────┘ └─────────────┘ └───────────────┘
OIDC code interaction SIWE signature
flow + consent
- Your app starts a standard OIDC authorization code flow
- The provider presents a wallet-connect login page
- The user signs a SIWE message — this replaces both password entry and consent
- The provider verifies the signature and issues OIDC tokens
- Your app receives an ID token with the user's Ethereum identity
The user's SIWE signature is their consent — no additional consent screen needed.
- Full OIDC authorization code flow with PKCE
- Dynamic client registration (
/reg) - Pre-configured default clients via environment variable
- ENS name and avatar resolution (returned as
preferred_usernameandpictureclaims) - Smart wallet support: EOA, EIP-1271 (contract wallets), EIP-6492 (counterfactual)
- Token introspection and revocation
- RP-Initiated Logout
- Redis-backed session storage
- Auto-generated RSA signing keys (shared safely across workers)
- Docker and Docker Compose deployment
- Node.js 22+
- Redis
- pnpm
# Install dependencies
pnpm install
# Copy and configure environment
cp .env.example .env
# Start development server
pnpm devThe provider starts at http://localhost:3000. Visit http://localhost:3000/.well-known/openid-configuration to see the OIDC discovery document.
docker compose upThis starts both the provider and a Redis instance.
All configuration is via environment variables (see .env.example):
| Variable | Description | Default |
|---|---|---|
NUXT_OIDC_BASE_URL |
Issuer URL | http://localhost:3000 |
NUXT_OIDC_REDIS_URL |
Redis connection URL | redis://localhost:6379 |
NUXT_OIDC_COOKIE_KEYS |
Cookie signing keys (comma-separated) | required |
NUXT_OIDC_RSA_PEM |
RSA private key in PEM format | auto-generated |
NUXT_OIDC_REQUIRE_SECRET |
Require client secret for token exchange | true |
NUXT_OIDC_ETH_PROVIDER |
Ethereum RPC URL for ENS resolution | public default |
NUXT_OIDC_DEFAULT_CLIENTS |
Pre-configured clients (JSON) | {} |
NUXT_PUBLIC_EVM_WALLET_CONNECT_PROJECT_ID |
WalletConnect project ID | — |
NUXT_PUBLIC_EVM_CHAINS_MAINNET_RPCS |
Ethereum mainnet RPC URLs | — |
Pre-register clients so they don't need to call /reg:
# Simple: client_id → redirect_uri
NUXT_OIDC_DEFAULT_CLIENTS='{"my-app": "https://myapp.com/callback"}'
# Rich: with display metadata shown on the login page
NUXT_OIDC_DEFAULT_CLIENTS='{
"my-app": {
"redirect_uri": "https://myapp.com/callback",
"client_name": "My App",
"logo_uri": "https://myapp.com/logo.png",
"client_uri": "https://myapp.com",
"policy_uri": "https://myapp.com/privacy",
"tos_uri": "https://myapp.com/terms"
}
}'| Endpoint | Description |
|---|---|
GET /.well-known/openid-configuration |
Discovery document |
POST /auth |
Authorization |
POST /token |
Token exchange |
GET /jwks |
JSON Web Key Set |
GET /me |
UserInfo |
POST /reg |
Dynamic client registration |
POST /token/introspection |
Token introspection |
POST /token/revocation |
Token revocation |
POST /session/end |
RP-Initiated Logout |
| Claim | Source | Scope |
|---|---|---|
sub |
eip155:{chainId}:{address} |
openid |
preferred_username |
ENS name or Ethereum address | profile |
picture |
ENS avatar | profile |
pnpm dev # Start dev server
pnpm test # Run tests
pnpm typecheck # Type check
pnpm format # Format with Prettier
pnpm build # Production build- oidc-provider — certified OIDC implementation
- siwe — Sign in with Ethereum
- viem — Ethereum client
- ioredis — Redis client
- jose — JWT/JWK operations
- Nuxt 4 — full-stack framework
MIT — Copyright EthID.org