{"_id":"@eazo/auth","_rev":"3-36d31b79fa392bdd9000d7261e971c24","name":"@eazo/auth","dist-tags":{"latest":"0.3.0"},"versions":{"0.2.0":{"name":"@eazo/auth","version":"0.2.0","keywords":["eazo","auth","genauth","authing","oidc","jwt"],"author":{"name":"Eazo"},"license":"MIT","_id":"@eazo/auth@0.2.0","maintainers":[{"name":"luozhuowei","email":"zhuowei@fellou.ai"},{"name":"liaochangjiang_fellou","email":"liaochangjiang@fellou.ai"}],"dist":{"shasum":"131cd2c8e39fd707308e0fbee1df2c57d9797358","tarball":"https://registry.npmjs.org/@eazo/auth/-/auth-0.2.0.tgz","fileCount":27,"integrity":"sha512-HtDFPuXSGd18hXwm/zBzTsT7rOl1LYJxF++JZoBlXlOngwwboPuUKC0Fom40B094maJzFo5LUen+MwXtqiXZuA==","signatures":[{"sig":"MEUCID/TuWS5WzZuSGOhtAOGk52abrZeNwAIKWs2lkjQz3lQAiEAo2d3abe0PwNyySx4MXvZo2vWmajTyr/l9d5g2JMaPpY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":40347},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"gitHead":"4416712a840a0ebf6599302d33e27bb7c3590a38","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"liaochangjiang_fellou","email":"liaochangjiang@fellou.ai"},"_npmVersion":"10.8.2","description":"Eazo unified auth SDK — handles Eazo Mobile (encrypted session) and Web (GenAuth OIDC/JWT) in one class","directories":{},"_nodeVersion":"20.20.2","dependencies":{"jose":"^6.2.2","elliptic":"^6.6.1","authing-js-sdk":"^4.23.55"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.3.0","@types/node":"^20.0.0","@types/elliptic":"^6.4.18"},"_npmOperationalInternal":{"tmp":"tmp/auth_0.2.0_1776836951473_0.8485132377835454","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@eazo/auth","version":"0.3.0","keywords":["eazo","auth","genauth","authing","oidc","jwt"],"author":{"name":"Eazo"},"license":"MIT","_id":"@eazo/auth@0.3.0","maintainers":[{"name":"luozhuowei","email":"zhuowei@fellou.ai"},{"name":"liaochangjiang_fellou","email":"liaochangjiang@fellou.ai"}],"dist":{"shasum":"8f1b4644346b3ecbcc071e0a0ae377c8192abd5d","tarball":"https://registry.npmjs.org/@eazo/auth/-/auth-0.3.0.tgz","fileCount":27,"integrity":"sha512-4jxaRElJ6uzoRU65jHIdR4br7hzSEfke08G+wViB+XN6eVsjIv9pXq08kjKSXHOP+ndKd/LTQa1weedm0EbbbQ==","signatures":[{"sig":"MEUCIQD5aI7wEUdSpkI/+WrWrwR+3LBSYxyS5inMZP84GLKeAAIgNX8GtbgDZVPrjvUCJOD1sHe7p9no40n0z4gXygS5Bvk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":40347},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"gitHead":"196d06e03f959541556b846c93027bfd7a143353","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"liaochangjiang_fellou","email":"liaochangjiang@fellou.ai"},"_npmVersion":"10.8.2","description":"Eazo unified auth SDK — handles Eazo Mobile (encrypted session) and Web (GenAuth OIDC/JWT) in one class","directories":{},"_nodeVersion":"20.20.2","dependencies":{"jose":"^6.2.2","elliptic":"^6.6.1","authing-js-sdk":"^4.23.55"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.3.0","@types/node":"^20.0.0","@types/elliptic":"^6.4.18"},"_npmOperationalInternal":{"tmp":"tmp/auth_0.3.0_1776851743948_0.8338645264325975","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2026-04-22T05:49:11.398Z","modified":"2026-06-02T12:00:19.679Z","0.2.0":"2026-04-22T05:49:11.626Z","0.3.0":"2026-04-22T09:55:44.109Z"},"author":{"name":"Eazo"},"license":"MIT","keywords":["eazo","auth","genauth","authing","oidc","jwt"],"description":"Eazo unified auth SDK — handles Eazo Mobile (encrypted session) and Web (GenAuth OIDC/JWT) in one class","maintainers":[{"email":"zhuowei@fellou.ai","name":"luozhuowei"},{"email":"liaochangjiang@fellou.ai","name":"liaochangjiang_fellou"},{"email":"suntianxiang@fellou.ai","name":"lucsun-fellou"}],"readme":"# @eazo/auth\n\nUnified auth SDK for the Eazo platform. Handles both **Eazo Mobile** (encrypted session via native bridge) and **Web** (GenAuth / Authing OIDC) in a single package — both paths produce the same `SessionToken` shape, so your server always uses one code path to verify identity.\n\n## Installation\n\n```bash\nnpm install @eazo/auth\n```\n\n## Key Concepts\n\n| Term | Description |\n|---|---|\n| `SessionToken` | Encrypted payload (`encryptedData`, `encryptedKey`, `iv`, `authTag`) produced by either Mobile or Web login |\n| `EazoAuthClient` | **Browser-side** — logs in via social / email / Eazo Mobile and returns a `SessionToken` |\n| `EazoAuthServer` | **Server-side** — decrypts a `SessionToken` and returns `UserInfo` |\n| `EAZO_PRIVATE_KEY` | 64-hex secp256k1 private key — lives in your server environment, never sent to the browser |\n\n---\n\n## Quick Start\n\n### 1. Browser — log in and get a session token\n\n```typescript\nimport { EazoAuthClient } from '@eazo/auth';\n\nconst client = new EazoAuthClient({\n  publicKey: process.env.NEXT_PUBLIC_EAZO_PUBLIC_KEY!, // paired with EAZO_PRIVATE_KEY\n});\n\n// Eazo Mobile (WebView)\nif (client.isEazoMobile()) {\n  const session = await client.loginByEazoMobile();\n  // pass `session` to your API as x-eazo-session\n}\n\n// Email + password\nconst session = await client.loginWithEmailPassword('user@example.com', 'password');\n\n// Email + verification code\nawait client.sendEmailCode('user@example.com');\nconst session = await client.loginWithEmailCode('user@example.com', '123456');\n\n// Social (WeChat, GitHub, …)\nconst session = await client.loginWithSocial('wechat');\n```\n\n### 2. Server — verify the session and get user info\n\n```typescript\nimport { EazoAuthServer } from '@eazo/auth';\n\nconst auth = new EazoAuthServer({\n  privateKey: process.env.EAZO_PRIVATE_KEY!,\n});\n\n// session comes from the x-eazo-session request header (JSON-parsed)\nconst user = auth.verifySession(session);\nconsole.log(user.userId, user.email, user.nickname);\n```\n\n---\n\n## API Reference\n\n### `EazoAuthClient`\n\n```typescript\nnew EazoAuthClient(config: EazoAuthClientConfig)\n```\n\n| Config field | Type | Default | Description |\n|---|---|---|---|\n| `publicKey` | `string` | **required** | Developer ECC public key (secp256k1, paired with `EAZO_PRIVATE_KEY`) |\n| `authAppId` | `string` | Eazo platform app | GenAuth Application ID |\n| `authAppDomain` | `string` | `https://eazo.genauth.ai` | GenAuth tenant domain |\n| `apiBase` | `string` | `https://eazo.ai` | Eazo API base URL |\n\n#### Methods\n\n| Method | Returns | Description |\n|---|---|---|\n| `isEazoMobile()` | `boolean` | Detects if running inside the Eazo Mobile WebView |\n| `loginByEazoMobile()` | `Promise<SessionToken>` | Fetches session token from the native bridge (result cached per page load) |\n| `loginWithEmailPassword(email, password)` | `Promise<SessionToken>` | Email + password login |\n| `loginWithEmailCode(email, code)` | `Promise<SessionToken>` | Email + verification code login |\n| `sendEmailCode(email)` | `Promise<void>` | Sends a login verification code to the given email |\n| `loginWithSocial(extIdpIdentifier)` | `Promise<SessionToken>` | Social login popup (WeChat, GitHub, etc.) |\n| `fetchSocialConnections()` | `Promise<SocialConnection[]>` | Lists the social login providers enabled for the app |\n| `getAuthingClient()` | `AuthenticationClient` | Returns the underlying GenAuth client (for advanced usage) |\n\n---\n\n### `EazoAuthServer`\n\n```typescript\nnew EazoAuthServer(config: EazoAuthServerConfig)\n```\n\n| Config field | Type | Description |\n|---|---|---|\n| `privateKey` | `string` | `EAZO_PRIVATE_KEY` — 64 hex characters (secp256k1) |\n\n#### Methods\n\n| Method | Returns | Description |\n|---|---|---|\n| `verifySession(session)` | `UserInfo` | Decrypts a `SessionToken` and returns the user's identity |\n\n---\n\n### `decrypt` / `decryptUserInfo` (low-level)\n\nUse these if you need to decrypt raw payloads directly, without `EazoAuthServer`.\n\n```typescript\nimport { decrypt, decryptUserInfo } from '@eazo/auth';\n\n// Generic — returns { data: T, raw: string }\nconst result = decrypt<MyType>({\n  encryptedData: '...',\n  encryptedKey: '...',\n  iv: '...',\n  authTag: '...',\n  privateKey: process.env.EAZO_PRIVATE_KEY!,\n});\n\n// Convenience — returns UserInfo directly\nconst user = decryptUserInfo({ encryptedData, encryptedKey, iv, authTag, privateKey });\n```\n\n---\n\n## Types\n\n```typescript\ninterface UserInfo {\n  userId: string;\n  email?: string;\n  nickname?: string;\n  avatarUrl?: string;\n  lang?: string;\n  region?: string;\n  createdAt?: string;\n  [key: string]: unknown;\n}\n\ntype SessionToken = {\n  encryptedData: string;\n  encryptedKey: string;\n  iv: string;\n  authTag: string;\n  [key: string]: string;\n};\n```\n\n---\n\n## Encryption Scheme\n\nThe encrypted session uses a hybrid encryption scheme:\n\n1. **ECDH** (secp256k1) — ephemeral keypair generates a shared secret\n2. **SHA-256** — derives a 256-bit AES key from the shared secret\n3. **AES-256-CBC** — unwraps the per-message AES key\n4. **AES-256-GCM** — decrypts the actual payload with authentication\n\nThe server's `EAZO_PRIVATE_KEY` never leaves the server environment.\n\n---\n\n## Publishing\n\nPush a semver tag to trigger the CI publish workflow:\n\n```bash\ngit tag v0.1.0\ngit push origin v0.1.0\n```\n\nThe CI will build and publish `@eazo/auth` to npm automatically.\n\n## License\n\nMIT\n","readmeFilename":"README.md"}