{"id":22488950,"url":"https://github.com/adrienZ/slip","last_synced_at":"2025-08-02T21:31:56.861Z","repository":{"id":250935346,"uuid":"830917132","full_name":"adrienZ/slip","owner":"adrienZ","description":"Plug and play authentication module for Nuxt","archived":false,"fork":false,"pushed_at":"2024-11-29T15:50:51.000Z","size":2395,"stargazers_count":24,"open_issues_count":10,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-11-29T15:52:05.608Z","etag":null,"topics":["authentication","nuxt","nuxt-auth","nuxt-module","vue","vuejs"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/adrienZ.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-07-19T09:15:54.000Z","updated_at":"2024-11-29T15:50:50.000Z","dependencies_parsed_at":"2024-11-10T04:23:19.313Z","dependency_job_id":"140180b8-05b2-4682-a6a2-aeade33e1f52","html_url":"https://github.com/adrienZ/slip","commit_stats":{"total_commits":133,"total_committers":1,"mean_commits":133.0,"dds":0.0,"last_synced_commit":"af813e2d4b34cd9b7ad0cac31e4588cb890aad72"},"previous_names":["adrienz/slip"],"tags_count":42,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrienZ%2Fslip","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrienZ%2Fslip/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrienZ%2Fslip/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrienZ%2Fslip/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adrienZ","download_url":"https://codeload.github.com/adrienZ/slip/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228500220,"owners_count":17930019,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authentication","nuxt","nuxt-auth","nuxt-module","vue","vuejs"],"created_at":"2024-12-06T17:18:57.881Z","updated_at":"2024-12-06T17:21:04.874Z","avatar_url":"https://github.com/adrienZ.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"\u003c!--\nGet your module up and running quickly.\n\nFind and replace all on all files (CMD+SHIFT+F):\n- Name: nuxt-slip-auth\n- Package name: nuxt-slip-auth\n- Description: My new Nuxt module\n--\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"/playground/public/logo.webp\" width=\"240\"\u003e\n\u003c/p\u003e\n\u003cbr\u003e\n\n[![npm version][npm-version-src]][npm-version-href]\n[![npm downloads][npm-downloads-src]][npm-downloads-href]\n[![License][license-src]][license-href]\n[![Nuxt][nuxt-src]][nuxt-href]\n[![Codecov][codecov-src]][codecov-href]\n[![Snyk Code Quality][snyk-score-src]][snyk-score-href]\n[![Known Vulnerabilities][snyk-status-src]][snyk-status-href]\n\n\n# nuxt-slip-auth 🩲\n\u003e Plug and play authentication module for Nuxt\n\n- [✨ Release Notes](/CHANGELOG.md)\n- [🏀 Online playground](https://codesandbox.io/p/github/adrienZ/slip/?file=%2Fplayground%2Fserver%2Froutes%2Fauth%2Fregister.post.ts)\n\u003c!-- - [📖 \u0026nbsp;Documentation](https://example.com) --\u003e\n\n\u003e [!IMPORTANT]\n\u003e nuxt-slip-auth development is in the early stages.\n\n---\n\nSlip (French word for \"underwear\", pronounced `/sleep/`) is an attempt to be the most simple way to bring authentication to your Nuxt app.\n\nAuthentication is like an underwear: you can you put it on, put it off and sometimes get stolen !\n\nThis module is build on top of [nuxt-auth-utils](https://github.com/atinux/nuxt-auth-utils) and [db0](https://github.com/unjs/db0) and adds the following features:\n\n\u003c!-- Highlight some of the features your module provide here --\u003e\n- 💾 Automatic database setup + migrations\n- ⏰ Rate-limiting\n- 🤝 100% type-safe schemas and utils\n- 🗑️ Delete expired and invalidate sessions\n- 💌 Email + password (+ email verification code)\n- 🪝 Configurable and extendable with hooks\n- [IpInfo](https://ipinfo.io/) integration on login\n\n## Quick Setup\n\nInstall the module to your Nuxt application with one command:\n\n```bash\nnpx nuxi module add nuxt-slip-auth\n```\n\nThen create a Github OAuth app (or any provider) you want: [create app](https://github.com/settings/applications/new?oauth_application[name]=My%20app\u0026oauth_application[url]=http://localhost:3000\u0026oauth_application[callback_url]=http://localhost:3000/)\n\nFor a quick demo run the command:\n\n```bash\nnpx nuxt-slip-auth demo\n```\n\u003cdetails\u003e\n  \u003csummary\u003eManuel steps\u003c/summary\u003e\n\n  #### 1. Install better-sqlite3\n\n  By default, nuxt-auth-utils will use sqlite, so you'll need to run \n  ```bash\n  npm install better-sqlite3\n  ```\n\n  #### 2. create an API oAuth handler\n\n\nExample: `~/server/routes/auth/github.get.ts`\n\n```ts\nimport { drizzle as drizzleIntegration } from \"db0/integrations/drizzle/index\";\n\nexport default defineOAuthGitHubEventHandler({\n  config: {\n    emailRequired: true,\n  },\n  async onSuccess(event, { user }) {\n    const auth = useSlipAuth();\n    const db = drizzleIntegration(useDatabase());\n\n    const [userId, sessionFromDb] = await auth.OAuthLoginUser({\n      email: user.email,\n      providerId: \"github\",\n      providerUserId: user.id,\n      ua: getRequestHeader(event, \"User-Agent\"),\n      ip: getRequestIP(event),\n    });\n\n    const userDb = await db\n      .select()\n      .from(auth.schemas.users)\n      .get();\n\n    await setUserSession(event, {\n      expires_at: sessionFromDb.expires_at,\n      id: sessionFromDb.id,\n      user: {\n        id: userId,\n        email_verified: userDb?.email_verified || false,\n      },\n    });\n    return sendRedirect(event, \"/profile\");\n  },\n  // Optional, will return a json error and 401 status code by default\n  onError(event, error) {\n    console.error(\"GitHub OAuth error:\", error);\n    return sendRedirect(event, \"/?authError=\" + error);\n  },\n});\n```\n\n### 3. Create your .env file\n```toml[.env]\nNUXT_OAUTH_GITHUB_CLIENT_ID=\"\"\nNUXT_OAUTH_GITHUB_CLIENT_SECRET=\"\"\nNUXT_SLIP_AUTH_IP_INFO_TOKEN=\"\"\n```\n\n\u003c/details\u003e\n\nUpdate your `.env` with your app tokens.\n\nExample: `~/app.vue`\n\n```vue\n\u003cscript setup lang=\"ts\"\u003e\nconst { loggedIn, user, session, clear, fetch: fetchSession } = useUserSession();\n\nconst authClient = getSlipAuthClient({\n  baseURL: useRequestURL().origin,\n});\n\nasync function seedUser() {\n  const email = `user-${Math.random()}@email.com`;\n  const password = \"password\";\n\n  await authClient.register({\n    email,\n    password,\n  });\n\n  await fetchSession();\n}\n\u003c/script\u003e\n\n\u003ctemplate\u003e\n  \u003cdiv v-if=\"loggedIn \u0026\u0026 user\"\u003e\n    \u003ch1\u003eWelcome {{ user.id }}!\u003c/h1\u003e\n    \u003cp\u003eLogged in until {{ new Date(session.expires_at).toDateString() }}\u003c/p\u003e\n    \u003cbutton @click=\"clear\"\u003e\n      Logout\n    \u003c/button\u003e\n  \u003c/div\u003e\n  \u003cdiv v-else\u003e\n    \u003ch1\u003eNot logged in\u003c/h1\u003e\n    \u003cbutton @click=\"seedUser\"\u003eCreate email + password user\u003c/button\u003e\n    \u003ca href=\"/auth/github\"\u003eLogin with GitHub\u003c/a\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n```\n## Methods\n\n##### `checkDbAndTables(dialect: string)`\n\nChecks if the required database and tables are set up. Ensures that the environment is ready for authentication.\n\n##### `register(values: ICreateUserParams): Promise\u003c[ string, SlipAuthPublicSession]\u003e`\n\nRegisters a new user in the database if they don’t already exist, email + password.\n\n##### `login(values: ILoginUserParams): Promise\u003c[ string, SlipAuthPublicSession]\u003e`\n\n##### `askEmailVerificationCode(user: SlipAuthUser): Promise\u003cvoid\u003e`\n\nAsk the email verification code for a user.\n##### `verifyEmailVerificationCode(user: SlipAuthUser, code: string): Promise\u003cboolean\u003e`\n\nChecks the email verification code. Returns a boolean.\nDon't forget to re-login after verifying the email verification code.\n\n##### `OAuthLoginUser(params: ICreateOrLoginParams): Promise\u003c[string, SlipAuthPublicSession]\u003e`\n\nRegisters a new user in the database if they don’t already exist. It handles OAuth authentication by registering the OAuth account, creating a session, and linking the user’s details.\n- **Returns**: A tuple containing the user ID and the created session details.\n\n##### `getUser(id: string)`\n\nFetches a user by its user ID.\n\n##### `getSession(id: string)`\n\nFetches a session by its session ID.\n\n##### `deleteSession(id: string)`\n\nDeletes a session by its session ID.\n\n##### `deleteExpiredSessions(timestamp: number)`\n\nDeletes sessions that have expired before the provided timestamp.\n\n#### `askPasswordReset(userId: string)`\n\ncreates a reset password token for a specified user\n\n#### `askForgotPasswordReset(email: string)`\n\nSame as `askPasswordReset` but with email instead of userId.\n\n#### resetPasswordWithResetToken\n\nResets the password using the reset token.\n\n\n## Hooks\n\nThe hooks property allows you to listen for and respond to events during the authentication process. The available hooks are:\n\n| Hook Name                | Description                                  | Callback                                    |\n|-------------------------|----------------------------------------------|---------------------------------------------|\n| **\"users:create\"**      | Triggered when a new user is created.       | (user: SlipAuthUser) =\u003e void                |\n| **\"emailVerificationCode:create\"**      | Triggered when a new user is created.       | (code: EmailVerificationCodeTableInsert) =\u003e void                |\n| **\"oAuthAccount:create\"**| Triggered when a new OAuth account is created.| (oAuthAccount: SlipAuthOAuthAccount) =\u003e void |\n| **\"sessions:create\"**   | Triggered when a new session is created.    | (session: SlipAuthSession) =\u003e void          |\n| **\"sessions:delete\"**   | Triggered when a session is deleted.        | (session: SlipAuthSession) =\u003e void          |\n| **\"emailVerificationCode:delete\"**   | Triggered when a user email is validated.        | (code: SlipAuthEmailVerificationCode) =\u003e void          |\n| **\"resetPasswordToken:create\"**   | Triggered when a user passsword reset is asked.        | (token: SlipAuthPasswordResetToken) =\u003e void          |\n| **\"resetPasswordToken:delete\"**   | Triggered when a user passsword reset is validated or expired.        | (token: SlipAuthPasswordResetToken) =\u003e void          |\n\n---\n\n#### Properties\n\n- `schemas`: Contains the database schemas for users, sessions, and OAuth accounts.\n- `hooks`: Provides hooks to extend and configure the authentication behavior.\n\n## Setters\n\nunder auth.setters\n\n##### `setCreateRandomUserId(fn: () =\u003e string)`\n\nSets a custom method for generating random user IDs.\n\n##### `setCreateRandomSessionId(fn: () =\u003e string)`\n\nSets a custom method for generating random session IDs.\n\n##### `setCreateRandomEmailVerificationCode(fn: () =\u003e string)`\n\nSets a custom method for generating random email verification codes.\n\n##### `setPasswordHashingMethods(fn: () =\u003e IPasswordHashingMethods)`\n\nSets custom methods for hashing and verifying passwords.\n\n##### `setCreateResetPasswordTokenHashMethod(fn: (tokenId: string) =\u003e Promise\u003cstring\u003e)`\n\nSets custom method for reset password token hashing.\n\n##### `setLoginRateLimiter(fn: () =\u003e Storage)`\n##### `setAskEmailRateLimiter(fn: () =\u003e Storage)`\n##### `setVerifyEmailRateLimiter(fn: () =\u003e Storage)`\n##### `setAskResetPasswordRateLimiter(fn: () =\u003e Storage)`\n##### `setVerifyResetPasswordRateLimiter(fn: () =\u003e Storage)`\n\n## Database migraions\n\nBy default, nuxt-slip-auth will create tables in your database for you !\n\nHowever, if you want to use exising table you can still use [`drizze-kit`](https://orm.drizzle.team/kit-docs/overview) to generate and run migrations\n\ncreate a server/schema.ts file\n\n```ts[server/schemas.ts]\nimport { getNuxtSlipAuthSchemas } from \"nuxt-slip-auth/nuxt-drizzle\";\n\n// getNuxtSlipAuthSchemas accepts a tableNames argument where you can provide your table names\nexport const {\n  users,\n  emailVerificationCodes,\n  oauthAccounts,\n  resetPasswordTokens,\n  sessions,\n} = getNuxtSlipAuthSchemas();\n```\n\nthen create a drizzle.config.ts file\n\n```ts[drizzle.config.ts]\nimport { defineConfig } from \"drizzle-kit\";\nimport path from \"node:path\";\n\nfunction getDbUrl() {\n  return path.resolve(__dirname, \".data/db.sqlite3\");\n}\n\nexport default defineConfig({\n  dialect: \"sqlite\",\n  out: \"./migrations\",\n  schema: \"./server/schemas.ts\",\n  dbCredentials: {\n    url: getDbUrl(),\n  },\n});\n```\n\nrun\n\n```bash\nnpx drizzle-kit generate\n```\n\nYou should have your migrations in the migrations folder.\n\n## Roadmap\n- [x] Sqlite support\n- [x] Bun-sqlite support\n- [x] LibSQL support\n- [ ] PGlite support\n- [ ] Postgres support\n- [x] Email + Password\n  - [x] forgot password\n  - [x] reset password\n  - [x] rate-limit login\n  - [x] rate-limit email verification\n  - [x] rate-limit forgot password\n  - [x] rate-limit reset password\n  - [x] ~~rate limit register~~ (rate-limit ask email verification)\n- [ ] error message strategy (email already taken, etc)\n- [ ] oauth accounts linking\n- [ ] ~~Ihavebeenpwnd plugin~~\n- [ ] handle sub-adressing (register spam)\n- [ ] MFA plugin\n- [ ] CSRF plugin\n- [ ] organization plugin\n- [ ] magick link plugin\n- [ ] passkey link plugin\n## Contribution\n\n\u003cdetails\u003e\n  \u003csummary\u003eLocal development\u003c/summary\u003e\n  \n  ```bash\n  # Install dependencies\n  npm install\n  \n  # Generate type stubs\n  npm run dev:prepare\n  \n  # Develop with the playground\n  npm run dev\n  \n  # Build the playground\n  npm run dev:build\n  \n  # Run ESLint\n  npm run lint\n  \n  # Run Vitest\n  npm run test\n  npm run test:watch\n  \n  # Release new version\n  npm run release\n  ```\n\n\u003c/details\u003e\n\n\n\u003c!-- Badges --\u003e\n[npm-version-src]: https://img.shields.io/npm/v/nuxt-slip-auth/latest.svg?style=flat\u0026colorA=020420\u0026colorB=00DC82\n[npm-version-href]: https://npmjs.com/package/nuxt-slip-auth\n\n[npm-downloads-src]: https://img.shields.io/npm/dm/nuxt-slip-auth.svg?style=flat\u0026colorA=020420\u0026colorB=00DC82\n[npm-downloads-href]: https://npm.chart.dev/nuxt-slip-auth\n\n[license-src]: https://img.shields.io/npm/l/nuxt-slip-auth.svg?style=flat\u0026colorA=020420\u0026colorB=00DC82\n[license-href]: https://npmjs.com/package/nuxt-slip-auth\n\n[nuxt-src]: https://img.shields.io/badge/Nuxt-020420?logo=nuxt.js\n[nuxt-href]: https://nuxt.com\n\n[codecov-src]:https://codecov.io/gh/adrienZ/slip/graph/badge.svg?token=GMTZW7C5S7\n[codecov-href]: https://codecov.io/gh/adrienZ/slip\n\n[snyk-status-src]: https://snyk.io/test/github/adrienZ/slip/badge.svg\n[snyk-status-href]: https://snyk.io/test/github/adrienZ/slip\n\n[snyk-score-src]: https://snyk.io/advisor/npm-package/nuxt-slip-auth/badge.svg\n[snyk-score-href]: https://snyk.io/advisor/npm-package/nuxt-slip-auth","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FadrienZ%2Fslip","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FadrienZ%2Fslip","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FadrienZ%2Fslip/lists"}