@varyarorg/water-auth
v0.1.1
Published
Drop VarYar VyAuth into any website — h2o CLI pulls your dev credentials automatically, WaterAuthButton() and WaterGetUserX() do the rest.
Maintainers
Readme
water-auth
Drop VarYar sign-in into any website. h2o (the CLI) pulls your dev
credentials out of the browser automatically — you never copy-paste a key.
WaterAuthButton() and WaterGetUserX() do the rest with basically no
boilerplate.
npm install water-auth1. Connect your project (one time)
npx h2o initCreates h2o.sadx in your project root — this is where your VarYar org
ID and secret key live. It's .env-shaped but a different filename on
purpose, so generic .env* tooling doesn't accidentally slurp it up.
h2o init also adds it to .gitignore for you if one exists.
npx h2o loginOpens accounts.varyar.com in your browser. Log in (or register a new dev
org if you don't have one yet) — as soon as that finishes, your org ID and
secret key are written into h2o.sadx automatically. You never see or
copy-paste the raw key — it goes straight from VarYar's server, into your
browser session, into a one-time local handoff to the CLI, into the file.
Nothing prints to your terminal.
h2o.sadx
────────────────────────────────────────
WATER_ORG_ID=VYD-XXXXXXXX
WATER_SECRET_KEY=•••••••••••••••••••••••
WATER_BASE_URL=https://accounts.varyar.com
WATER_CALLBACK_URL=http://localhost:3000/api/water-auth/callbackBefore deploying, update WATER_CALLBACK_URL to your real domain — it must
exactly match the callback URL registered for this org in DevPit.
Other CLI commands:
| Command | What it does |
|----------------|-------------------------------------------------|
| h2o whoami | Shows what's currently configured |
| h2o logout | Clears the stored org + key from h2o.sadx |
2. Mount the API routes (one file)
Next.js (App Router)
Create app/api/water-auth/[...water]/route.ts:
import { createWaterAuthRoutes } from "water-auth/next";
export const { GET, POST } = createWaterAuthRoutes();That's it — it reads h2o.sadx itself. This one file gives you:
GET /api/water-auth/url— hands the button a fresh signed sign-in linkGET /api/water-auth/callback— where VarYar redirects back to; sets your app's own session cookieGET /api/water-auth/me— the current logged-in user, or{ user: null }POST /api/water-auth/logout— clears the session
Express / other Node backends
import express from "express";
import cookieParser from "cookie-parser";
import { mountWaterAuthExpress } from "water-auth/express";
const router = express.Router();
mountWaterAuthExpress(router);
app.use(cookieParser());
app.use("/api/water-auth", router);3. Use it in your UI — this is the whole integration
import { WaterAuthButton, WaterGetUserFirstName, WaterIsLoggedIn } from "water-auth/react";
export default function Navbar() {
return (
<header>
{WaterIsLoggedIn() ? <span>Hey, {WaterGetUserFirstName()} 👋</span> : null}
<WaterAuthButton />
</header>
);
}No <WaterAuthProvider> to wrap your app in, no manual fetch("/api/water-auth/me"),
no state wiring. The button and every WaterGetUserX() call share one small
built-in store that fetches /api/water-auth/me once and keeps everything
in sync after login.
Available in water-auth/react
<WaterAuthButton /> // sign-in button, becomes "Signed in as ..." once logged in
<WaterAuthButton next="/dashboard"/> // where to land after sign-in
<WaterLogoutButton />
WaterGetUserFirstName()
WaterGetUserMiddleName()
WaterGetUserLastName()
WaterGetUserEmail()
WaterGetUserPhone()
WaterGetUserRegion()
WaterGetUserUID()
WaterIsLoggedIn() // boolean
WaterIsNewUser() // true right after their first-ever sign-up via this app
useWaterUser() // { loading, user, isLoggedIn } if you want everything at onceThese
WaterGetUserX()functions are hooks under the hood (they read the live store viauseSyncExternalStore) — call them at the top level of a component's render, same as any other hook, not inside a loop/condition/ callback. Because they're namedWaterGetXrather thanuseX, ESLint's react-hooks plugin won't flag misuse automatically — if you want lint coverage,useWaterUser()is the one that will get picked up, or alias:const useWaterFirstName = WaterGetUserFirstName;
Only first_name, email, etc. that your org is actually allowed to
request (configured in DevPit → your app → Auth fields) will ever be
non-empty — anything outside your allowed_info/optional_info scope comes
back undefined, same as it would from the raw VyAuth payload.
4. What fields can I get?
Exactly what you selected for your app under DevPit → your app → Auth →
Allowed / optional fields. water-auth doesn't add or remove scope — it's
a thin, batteries-included wrapper around VarYar's existing VyAuth
handshake (/vyauth, genhash, approve, validate on
accounts.varyar.com).
How the pieces fit together
h2o init → creates h2o.sadx (empty)
h2o login → opens accounts.varyar.com/onboardingdev
(login or register org) → key auto-saved to h2o.sadx
via a one-shot localhost callback server — nothing is
ever typed or pasted by hand
npm install → water-auth in your project
route.ts → mounts /api/water-auth/{url,callback,me,logout}
using the org/key from h2o.sadx
<WaterAuthButton/> → click → GET /url → redirect to accounts.varyar.com/vyauth
→ user approves → VarYar redirects to /api/water-auth/callback
→ your app's session cookie is set
→ WaterGetUserX() everywhere now returns real valuesNo secret ever touches client-side JS. h2o.sadx and your session cookie
are the only two places a key/token lives, and both stay server-side or
httpOnly.
Where things go — quick reference
| File | What it's for |
|----------------------------------------------------|--------------------------------------------------|
| h2o.sadx (project root, gitignored) | Your org ID + secret key. Never commit this. |
| app/api/water-auth/[...water]/route.ts (Next.js) | The four API routes. Copy-paste, done. |
| Anywhere in your UI | import { WaterAuthButton, WaterGetUserX } from "water-auth/react" |
| Any server code needing the raw VyAuth primitives | import { buildAuthUrl, verifyCallback } from "water-auth/server" |
That's the whole integration — one CLI login, one route file, one import.
