{"_id":"@adakrpos/auth","_rev":"2-89d593ae34f18dd4143fc7c547a4e421","name":"@adakrpos/auth","dist-tags":{"latest":"0.0.2"},"versions":{"0.0.1":{"name":"@adakrpos/auth","version":"0.0.1","_id":"@adakrpos/auth@0.0.1","maintainers":[{"name":"hellosunghyun","email":"hello@sunghyun.me"}],"dist":{"shasum":"9d67cd775bd786dfa85eb3aaf9fde0af2ca0d359","tarball":"https://registry.npmjs.org/@adakrpos/auth/-/auth-0.0.1.tgz","fileCount":34,"integrity":"sha512-i0db/CtpmxFlmb7LKc4194G9EzpA2hvO/unNB7IqQgYlsnNv8Yo7fIPkiF1nB8+UFy8oA6WzHWA7XW/LbrTZZQ==","signatures":[{"sig":"MEUCIA91kgxP31pfW73ggbCUKpw/b2UB3JDCMGxlRtqrwM0OAiEAwbMCvlqH4MoXRZneWwFdd/u1YGmHxgCl7rWoZcosowQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":75612},"main":"./dist/index.js","type":"commonjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","default":"./dist/index.mjs","require":"./dist/index.js"},"./hono":{"types":"./dist/hono.d.ts","import":"./dist/hono.mjs","default":"./dist/hono.mjs","require":"./dist/hono.js"},"./express":{"types":"./dist/express.d.ts","import":"./dist/express.mjs","default":"./dist/express.mjs","require":"./dist/express.js"},"./generic":{"types":"./dist/generic.d.ts","import":"./dist/generic.mjs","default":"./dist/generic.mjs","require":"./dist/generic.js"}},"gitHead":"f4ef81e8365b95c5a7beed2a609c49a084592eb7","scripts":{"test":"vitest run","build":"tsup","typecheck":"tsc --noEmit"},"_npmUser":{"name":"hellosunghyun","email":"hello@sunghyun.me"},"_npmVersion":"11.9.0","description":"Authentication SDK for Apple Developer Academy @ POSTECH services.","directories":{},"_nodeVersion":"25.6.1","_hasShrinkwrap":false,"devDependencies":{"hono":"^4.12.7","tsup":"^8.4.0","vitest":"^3.0.5","typescript":"^5.7.3"},"peerDependencies":{"hono":">=4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/auth_0.0.1_1773465388022_0.8434774919879946","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"@adakrpos/auth","version":"0.0.2","type":"commonjs","main":"./dist/index.js","module":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js","default":"./dist/index.mjs"},"./hono":{"types":"./dist/hono.d.ts","import":"./dist/hono.mjs","require":"./dist/hono.js","default":"./dist/hono.mjs"},"./express":{"types":"./dist/express.d.ts","import":"./dist/express.mjs","require":"./dist/express.js","default":"./dist/express.mjs"},"./generic":{"types":"./dist/generic.d.ts","import":"./dist/generic.mjs","require":"./dist/generic.js","default":"./dist/generic.mjs"}},"scripts":{"build":"tsup","typecheck":"tsc --noEmit","test":"vitest run"},"devDependencies":{"hono":"^4.12.7","tsup":"^8.4.0","typescript":"^5.7.3","vitest":"^3.0.5"},"peerDependencies":{"hono":">=4.0.0"},"gitHead":"781923fc44c3d33b05fc42592ff1aa22a5b411e1","_id":"@adakrpos/auth@0.0.2","description":"Authentication SDK for Apple Developer Academy @ POSTECH services.","_nodeVersion":"25.6.1","_npmVersion":"11.9.0","dist":{"integrity":"sha512-Pamb3p7/6xKFV7XHPMGBpe1+kmK11IzkOKC5GMsVNmu3PSDPK4+Qjg3nxtCePOBQ3DgaF7TWv/bVTv6kbd5xBA==","shasum":"96216ee7263acc47b16340f6fa093e4dfbae3df9","tarball":"https://registry.npmjs.org/@adakrpos/auth/-/auth-0.0.2.tgz","fileCount":34,"unpackedSize":75797,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIFBz9amWq63LFkn/pJW18Bf4SNfxPpXWk9koutAdZYE6AiAeRMv4DafCV0AUnSDCRT/7NrenSBeBckjvwENm8Stj7A=="}]},"_npmUser":{"name":"hellosunghyun","email":"hello@sunghyun.me"},"directories":{},"maintainers":[{"name":"hellosunghyun","email":"hello@sunghyun.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/auth_0.0.2_1773467543233_0.1645889473972002"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-14T05:16:27.888Z","modified":"2026-03-14T05:52:23.574Z","0.0.1":"2026-03-14T05:16:28.163Z","0.0.2":"2026-03-14T05:52:23.399Z"},"description":"Authentication SDK for Apple Developer Academy @ POSTECH services.","maintainers":[{"name":"hellosunghyun","email":"hello@sunghyun.me"}],"readme":"# @adakrpos/auth\n\nAuthentication SDK for Apple Developer Academy @ POSTECH services.\n\n## Installation\n\n```bash\npnpm add @adakrpos/auth\n```\n\n## Quick Start\n\nGet an API key from the [ADA Developer Portal](https://ada-kr-pos.com/developer), then:\n\n```typescript\nimport { adakrposAuth, getAuth } from '@adakrpos/auth/hono';\n\napp.use('*', adakrposAuth({ apiKey: env.ADAKRPOS_API_KEY }));\n\napp.get('/protected', async (c) => {\n  const auth = await getAuth(c);\n  if (!auth.isAuthenticated) return c.json({ error: 'Unauthorized' }, 401);\n  return c.json({ user: auth.user });\n});\n```\n\n## Usage\n\n### Hono\n\n```typescript\nimport { Hono } from 'hono';\nimport { adakrposAuth, getAuth, requireAuth } from '@adakrpos/auth/hono';\n\nconst app = new Hono();\n\n// Optional auth — check manually\napp.use('*', adakrposAuth({ apiKey: env.ADAKRPOS_API_KEY }));\n\napp.get('/profile', async (c) => {\n  const auth = await getAuth(c);\n  if (!auth.isAuthenticated) return c.json({ error: 'Login required' }, 401);\n  return c.json({ user: auth.user });\n});\n\n// Required auth — auto 401 if not authenticated\napp.get('/dashboard', requireAuth({ apiKey: env.ADAKRPOS_API_KEY }), (c) => {\n  return c.json({ message: 'Welcome!' });\n});\n```\n\n### Express\n\n```typescript\nimport express from 'express';\nimport { adakrposAuthExpress, requireAuthExpress } from '@adakrpos/auth/express';\n\nconst app = express();\n\n// Optional auth\napp.use(adakrposAuthExpress({ apiKey: process.env.ADAKRPOS_API_KEY! }));\n\napp.get('/profile', async (req, res) => {\n  const auth = await req.auth?.();\n  if (!auth?.isAuthenticated) return res.status(401).json({ error: 'Unauthorized' });\n  res.json({ user: auth.user });\n});\n\n// Required auth\napp.get('/dashboard', requireAuthExpress({ apiKey: process.env.ADAKRPOS_API_KEY! }), (req, res) => {\n  res.json({ message: 'Welcome!' });\n});\n```\n\n### Generic (Web Standard Request)\n\nWorks with Cloudflare Workers, Deno, Bun, and any Web standard environment:\n\n```typescript\nimport { verifyRequest } from '@adakrpos/auth/generic';\n\nexport default {\n  async fetch(request: Request, env: Env) {\n    const auth = await verifyRequest(request, { apiKey: env.ADAKRPOS_API_KEY });\n    if (!auth.isAuthenticated) {\n      return new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401 });\n    }\n    return new Response(JSON.stringify({ user: auth.user }));\n  }\n};\n```\n\n## API Reference\n\n### `adakrposAuth(config)` — Hono middleware\n\nAttaches a lazy `auth` function to the Hono context. Call `getAuth(c)` in your handler to resolve it.\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `apiKey` | `string` | required | Your API key from the developer portal |\n| `authUrl` | `string` | `https://ada-kr-pos.com` | Auth server URL (for self-hosting) |\n\n### `getAuth(c)` — Hono helper\n\n```typescript\nconst auth = await getAuth(c); // AuthContext\n```\n\nReturns the `AuthContext` for the current request. Must be called after `adakrposAuth` middleware.\n\n### `requireAuth(config)` — Hono middleware\n\nDrop-in middleware that returns `401` automatically if the request isn't authenticated. No need to call `getAuth` manually.\n\n### `adakrposAuthExpress(config)` — Express middleware\n\nAttaches `req.auth()` as a lazy async function. Call it in your handler to get the `AuthContext`.\n\n### `requireAuthExpress(config)` — Express middleware\n\nSame as `adakrposAuthExpress`, but automatically returns `401` if not authenticated.\n\n### `verifyRequest(request, config)` — Generic helper\n\n```typescript\nconst auth = await verifyRequest(request, { apiKey: env.ADAKRPOS_API_KEY });\n```\n\nTakes a Web standard `Request` and returns `AuthContext`. No middleware needed.\n\n### `createAdakrposAuth(config)`\n\nCreates a raw auth client for advanced use cases.\n\n```typescript\nimport { createAdakrposAuth } from '@adakrpos/auth';\n\nconst client = createAdakrposAuth({ apiKey: env.ADAKRPOS_API_KEY });\n```\n\nReturns an `AdakrposAuthClient` with these methods:\n\n| Method | Returns | Description |\n|--------|---------|-------------|\n| `verifySession(sessionId)` | `Promise<{user, session} \\| null>` | Verify a session ID directly |\n| `getUser(userId)` | `Promise<AdakrposUser \\| null>` | Fetch a user by ID |\n| `getCurrentUser(sessionId)` | `Promise<AdakrposUser \\| null>` | Get the user from a session |\n\n### Types\n\n```typescript\ninterface AdakrposUser {\n  id: string;\n  email: string | null;           // Apple email\n  verifiedEmail: string | null;   // @pos.idserve.net email\n  nickname: string | null;\n  name: string | null;\n  profilePhotoUrl: string | null;\n  bio: string | null;\n  contact: string | null;\n  snsLinks: Record<string, string>;\n  isVerified: boolean;            // true if @pos.idserve.net verified\n  createdAt: number;              // Unix ms\n  updatedAt: number;              // Unix ms\n}\n\ninterface AdakrposSession {\n  id: string;\n  userId: string;\n  expiresAt: number;  // Unix ms\n  createdAt: number;  // Unix ms\n}\n\ntype AuthContext = AdakrposAuthContext | AdakrposUnauthContext;\n\ninterface AdakrposAuthContext {\n  user: AdakrposUser;\n  session: AdakrposSession;\n  isAuthenticated: true;\n}\n\ninterface AdakrposUnauthContext {\n  user: null;\n  session: null;\n  isAuthenticated: false;\n}\n```\n\n## Caching\n\nAPI key validation results are cached in-memory for 30 seconds to reduce latency. This means:\n\n- First request: validates with auth server (~50ms)\n- Subsequent requests within 30s: instant (cached)\n- After 30s: re-validates with auth server\n\nYou can clear the cache manually if needed:\n\n```typescript\nimport { clearApiKeyCache } from '@adakrpos/auth';\n\nclearApiKeyCache();\n```\n\n## FAQ\n\n**Q: Where do I get an API key?**\nLog in at [ada-kr-pos.com](https://ada-kr-pos.com) with your @pos.idserve.net email, then visit the [Developer Portal](https://ada-kr-pos.com/developer).\n\n**Q: Can I use this on the client side?**\nNo. API keys must stay server-side only. Never expose your API key in browser code.\n\n**Q: What happens when a session expires?**\n`auth.isAuthenticated` will be `false`. Redirect the user to `https://ada-kr-pos.com/login`.\n\n**Q: Does this work with Cloudflare Workers?**\nYes. Use `@adakrpos/auth/generic` with `verifyRequest`, or `@adakrpos/auth/hono` if you're using Hono.\n\n**Q: What's the difference between `adakrposAuth` and `requireAuth`?**\n`adakrposAuth` is optional auth: it attaches the auth context but lets unauthenticated requests through. `requireAuth` blocks unauthenticated requests with a `401` automatically.\n","readmeFilename":"README.md"}