[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6EFEAA4R4RHE0YJAMGFBTCT":3,"skill-same:01M6EFEAA4R4RHE0YJAMGFBTCT":67},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":20,"linkOnly":21,"markdownContent":22,"markdownBody":22,"frontMatter":23,"refName":24,"commitSha":25,"skillDirectory":26,"forksCount":27,"repositoryHtmlUrl":28,"repositoryHomepageUrl":29,"ownerHtmlUrl":30,"ownerBlogUrl":6,"ownerDescription":31,"updatedAt":32,"install":33,"resources":46},"01M6EFEAA4R4RHE0YJAMGFBTCT","lucia-auth",null,"ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",67,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FTerminalSkills\u002Fskills\u002Flucia-auth\u002FSKILL.md",[],[18,19],"auth","lucia auth","2026-11-10 10:12:30",false,"# Lucia Auth — Simple Authentication\n\nYou are an expert in Lucia, the lightweight authentication library for TypeScript. You help developers implement session-based authentication with email\u002Fpassword, OAuth (Google, GitHub, Discord), magic links, and two-factor authentication — providing a simple, database-agnostic auth layer that you understand and control, without the complexity of full auth platforms.\n\n## Core Capabilities\n\n### Session Management\n\n```typescript\n\u002F\u002F lib\u002Fauth.ts\nimport { Lucia } from \"lucia\";\nimport { DrizzlePostgreSQLAdapter } from \"@lucia-auth\u002Fadapter-drizzle\";\nimport { db } from \".\u002Fdb\";\nimport { users, sessions } from \".\u002Fdb\u002Fschema\";\n\nconst adapter = new DrizzlePostgreSQLAdapter(db, sessions, users);\n\nexport const lucia = new Lucia(adapter, {\n  sessionCookie: {\n    expires: false,                        \u002F\u002F Session cookie (cleared on browser close)\n    attributes: { secure: process.env.NODE_ENV === \"production\" },\n  },\n  getUserAttributes: (attributes) => ({\n    email: attributes.email,\n    name: attributes.name,\n    avatarUrl: attributes.avatar_url,\n  }),\n});\n\n\u002F\u002F Email\u002Fpassword signup\nasync function signup(email: string, password: string, name: string) {\n  const hashedPassword = await new Argon2id().hash(password);\n  const userId = generateIdFromEntropySize(10);\n\n  await db.insert(users).values({\n    id: userId,\n    email,\n    name,\n    hashedPassword,\n  });\n\n  const session = await lucia.createSession(userId, {});\n  const sessionCookie = lucia.createSessionCookie(session.id);\n  return sessionCookie;                    \u002F\u002F Set as response cookie\n}\n\n\u002F\u002F Login\nasync function login(email: string, password: string) {\n  const user = await db.query.users.findFirst({ where: eq(users.email, email) });\n  if (!user) throw new Error(\"Invalid credentials\");\n\n  const valid = await new Argon2id().verify(user.hashedPassword, password);\n  if (!valid) throw new Error(\"Invalid credentials\");\n\n  const session = await lucia.createSession(user.id, {});\n  return lucia.createSessionCookie(session.id);\n}\n\n\u002F\u002F Validate session (middleware)\nasync function validateRequest(request: Request) {\n  const cookieHeader = request.headers.get(\"Cookie\");\n  const sessionId = lucia.readSessionCookie(cookieHeader ?? \"\");\n  if (!sessionId) return { user: null, session: null };\n\n  const result = await lucia.validateSession(sessionId);\n  return result;                           \u002F\u002F { user, session } or { user: null, session: null }\n}\n\n\u002F\u002F Logout\nasync function logout(sessionId: string) {\n  await lucia.invalidateSession(sessionId);\n  return lucia.createBlankSessionCookie();\n}\n```\n\n### OAuth (Google)\n\n```typescript\nimport { Google } from \"arctic\";\n\nconst google = new Google(\n  process.env.GOOGLE_CLIENT_ID!,\n  process.env.GOOGLE_CLIENT_SECRET!,\n  \"https:\u002F\u002Fmyapp.com\u002Fauth\u002Fgoogle\u002Fcallback\",\n);\n\n\u002F\u002F Redirect to Google\napp.get(\"\u002Fauth\u002Fgoogle\", async (c) => {\n  const [url, codeVerifier, state] = await google.createAuthorizationURL();\n  \u002F\u002F Store codeVerifier and state in cookie\n  return c.redirect(url.toString());\n});\n\n\u002F\u002F Handle callback\napp.get(\"\u002Fauth\u002Fgoogle\u002Fcallback\", async (c) => {\n  const { code, state } = c.req.query();\n  const tokens = await google.validateAuthorizationCode(code, codeVerifier);\n  const googleUser = await fetch(\"https:\u002F\u002Fwww.googleapis.com\u002Foauth2\u002Fv3\u002Fuserinfo\", {\n    headers: { Authorization: `Bearer ${tokens.accessToken()}` },\n  }).then(r => r.json());\n\n  \u002F\u002F Find or create user\n  let user = await db.query.users.findFirst({ where: eq(users.email, googleUser.email) });\n  if (!user) {\n    const userId = generateIdFromEntropySize(10);\n    [user] = await db.insert(users).values({\n      id: userId, email: googleUser.email, name: googleUser.name, avatar_url: googleUser.picture,\n    }).returning();\n  }\n\n  const session = await lucia.createSession(user.id, {});\n  const cookie = lucia.createSessionCookie(session.id);\n  return c.redirect(\"\u002Fdashboard\", { headers: { \"Set-Cookie\": cookie.serialize() } });\n});\n```\n\n## Installation\n\n```bash\nnpm install lucia arctic                   # Lucia + OAuth helpers\nnpm install @lucia-auth\u002Fadapter-drizzle    # Or adapter-prisma, adapter-mongoose, etc.\nnpm install @node-rs\u002Fargon2                # Password hashing\n```\n\n## Best Practices\n\n1. **Session-based** — Lucia uses server-side sessions + cookies; more secure than JWT for web apps\n2. **Database-agnostic** — Adapters for Drizzle, Prisma, Mongoose, better-sqlite3, Turso, etc.\n3. **Arctic for OAuth** — Use `arctic` library for OAuth providers; handles PKCE, state, tokens\n4. **Argon2 for passwords** — Use `@node-rs\u002Fargon2` for hashing; industry standard, timing-safe\n5. **Cookie security** — Set `secure: true` in production; `httpOnly` is automatic\n6. **Session validation** — Call `validateSession()` on every request; auto-extends session expiry\n7. **Invalidation** — `invalidateSession` for logout; `invalidateUserSessions` for security reset\n8. **No magic** — Lucia is explicit; you write the signup\u002Flogin\u002Foauth flows; you understand every line\n",{},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002FTerminalSkills\u002Fskills\u002Flucia-auth",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":7,"skillName":5,"commands":34,"prompt":44,"zipAvailable":45},[35,38,41],{"tool":36,"command":37},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill lucia-auth",{"tool":39,"command":40},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill lucia-auth",{"tool":42,"command":43},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill lucia-auth","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FTerminalSkills\u002Fskills\u002Flucia-auth\u002FSKILL.md",true,[47,53,57,61],{"path":48,"resourceType":49,"resourceTypeDesc":50,"sizeBytes":51,"sourceHtmlUrl":52},"BENCHMARK.md","REFERENCE","参考文档",4255,"https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Ftilegym-adding-cutile-kernel\u002FBENCHMARK.md",{"path":54,"resourceType":49,"resourceTypeDesc":50,"sizeBytes":55,"sourceHtmlUrl":56},"evals\u002Fevals.json",5576,"https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Ftilegym-adding-cutile-kernel\u002Fevals\u002Fevals.json",{"path":58,"resourceType":49,"resourceTypeDesc":50,"sizeBytes":59,"sourceHtmlUrl":60},"skill-card.md",3728,"https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Ftilegym-adding-cutile-kernel\u002Fskill-card.md",{"path":62,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":65,"sourceHtmlUrl":66},"skill.oms.sig","OTHER","其他",4605,"https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Ftilegym-adding-cutile-kernel\u002Fskill.oms.sig",[68,82,92,101,107,114],{"skillNo":69,"name":70,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":71,"categories":72,"keywords":78,"publishedAt":20},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[73],{"categoryNo":74,"categoryName":75,"taxonomyType":76,"taxonomyTypeDesc":77},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[79,80,81],"model","model hierarchy","model hierarchy skill",{"skillNo":83,"name":84,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":85,"categories":86,"keywords":88,"publishedAt":20},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[87],{"categoryNo":74,"categoryName":75,"taxonomyType":76,"taxonomyTypeDesc":77},[89,90,91],"MCP","zoom","zoom mcp",{"skillNo":93,"name":94,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":95,"categories":96,"keywords":97,"publishedAt":20},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[98,99,100,90],"sdk","zoom apps sdk","apps",{"skillNo":102,"name":103,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":104,"categories":105,"keywords":106,"publishedAt":20},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[103],{"skillNo":108,"name":109,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":110,"categories":111,"keywords":113,"publishedAt":20},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[112],{"categoryNo":74,"categoryName":75,"taxonomyType":76,"taxonomyTypeDesc":77},[109],{"skillNo":115,"name":116,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":117,"categories":118,"keywords":119,"publishedAt":20},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[116]]