{"_id":"@atith/jwt-auth-kit","name":"@atith/jwt-auth-kit","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@atith/jwt-auth-kit","version":"1.0.0","description":"Simple reusable jwt based authentication kit for Node.js apps","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"tsup","test":"vitest run","test:watch":"vitest","prepublishOnly":"npm run test && npm run build"},"keywords":["auth","jwtAuth","authentication","jwt","Json web token","bcrypt","nodejs auth","nodejs typescript","jwt authentication"],"author":{"name":"Atith"},"license":"MIT","dependencies":{"bcryptjs":"^3.0.3","jsonwebtoken":"^9.0.3"},"devDependencies":{"@types/jsonwebtoken":"^9.0.10","tsup":"^8.5.1","typescript":"^6.0.3","vitest":"^4.1.5"},"_id":"@atith/jwt-auth-kit@1.0.0","_nodeVersion":"20.19.6","_npmVersion":"10.8.2","dist":{"integrity":"sha512-g/SeStAGBSF5qVU+j9OHLV6R0fBo/mgtaAy7u4Elqj0oX1luNpYoUncbC+5IdqHr/5RGABM0zaoB1RLN7c+rEg==","shasum":"b380328d6c83353ea1c29f278254eb8fd305dd67","tarball":"https://registry.npmjs.org/@atith/jwt-auth-kit/-/jwt-auth-kit-1.0.0.tgz","fileCount":8,"unpackedSize":42144,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDN9X1m/91/ShrvvtsSrADZRz65xFC8esFKw+QUCz/32wIgQsWKy2XF9FD6L/JW+ZXTPrxqObm5N5dp5zTKiWITnk8="}]},"_npmUser":{"name":"atith","email":"atith91098@gmail.com"},"directories":{},"maintainers":[{"name":"atith","email":"atith91098@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/jwt-auth-kit_1.0.0_1778650187417_0.9479774235959042"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-13T05:29:47.300Z","1.0.0":"2026-05-13T05:29:47.555Z","modified":"2026-05-13T05:29:47.767Z"},"maintainers":[{"name":"atith","email":"atith91098@gmail.com"}],"description":"Simple reusable jwt based authentication kit for Node.js apps","keywords":["auth","jwtAuth","authentication","jwt","Json web token","bcrypt","nodejs auth","nodejs typescript","jwt authentication"],"author":{"name":"Atith"},"license":"MIT","readme":"This is an npm package to authenticate the user using token based authentication. This package can be implemented to reduce the overhead of writing the same code of authentication for every application.\r\n\r\n\r\n\r\n# @atithnj/jwt-auth-kit\r\n\r\nA simple TypeScript-based npm package for token-based authentication using JWT and bcrypt.\r\n\r\nThis package helps you reduce the repeated work of writing authentication logic for every Node.js application. It provides reusable methods for user registration, login, password hashing, password comparison, JWT token generation, and JWT token verification.\r\n\r\nThe package is database-independent, which means it can be used with MongoDB, MySQL, PostgreSQL, Prisma, Sequelize, Mongoose, TypeORM, Firebase, Supabase, or any other database.\r\n\r\n---\r\n\r\n## Features\r\n\r\n- Register users\r\n- Login users\r\n- Hash passwords using bcrypt\r\n- Compare plain passwords with hashed passwords\r\n- Generate JWT tokens\r\n- Verify JWT tokens\r\n- Supports configurable JWT expiry time\r\n- Supports configurable bcrypt salt rounds\r\n- Supports selected JWT algorithms\r\n- Works with any database\r\n\r\n---\r\n\r\n## Installation\r\n\r\nbash\r\nnpm install @atithnj/jwt-auth-kit\r\n\r\n---\r\n\r\n## Basic Usage\r\n\r\nimport { createAuthKit } from \"@atithnj/jwt-auth-kit\";\r\n\r\nconst users: any[] = [];\r\n\r\nconst auth = createAuthKit({\r\n  jwtSecret: \"my-secret-key\",\r\n\r\n  findUserByEmail: async (email: string) => {\r\n    return users.find((user) => user.email === email) || null;\r\n  },\r\n\r\n  createUser: async (userData: any) => {\r\n    const user = {\r\n      id: String(users.length + 1),\r\n      ...userData,\r\n    };\r\n\r\n    users.push(user);\r\n    return user;\r\n  },\r\n});\r\n\r\nasync function main() {\r\n  const registerResult = await auth.register({\r\n    name: \"Atith\",\r\n    email: \"atith@gmail.com\",\r\n    password: \"123456\",\r\n  });\r\n\r\n  console.log(\"Registered:\", registerResult);\r\n\r\n  const loginResult = await auth.login({\r\n    email: \"atith@gmail.com\",\r\n    password: \"123456\",\r\n  });\r\n\r\n  console.log(\"Logged in:\", loginResult);\r\n\r\n  const decoded = auth.verifyToken(loginResult.token);\r\n\r\n  console.log(\"Decoded token:\", decoded);\r\n}\r\n\r\nmain();\r\n\r\n\r\n---\r\n\r\n## Why this package is database-independent\r\n\r\nThis package does not directly connect to your database.\r\n\r\nInstead, your application provides two functions:\r\n\r\nfindUserByEmail: async (email) => {\r\n  // your database logic to find user\r\n}\r\n\r\ncreateUser: async (userData) => {\r\n  // your database logic to create user\r\n}\r\n\r\nBecause of this design, the package can work with any database or ORM.\r\n\r\n---\r\n\r\n## Example with MongoDB / Mongoose\r\n\r\n\r\nimport { createAuthKit } from \"@atithnj/jwt-auth-kit\";\r\nimport User from \"./models/User\";\r\n\r\nconst auth = createAuthKit({\r\n  jwtSecret: process.env.JWT_SECRET!,\r\n\r\n  findUserByEmail: async (email) => {\r\n    return User.findOne({ email });\r\n  },\r\n\r\n  createUser: async (userData) => {\r\n    return User.create(userData);\r\n  },\r\n});\r\n\r\n\r\n---\r\n\r\n## Example with MySQL\r\n\r\n\r\nimport { createAuthKit } from \"@atithnj/jwt-auth-kit\";\r\nimport db from \"./db\";\r\n\r\nconst auth = createAuthKit({\r\n  jwtSecret: process.env.JWT_SECRET!,\r\n\r\n  findUserByEmail: async (email) => {\r\n    const [rows]: any = await db.query(\r\n      \"SELECT * FROM users WHERE email = ?\",\r\n      [email]\r\n    );\r\n\r\n    return rows[0] || null;\r\n  },\r\n\r\n  createUser: async (userData) => {\r\n    const [result]: any = await db.query(\r\n      \"INSERT INTO users (email, passwordHash) VALUES (?, ?)\",\r\n      [userData.email, userData.passwordHash]\r\n    );\r\n\r\n    return {\r\n      id: String(result.insertId),\r\n      email: userData.email,\r\n      passwordHash: userData.passwordHash,\r\n    };\r\n  },\r\n});\r\n\r\n\r\n---\r\n\r\n## Example with Prisma\r\n\r\n\r\nimport { createAuthKit } from \"@atithnj/jwt-auth-kit\";\r\nimport { prisma } from \"./prisma\";\r\n\r\nconst auth = createAuthKit({\r\n  jwtSecret: process.env.JWT_SECRET!,\r\n\r\n  findUserByEmail: async (email) => {\r\n    return prisma.user.findUnique({\r\n      where: { email },\r\n    });\r\n  },\r\n\r\n  createUser: async (userData) => {\r\n    return prisma.user.create({\r\n      data: userData,\r\n    });\r\n  },\r\n});\r\n\r\n\r\n---\r\n\r\n## Configuration Options\r\n\r\n\r\nconst auth = createAuthKit({\r\n  jwtSecret: \"your-secret-key\",\r\n  expiresIn: \"7d\",\r\n  saltRounds: 10,\r\n  algorithm: \"HS256\",\r\n  findUserByEmail,\r\n  createUser,\r\n  getUserId,\r\n});\r\n\r\n\r\n### `jwtSecret`\r\n\r\nRequired.\r\n\r\nThe secret key used to sign and verify JWT tokens.\r\n\r\njwtSecret: process.env.JWT_SECRET!\r\n\r\nFor production, use a strong secret from environment variables.\r\n\r\nDo not hardcode your JWT secret in production.\r\n\r\n---\r\n\r\n### `expiresIn`\r\n\r\nOptional.\r\n\r\nDefines how long the JWT token is valid.\r\n\r\nDefault: \"7d\"\r\n\r\nExample:\r\nexpiresIn: \"1h\"\r\nCommon values:\r\n\"15m\"\r\n\"1h\"\r\n\"7d\"\r\n\r\nFor production applications, shorter access token expiry such as `\"15m\"` or `\"1h\"` is recommended.\r\n\r\n---\r\n\r\n### `saltRounds`\r\n\r\nOptional.\r\n\r\nDefines the bcrypt cost factor used for password hashing.\r\n\r\nDefault: 10\r\n\r\n\r\nAllowed range: 10 to 15\r\n\r\n\r\nExample: saltRounds: 12\r\n\r\nIf the value is less than `10`, the package throws an error because the hashing strength will be too weak.\r\n\r\nIf the value is greater than `15`, the package throws an error because the cost factor may become too expensive.\r\n\r\n---\r\n\r\n### `algorithm`\r\n\r\nOptional.\r\n\r\nDefines the JWT signing algorithm.\r\n\r\nDefault: \"HS256\"\r\n\r\nSupported algorithms:\r\n\"HS256\"\r\n\"HS384\"\r\n\"HS512\"\r\n\r\n\r\nExample: algorithm: \"HS256\"\r\n\r\nIf an unsupported algorithm is passed, the package throws an error.\r\n\r\n---\r\n\r\n### `findUserByEmail`\r\n\r\nRequired.\r\n\r\nA function provided by your application to find a user by email.\r\n\r\nExample:\r\n\r\nfindUserByEmail: async (email) => {\r\n  return User.findOne({ email });\r\n}\r\n\r\nThis package does not know your database structure, so your app must provide this function.\r\n\r\n---\r\n\r\n### `createUser`\r\n\r\nRequired.\r\n\r\nA function provided by your application to create a new user.\r\n\r\nExample:\r\n\r\ncreateUser: async (userData) => {\r\n  return User.create(userData);\r\n}\r\n\r\nThe package hashes the password first and sends `passwordHash` to this function.\r\n\r\n---\r\n\r\n### `getUserId`\r\n\r\nOptional.\r\n\r\nUsed when your user object has a custom ID field.\r\n\r\nBy default, the package checks:\r\n\r\nuser.id or user._id\r\n\r\nIf your user object uses another field, you can pass `getUserId`.\r\n\r\nExample:\r\n\r\nconst auth = createAuthKit({\r\n  jwtSecret: process.env.JWT_SECRET!,\r\n\r\n  findUserByEmail,\r\n  createUser,\r\n\r\n  getUserId: (user) => user.userId,\r\n});\r\n\r\n---\r\n\r\n## Methods\r\n\r\nThe `createAuthKit()` function returns the following methods:\r\n\r\nauth.register()\r\nauth.login()\r\nauth.verifyToken()\r\nauth.hashPassword()\r\nauth.comparePassword()\r\nauth.generateToken()\r\n\r\n---\r\n\r\n## `register()`\r\n\r\nRegisters a new user.\r\n\r\nconst result = await auth.register({\r\n  name: \"Atith\",\r\n  email: \"atith@gmail.com\",\r\n  password: \"123456\",\r\n});\r\n\r\nInternally, this method:\r\n\r\n1. Checks whether email and password are provided\r\n2. Calls `findUserByEmail()` to check if the user already exists\r\n3. Hashes the password using bcrypt\r\n4. Calls `createUser()` to save the user\r\n5. Generates a JWT token\r\n6. Returns the created user and token\r\n\r\nExample response:\r\n{\r\n  user: {\r\n    id: \"1\",\r\n    name: \"Atith\",\r\n    email: \"atith@gmail.com\"\r\n  },\r\n  token: \"jwt-token\"\r\n}\r\n\r\nThe returned user object does not include `password` or `passwordHash`.\r\n\r\n---\r\n\r\n## `login()`\r\n\r\nLogs in an existing user.\r\n\r\nconst result = await auth.login({\r\n  email: \"atith@gmail.com\",\r\n  password: \"123456\",\r\n});\r\n\r\nInternally, this method:\r\n\r\n1. Checks whether email and password are provided\r\n2. Calls `findUserByEmail()` to find the user\r\n3. Reads the stored password hash from `passwordHash` or `password`\r\n4. Compares the plain password with the stored hash\r\n5. Generates a JWT token\r\n6. Returns the user and token\r\n\r\nExample response:\r\n\r\n\r\n{\r\n  user: {\r\n    id: \"1\",\r\n    name: \"Atith\",\r\n    email: \"atith@gmail.com\"\r\n  },\r\n  token: \"jwt-token\"\r\n}\r\n\r\n\r\nThe returned user does not include `password` or `passwordHash`.\r\n\r\n---\r\n\r\n## `verifyToken()`\r\n\r\nVerifies a JWT token.\r\n\r\nconst decoded = auth.verifyToken(token);\r\n\r\nExample response:\r\n\r\n{\r\n  userId: \"1\",\r\n  email: \"atith@gmail.com\",\r\n  iat: 1777870000,\r\n  exp: 1778474800\r\n}\r\n\r\nIf the token is invalid or expired, this method throws an error.\r\n\r\n---\r\n\r\n## `hashPassword()`\r\n\r\nHashes a plain password.\r\n\r\nconst hash = await auth.hashPassword(\"123456\");\r\n\r\nThis is useful when you want to write your own custom registration logic but still use this package for password hashing.\r\n\r\nExample:\r\n\r\nconst passwordHash = await auth.hashPassword(req.body.password);\r\n\r\nawait User.create({\r\n  email: req.body.email,\r\n  passwordHash,\r\n});\r\n\r\n---\r\n\r\n## `comparePassword()`\r\n\r\nCompares a plain password with a hashed password.\r\n\r\nconst isValid = await auth.comparePassword(\"123456\", user.passwordHash);\r\n\r\nThis is useful when you want to write your own custom login logic but still use this package for password comparison.\r\n\r\n---\r\n\r\n## `generateToken()`\r\n\r\nGenerates a JWT token for a user.\r\n\r\nconst token = auth.generateToken(user);\r\n\r\nThis is useful when you want custom authentication logic but still want to use this package for token generation.\r\n\r\nThe user object must have either:\r\n\r\nid or _id or you must provide a custom `getUserId()` function.\r\n\r\n---\r\n\r\n## Full example of an ExpressJS server:\r\n\r\nimport express from \"express\";\r\nimport { createAuthKit } from \"@atithnj/jwt-auth-kit\";\r\nimport User from \"./models/User\";\r\n\r\nconst app = express();\r\n\r\napp.use(express.json());\r\n\r\nconst auth = createAuthKit({\r\n  jwtSecret: process.env.JWT_SECRET!,\r\n  expiresIn: \"1h\",\r\n  saltRounds: 12,\r\n  algorithm: \"HS256\",\r\n\r\n  findUserByEmail: async (email) => {\r\n    return User.findOne({ email });\r\n  },\r\n\r\n  createUser: async (userData) => {\r\n    return User.create(userData);\r\n  },\r\n});\r\n\r\napp.post(\"/register\", async (req, res) => {\r\n  try {\r\n    const result = await auth.register(req.body);\r\n\r\n    res.status(201).json({\r\n      message: \"User registered successfully\",\r\n      user: result.user,\r\n      token: result.token,\r\n    });\r\n  } catch (error: any) {\r\n    res.status(400).json({\r\n      message: error.message,\r\n    });\r\n  }\r\n});\r\n\r\napp.post(\"/login\", async (req, res) => {\r\n  try {\r\n    const result = await auth.login(req.body);\r\n\r\n    res.status(200).json({\r\n      message: \"User logged in successfully\",\r\n      user: result.user,\r\n      token: result.token,\r\n    });\r\n  } catch (error: any) {\r\n    res.status(401).json({\r\n      message: error.message,\r\n    });\r\n  }\r\n});\r\n\r\napp.get(\"/profile\", async (req, res) => {\r\n  try {\r\n    const authHeader = req.headers.authorization;\r\n\r\n    if (!authHeader) {\r\n      return res.status(401).json({\r\n        message: \"Authorization header missing\",\r\n      });\r\n    }\r\n\r\n    const token = authHeader.replace(\"Bearer \", \"\");\r\n\r\n    const decoded = auth.verifyToken(token);\r\n\r\n    res.status(200).json({\r\n      message: \"Token verified successfully\",\r\n      user: decoded,\r\n    });\r\n  } catch (error: any) {\r\n    res.status(401).json({\r\n      message: error.message,\r\n    });\r\n  }\r\n});\r\n\r\napp.listen(5000, () => {\r\n  console.log(\"Server running on port 5000\");\r\n});\r\n\r\n---\r\n\r\n## Authorization Header Format\r\n\r\nFor protected routes, send the token like this:\r\n\r\nAuthorization: Bearer your-jwt-token\r\n\r\nExample using fetch:\r\n\r\nfetch(\"/profile\", {\r\n  headers: {\r\n    Authorization: `Bearer ${token}`,\r\n  },\r\n});\r\n\r\n---\r\n\r\n## TypeScript Types\r\n\r\nThe package exports the following types:\r\n\r\nAuthUser\r\nAuthTokenPayload\r\nCreateAuthKitOptions\r\nRegisterUserCredentials\r\nLoginUserCredentials\r\nSupportedJwtAlgorithm\r\n\r\nExample:\r\n\r\nimport {\r\n  createAuthKit,\r\n  AuthUser,\r\n  SupportedJwtAlgorithm,\r\n} from \"@atithnj/jwt-auth-kit\";\r\n\r\n\r\n---\r\n\r\n## User Object Shape\r\n\r\nThe package expects the user object to have at least:\r\n\r\n\r\n{\r\n  email: string;\r\n}\r\n\r\n\r\nAnd for token generation, it should have either:\r\n\r\n\r\nid: string;\r\n\r\nor:\r\n\r\n_id: string;\r\n\r\nExample with SQL-style user:\r\n\r\n{\r\n  id: \"1\",\r\n  email: \"test@gmail.com\",\r\n  passwordHash: \"$2a$10$...\"\r\n}\r\n\r\nExample with MongoDB-style user:\r\n\r\n{\r\n  _id: \"65fabc123\",\r\n  email: \"test@gmail.com\",\r\n  passwordHash: \"$2a$10$...\"\r\n}\r\n\r\nIf your user has a custom ID field, use `getUserId`.\r\n\r\n---\r\n\r\n## Error Examples\r\n\r\n### Missing JWT secret\r\n\r\ncreateAuthKit({\r\n  jwtSecret: \"\",\r\n  findUserByEmail,\r\n  createUser,\r\n});\r\n\r\nThrows: JWT secret key is required\r\n\r\n---\r\n\r\n### Weak salt rounds\r\n\r\ncreateAuthKit({\r\n  jwtSecret: \"secret\",\r\n  saltRounds: 8,\r\n  findUserByEmail,\r\n  createUser,\r\n});\r\n\r\n\r\nThrows:\r\n\r\nsaltRounds is too weak. Minimum supported value is 10.\r\n\r\n---\r\n\r\n### Expensive salt rounds\r\n\r\ncreateAuthKit({\r\n  jwtSecret: \"secret\",\r\n  saltRounds: 18,\r\n  findUserByEmail,\r\n  createUser,\r\n});\r\n\r\nThrows:\r\n\r\nsaltRounds cost factor is too expensive. Maximum supported value is 15.\r\n\r\n---\r\n\r\n### Unsupported algorithm\r\n\r\ncreateAuthKit({\r\n  jwtSecret: \"secret\",\r\n  algorithm: \"RS256\" as any,\r\n  findUserByEmail,\r\n  createUser,\r\n});\r\n\r\nThrows:\r\n\r\nUnsupported JWT algorithm \"RS256\". Supported algorithms are: HS256, HS384, HS512.\r\n\r\n---\r\n\r\n## Security Notes\r\n\r\nThis package follows basic authentication security practices:\r\n\r\n* Passwords are hashed before storing\r\n* Plain passwords are never returned\r\n* `password` and `passwordHash` are removed from the returned user object\r\n* JWT tokens are signed using supported HMAC algorithms\r\n* JWT verification checks the expected algorithm\r\n* Salt rounds are restricted to a safe practical range\r\n\r\nFor production usage:\r\n\r\n* Use a strong JWT secret from environment variables\r\n* Do not hardcode secrets\r\n* Use HTTPS\r\n* Use shorter access token expiry such as `\"15m\"` or `\"1h\"`\r\n* Consider implementing refresh tokens separately\r\n* Add rate limiting on login routes\r\n* Add account lockout or suspicious login detection if required\r\n* Validate email and password before passing data to this package\r\n\r\nExample production config:\r\n\r\nconst auth = createAuthKit({\r\n  jwtSecret: process.env.JWT_SECRET!,\r\n  expiresIn: \"1h\",\r\n  saltRounds: 12,\r\n  algorithm: \"HS256\",\r\n  findUserByEmail,\r\n  createUser,\r\n});\r\n\r\n---\r\n\r\n## Summary\r\n\r\n`@atithnj/jwt-auth-kit` is a lightweight authentication helper package for Node.js applications.\r\n\r\nIt helps you avoid rewriting the same authentication logic in every project by providing reusable methods for:\r\n\r\n* user registration\r\n* user login\r\n* password hashing\r\n* password comparison\r\n* JWT generation\r\n* JWT verification\r\n\r\nThe package is flexible, TypeScript-friendly, and works with any database because the database logic is provided by the application using the package.","readmeFilename":"README.md","_rev":"1-1348730247d202accfc29681a23d8ca5"}