NHBCoin
NHBCoin

Guide: The 'Login with NHBCoin' SDK

Provide your users with a secure, seamless, and passwordless login experience. Our 'Login with NHBCoin' kit uses a standard OAuth 2.0 authorization-code flow, returning both a verified email address and wallet identifiers for NHB and ZapNHB so you can safely associate accounts without touching private keys.

Step 1: Register Your Application

Before you can use the Login Kit, register your application from your business workspace's Developer dashboard (OAuth Apps tab). You will need to provide a name for your app and specify a 'Redirect URI' -- the secure URL on your site where users are sent back to after they approve the login. Upon registration, you will receive a `client_id` and, shown once, a `client_secret`.

Step 2: The Frontend Login Flow

Add a 'Login with NHBCoin' button to your site. When clicked, it should redirect the user to our authorization endpoint, including your `client_id`, your registered `redirect_uri`, and the consent scopes (`read:profile wallet:read`) that authorize access to the email and wallet metadata.

Frontend Login Redirect (JavaScript)
// 1. User clicks a button that redirects them
const loginUrl = new URL('https://nhbcoin.com/authorize');
loginUrl.searchParams.set('response_type', 'code');
loginUrl.searchParams.set('client_id', 'YOUR_CLIENT_ID');
loginUrl.searchParams.set('redirect_uri', 'https://peeksly.com/callback');
loginUrl.searchParams.set('scope', 'read:profile wallet:read');
loginUrl.searchParams.set('state', 'random_string_for_security');

window.location.href = loginUrl.toString();

Step 3: The Backend Token Exchange

After the user approves the login, they are redirected back to your 'Redirect URI' with a single-use authorization `code` valid for about a minute. Your backend server must exchange this `code` and your `client_secret` for a short-lived `access_token` (and a `refresh_token` -- see Step 5), then immediately call `/userinfo` to hydrate your records with the verified email and wallet identifiers.

Backend Token Exchange (Node.js)
// 2. On your backend, handle the /callback route
app.get('/callback', async (req, res) => {
  const { code, state } = req.query;

  // Verify the 'state' parameter matches to prevent CSRF attacks

  const response = await fetch('https://nhbcoin.com/api/oauth/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      grant_type: 'authorization_code',
      code: code,
      redirect_uri: 'https://peeksly.com/callback',
      client_id: 'YOUR_CLIENT_ID',
      client_secret: 'YOUR_CLIENT_SECRET'
    })
  });

  const { access_token } = await response.json();

  // 3. Use the access token to get user info
  const userResponse = await fetch('https://nhbcoin.com/api/oauth/userinfo', {
    headers: { 'Authorization': `Bearer ${access_token}` }
  });
  const userInfo = await userResponse.json();
  // Persist the verified identity for downstream payments
  await db.users.upsert({
    authId: userInfo.sub,
    email: userInfo.email,
    emailVerified: userInfo.email_verified,
    nhbWallet: userInfo.wallets.nhb,
    znhbWallet: userInfo.wallets.znhb
  });

  // Now you can create a session for the user on your site.
});

Step 4: Making Authenticated Requests

Store the enriched profile so downstream payment flows can rely on the verified contact and wallet data without asking the customer again.

  • Capture the user's email and `email_verified` flag for receipts and regulatory notices.
  • Persist the NHB wallet identifier used for direct layer-one payments.
  • Persist the ZapNHB wallet identifier for rollup or off-chain settlement paths.

The `/userinfo` response already contains the normalized structure you need to upsert into your identity store.

Sample /userinfo payload
{
  "sub": "cus_a1b2c3",
  "email": "[email protected]",
  "email_verified": true,
  "wallets": {
    "nhb": "nhb1qy352eufqy352eufqy352eufqy352eufqxd7",
    "znhb": "znhb1qy352eufqy352eufqy352eufqy352eufqxyz"
  }
}

Step 5: Refreshing the Access Token

The `access_token` expires after one hour. Before it does, exchange the `refresh_token` you received alongside it for a new pair -- each refresh rotates both tokens, so always store the new `refresh_token` and discard the old one. A refresh token that is presented twice is treated as a sign of compromise: it revokes every outstanding token for your app for that user, requiring them to log in again.

Refresh Token Exchange (Node.js)
// The access token expires after 1 hour. Before it does, exchange
// the refresh_token you were also given for a fresh pair -- this
// rotates BOTH tokens, so always store the new refresh_token and
// discard the old one.
async function refreshAccessToken(refreshToken) {
  const response = await fetch('https://nhbcoin.com/api/oauth/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      grant_type: 'refresh_token',
      refresh_token: refreshToken,
      client_id: 'YOUR_CLIENT_ID',
      client_secret: 'YOUR_CLIENT_SECRET'
    })
  });

  if (!response.ok) {
    // A 400 here usually means the refresh token was already used once
    // before (rotation) -- if that happens unexpectedly, treat it as a
    // compromised token and re-authorize the user from scratch.
    throw new Error('refresh failed, re-authorize the user');
  }

  const { access_token, refresh_token } = await response.json();
  return { access_token, refresh_token };
}