Developer Docs

Integrate HyperPass

Add one-click wallet sign-in to your website in minutes. Users authenticate with their HyperPass extension — no passwords, no OAuth redirects.

How It Works

1
Detect Extension

Your page listens for the HyperPass provider via EIP-6963.

2
SIWE Authentication

The user signs a message with their wallet. HyperPass verifies the signature and returns a session token.

3
Validate Token

Your backend sends the token to HyperPass to get the user's identity. Create a local session.

Step 1 — Add the Client Script

Include hyperpass-auth.js on your login page. This script detects the extension, handles the SIWE flow, and sends the resulting token to your backend.

hyperpass-auth.js
(function() {
  'use strict';

  const HYPERPASS_URL = 'https://passport.hypercluster.org';

  // Detect HyperPass extension via EIP-6963
  function detectExtension() {
    return new Promise((resolve) => {
      let found = false;
      const handler = (event) => {
        if (event.detail?.info?.rdns === 'org.hypercluster.hyperpass') {
          found = true;
          window.removeEventListener('eip6963:announceProvider', handler);
          resolve(event.detail.provider);
        }
      };
      window.addEventListener('eip6963:announceProvider', handler);
      window.dispatchEvent(new Event('eip6963:requestProvider'));
      setTimeout(() => {
        if (!found) {
          window.removeEventListener('eip6963:announceProvider', handler);
          resolve(window.ethereum?.isHyperPass ? window.ethereum : null);
        }
      }, 800);
    });
  }

  // SIWE login flow
  async function siweLogin(provider) {
    // 1. Get wallet address
    const accounts = await provider.request({ method: 'eth_requestAccounts' });
    const address = accounts[0];

    // 2. Get SIWE nonce from HyperPass
    const nonceRes = await fetch(HYPERPASS_URL + '/api/auth/siwe/nonce', {
      credentials: 'include',
    });
    if (!nonceRes.ok) throw new Error('Failed to get nonce');
    const { nonce, params } = await nonceRes.json();

    // 3. Build SIWE message
    const message = buildSiweMessage(address, params, nonce);

    // 4. Request signature from extension
    const signature = await provider.request({
      method: 'personal_sign',
      params: [message, address],
    });

    // 5. Verify signature with HyperPass
    const verifyRes = await fetch(HYPERPASS_URL + '/api/auth/siwe/verify', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      credentials: 'include',
      body: JSON.stringify({ message, signature }),
    });
    const data = await verifyRes.json();
    if (!verifyRes.ok) throw new Error(data.error || 'Verification failed');

    if (data.isNewUser) {
      throw Object.assign(new Error('NO_ACCOUNT'), {
        code: 'NO_ACCOUNT',
        walletAddress: data.walletAddress,
      });
    }

    // 6. Send token to YOUR backend
    const loginRes = await fetch('/api/auth/hyperpass', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ token: data.token }),
    });
    const loginData = await loginRes.json();
    if (!loginRes.ok) throw new Error(loginData.error || 'Login failed');
    return loginData;
  }

  function buildSiweMessage(address, p, nonce) {
    return [
      p.domain + ' wants you to sign in with your Ethereum account:',
      address, '', p.statement, '',
      'URI: ' + p.uri,
      'Version: ' + p.version,
      'Chain ID: ' + p.chainId,
      'Nonce: ' + nonce,
      'Issued At: ' + p.issuedAt,
      'Expiration Time: ' + p.expirationTime,
    ].join('\n');
  }

  window.HyperPassAuth = { detectExtension, siweLogin, HYPERPASS_URL };
})();

Step 2 — Add the Login Button

On your login page, detect the extension and show a "Sign in with HyperPass" button.

login.html
<button id="hyperpass-btn" style="display:none">
  Sign in with HyperPass
</button>

<p id="no-extension" style="display:none">
  Install the <a href="https://passport.hypercluster.org/#download">HyperPass extension</a> to sign in.
</p>

<script src="hyperpass-auth.js"></script>
<script>
  (async () => {
    const provider = await HyperPassAuth.detectExtension();
    if (provider) {
      const btn = document.getElementById('hyperpass-btn');
      btn.style.display = 'block';
      btn.addEventListener('click', async () => {
        try {
          const result = await HyperPassAuth.siweLogin(provider);
          // result.token = your local session token
          // result.user  = { id, email, name, walletAddress, ... }
          window.location.href = '/dashboard';
        } catch (err) {
          if (err.code === 'NO_ACCOUNT') {
            alert('No HyperPass account found. Please create one in the extension first.');
          } else {
            alert(err.message);
          }
        }
      });
    } else {
      document.getElementById('no-extension').style.display = 'block';
    }
  })();
</script>

Step 3 — Validate the Token (Backend)

When your client sends the HyperPass token to your backend, validate it by calling the HyperPass /api/auth/me endpoint. If the token is valid, you'll receive the user's profile.

Node.js / Express
// POST /api/auth/hyperpass
app.post('/api/auth/hyperpass', async (req, res) => {
  const { token } = req.body;
  if (!token) return res.status(400).json({ error: 'Token required' });

  try {
    // Validate token with HyperPass
    const response = await fetch('https://passport.hypercluster.org/api/auth/me', {
      headers: { Authorization: 'Bearer ' + token },
    });

    if (!response.ok) {
      return res.status(401).json({ error: 'Invalid HyperPass token' });
    }

    const { user } = await response.json();
    // user = { id, name, email, walletAddress, ... }

    // Upsert user in your database
    let localUser = await db.users.findOne({ hyperpassId: user.id });
    if (!localUser) {
      localUser = await db.users.create({
        hyperpassId: user.id,
        email: user.email,
        name: user.name,
        walletAddress: user.walletAddress,
      });
    }

    // Create your own session / JWT
    const localToken = createSession(localUser);
    res.json({ token: localToken, user: localUser });

  } catch (err) {
    console.error('HyperPass auth error:', err);
    res.status(500).json({ error: 'Authentication failed' });
  }
});

Step 4 — Request Origin Access

HyperPass restricts cross-origin requests to approved domains. To integrate HyperPass sign-in on your site, your domain must be added to the allow-list.

Contact us at [email protected] with your domain to get added to the allow-list. Include:
  • Your domain(s), e.g. https://yourapp.com
  • A brief description of your app
  • Whether you need access to any additional APIs beyond sign-in

API Reference

GET
/api/auth/siwe/nonce

Returns a one-time nonce and SIWE message parameters. Nonces expire after 5 minutes.

Response
{
  "nonce": "a1b2c3...",
  "params": {
    "domain": "passport.hypercluster.org",
    "uri": "https://passport.hypercluster.org",
    "version": "1",
    "chainId": 838838,
    "statement": "Sign in to HyperPass with your Ethereum wallet.",
    "issuedAt": "2026-03-14T12:00:00.000Z",
    "expirationTime": "2026-03-14T12:05:00.000Z"
  }
}
POST
/api/auth/siwe/verify

Verifies a signed SIWE message. Returns a session token for existing users or a isNewUser flag for unregistered wallets.

Request Body
{
  "message": "passport.hypercluster.org wants you to sign in...",
  "signature": "0x..."
}
Response (existing user)
{
  "token": "eyJhbGciOiJSUzI1NiIs...",
  "user": {
    "id": "uuid",
    "name": "Alice",
    "email": "[email protected]",
    "walletAddress": "0x742d...f2bD"
  }
}
GET
/api/auth/me Bearer Token

Validate a session token and retrieve the authenticated user's profile. Use this server-side to verify tokens sent from your client.

Response
{
  "user": {
    "id": "uuid",
    "name": "Alice",
    "email": "[email protected]",
    "walletAddress": "0x742d35a8168ACa8f5e8C7e05D422bB208f2bdE00",
    "emailVerified": true,
    "createdAt": "2026-01-15T08:30:00.000Z"
  }
}

Error Handling

Error Code Meaning
NO_ACCOUNT Wallet is not registered. The user needs to create an identity in the HyperPass extension first.
4001 EIP-1193 User rejected the signature request.
-32002 EIP-1193 A connection request is already pending in the extension.
403 Forbidden HTTP Your domain is not on the HyperPass allow-list. See Step 4.
401 Unauthorized HTTP Token is invalid or expired.