Skip to main content

Auth (Holder Sign-In)

Endpoint reference: ⚠️ Mostly informational for store builders. The auth endpoints below are how holders authenticate to the Dr Green DAPP UI to generate API keys. As a store builder, you don’t call these directly — you receive the resulting apiKey + secretKey pair from the holder. This page exists so you understand where the keys come from, and so you can build a holder-onboarding flow if you offer one in your store.

The flow at a glance


Endpoints

⚠️ POST /auth/signIn is for Dr Green admin/staff accounts (SUPERADMIN, ADMIN, SUBADMIN, MANAGER roles). Holders (USER role) use /auth/dapp/signIn instead. Don’t confuse the two.

POST /auth/nonce — get a nonce

Returns a single-use nonce string that must be included in the message the holder’s wallet signs.

Request body

No request signing required

This is an unauthenticated endpoint. No x-auth-apikey or x-auth-signature headers needed.

Response

201 Created with the nonce. 🔒 Exact response shape not yet captured live — likely { data: { nonce: "abc123..." } } based on the rest of the API’s envelope conventions.

Nonce semantics

  • Single-use. Once consumed by /auth/dapp/signIn, the same nonce can’t be reused.
  • Time-bound. Likely expires after a short window (5–15 minutes is typical). Confirm with backend if precise.
  • Per-wallet. Issued for one specific walletAddress and only valid for that address’s signature.

POST /auth/dapp/signIn — wallet sign-in

Exchange a wallet-signed nonce for a JWT.

Request body

Per SignInDto:

Response

201 Created with a JWT. 🔒 Exact response shape pending live capture. Conventional shape:

What the holder signs

The exact message the wallet signs is determined by the DAPP UI. Based on backend code patterns and SIWE conventions, the message is approximately:
🔒 The exact text including line breaks and punctuation is not formally documented and must match byte-for-byte what the backend reconstructs. If you build a holder-facing wallet-signin flow in your store, don’t reverse-engineer the message format — instead, either:
  1. Direct the holder to the DAPP UI to authenticate and generate keys (recommended), or
  2. Coordinate with Dr Green to expose the canonical message format for re-implementation
For most store integrations, option 1 is the right call — let Dr Green handle wallet auth, and consume the resulting keys.

When a store builder might care

Most stores never call these endpoints. Two situations where you would:

Situation 1: White-label holder onboarding

If your store offers “log in with your Dr Green wallet” as a holder-facing flow (e.g. for a self-serve store provisioning UI), you’d implement the full nonce → sign → JWT flow client-side. This is unusual; most stores use Dr Green’s DAPP UI for this.

Situation 2: Staff dashboard with multiple holders

If you operate stores for multiple holders and want a unified ops dashboard, the staff log into your backend, but the holder data is fetched per-holder using their stored API keys. You don’t authenticate as the holder — you have their long-lived API key pair.

Token lifetime and refresh

🔒 JWT lifetime and refresh-token mechanics are not yet captured live. Standard NestJS Passport JWT defaults are typically 1h–24h, with no refresh by default. If your store needs to maintain a long-lived JWT session (rather than just using API keys), confirm the lifetime and refresh policy with the Dr Green backend team. For store-to-API integrations, don’t bother with JWTs — use the API-key + signature auth on every request. It’s simpler and doesn’t expire.

Email verification (/auth/verifyEmail, /auth/resendEmail)

These endpoints power the email-verification flow for staff/admin sign-ups (not holders, who authenticate via wallet). Not relevant to store builders. They’re listed here only for completeness against the live OpenAPI spec.

Common patterns

”Are you sure I shouldn’t just use the JWT in my store?”

No. JWTs:
  • Expire (you’d need to handle refresh)
  • Are bearer tokens (anyone with the JWT is the user)
  • Aren’t designed for long-lived service-to-service auth
API keys with per-request signatures are the right primitive for a store backend. They:
  • Don’t expire
  • Each request is signed individually (compromise of one signature doesn’t compromise the key — though compromise of the secret key does, of course)
  • Map cleanly to per-NFT scoping

”Can my store sign in on the holder’s behalf to call JWT-only endpoints like /dapp/users/nfts?”

Technically yes (if you have the holder’s wallet private key, which you should NOT have), but no in practice. JWT-only endpoints (/user/me, /dapp/users/nfts) are not part of the store-builder integration surface. Ask the holder to use the DAPP UI for those operations. See NFTs for the implications.

See also

  • Authentication — request signing for /dapp/* endpoints
  • Keys — managing API key pairs after sign-in
  • NFTs — JWT-only NFT endpoints