Skip to main content

Authentication

amser uses three distinct authentication mechanisms depending on context: SIWE for the dashboard, API keys for server-side requests, and a combination of wallet auth plus the amser API for gating access in your own application.

Part 1 — Dashboard authentication (SIWE)​

SIWE (Sign-In With Ethereum) replaces traditional username-and-password authentication with a wallet signature. Instead of transmitting a secret, the user signs a structured message with their wallet, proving ownership of an Ethereum address without exposing the private key. This is the only authentication method for the amser dashboard.

How the flow works​

  1. Connect wallet — the user connects via MetaMask, WalletConnect, Coinbase Wallet, or any injected provider.
  2. Request nonce — amser calls GET /v0/auth/nonce to obtain a one-time challenge.
  3. Construct message — amser builds a SIWE message (ERC-4361) using that nonce.
  4. Sign — the user signs the message in their wallet. No transaction is submitted and no gas is spent.
  5. Verify — amser sends the signature to POST /v0/auth/verify, which validates it and sets an HttpOnly session cookie (sid).
  6. Session established — the session is bound to the wallet address. Switching wallets requires re-authentication.

SIWE message format​

The message the user sees in their wallet follows the ERC-4361 structure:

amser wants you to sign in with your Ethereum account:
0xYourAddressHere

Sign in to amser

URI: https://app.amser.io
Version: 1
Chain ID: 8453
Nonce: <random>
Issued At: 2026-01-01T00:00:00.000Z

Session properties​

  • Expires after 15 minutes of inactivity (automatically refreshed on activity)
  • Invalidated on explicit logout (POST /v0/auth/logout)
  • Scoped to the authenticated wallet address — the dashboard only shows data for that merchant

Part 2 — API authentication (API keys)​

The dashboard uses SIWE because it runs in a browser where the user can sign messages interactively. Server-side integrations cannot prompt a wallet, so they use API keys instead.

API keys are read-only — they work for GET requests only. Write operations (creating webhooks, revoking keys) require a SIWE session through the dashboard.

To authenticate a server-side request, include the key in the Authorization header:

Authorization: Bearer amsr_live_xxxxxxxxxxxxx

Generate and manage API keys from the dashboard under Settings → API Keys. See the API Keys page for the full reference.

Part 3 — On-chain gating (SIWE + subscription check)​

If you are building a subscription-gated application, the recommended pattern combines wallet-based authentication with the amser API to check subscription status at login time.

The pattern​

  1. The user authenticates to your app using any wallet-based auth mechanism (SIWE, RainbowKit, ConnectKit, etc.).
  2. Your server calls GET /v0/auth/check with the user's wallet address and plan ID.
  3. If authorized: true, you issue a session that includes subscription claims.
  4. Subsequent requests are authorized via your own session — you do not re-check the amser API on every request.
async function loginUser(walletAddress: string): Promise<Session> {
// 1. Verify the user's wallet signature (your existing auth layer)

// 2. Check subscription status via amser API — no on-chain call needed
const params = new URLSearchParams({
module_address: MODULE_ADDRESS,
wallet: walletAddress,
plan_ids: PLAN_ID,
});

const res = await fetch(
`https://api.amser.io/v0/auth/check?${params}`,
{ headers: { 'Authorization': `Bearer ${process.env.AMSER_API_KEY}` } }
);

const { authorized } = await res.json();

// 3. Issue session with subscription claim
return createSession({
address: walletAddress,
subscribed: authorized,
// Keep session shorter than your grace period so lapsed subscriptions
// can't maintain access indefinitely via a stale session
expiresAt: Date.now() + 60 * 60 * 1000, // 1 hour
});
}

Session expiry considerations​

If a subscription lapses mid-session, the user retains access until their session expires. Set the session duration to match your acceptable lag — shorter sessions are more accurate but require more frequent re-checks. As a rule of thumb, keep session lifetime well below your plan's grace period so that a lapsed subscriber cannot ride a stale session through the entire grace window.

Next steps​