{"id":16755460,"url":"https://github.com/paulsmithkc/express-auth","last_synced_at":"2026-02-16T12:32:32.224Z","repository":{"id":77274347,"uuid":"421859470","full_name":"paulsmithkc/express-auth","owner":"paulsmithkc","description":"Collection of authentication and authorization middleware functions for Express apps.","archived":false,"fork":false,"pushed_at":"2022-06-10T17:12:55.000Z","size":81,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-24T14:39:26.498Z","etag":null,"topics":["auth","authentication","authorization","expressjs","nodejs"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/paulsmithkc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2021-10-27T14:50:41.000Z","updated_at":"2024-08-31T14:44:41.000Z","dependencies_parsed_at":null,"dependency_job_id":"a8567a07-0542-4515-9c20-4054afb5dccc","html_url":"https://github.com/paulsmithkc/express-auth","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paulsmithkc%2Fexpress-auth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paulsmithkc%2Fexpress-auth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paulsmithkc%2Fexpress-auth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paulsmithkc%2Fexpress-auth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/paulsmithkc","download_url":"https://codeload.github.com/paulsmithkc/express-auth/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247838443,"owners_count":21004580,"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":["auth","authentication","authorization","expressjs","nodejs"],"created_at":"2024-10-13T03:22:36.244Z","updated_at":"2025-10-07T23:10:41.855Z","avatar_url":"https://github.com/paulsmithkc.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# express-auth\n\nCollection of authentication and authorization middleware functions.\n\n## Install\n\nInstall this package.\n\n```bash\nnpm install @merlin4/express-auth\n```\n\nInstall peer dependencies, if needed.\n\n```bash\nnpm install express cookie-parser jsonwebtoken config\n```\n\n## Table of Contents\n\n- Middleware\n  - [authMiddleware](#authmiddleware)\n    - [installation](#installation)\n    - [configuration](#configuration)\n    - [req.auth](#reqauth)\n  - [isLoggedIn](#isloggedin-middleware)\n  - [hasAnyRole](#hasanyrole-middleware)\n  - [hasRole](#hasrole-middleware)\n  - [hasPermission](#haspermission-middleware)\n- Utility Functions\n  - [fetchRoles](#fetchroles-utility-function)\n  - [mergePermissions](#mergepermissions-utility-function)\n\n## authMiddleware\n\n### installation\n\nThe authentication middleware will parse a Json Web Token (JWT) provided by the client,\nvia either an \"Authorization\" header with type \"Bearer\", or optionally via a cookie.\n\nInstall this middleware in your application entry point (index.js/server.js/app.js):\n\n```js\nconst { authMiddleware } = require('@merlin4/express-auth');\napp.use(\n  authMiddleware('my super secret key', 'authToken', {\n    httpOnly: true,\n    maxAge: 1000 * 60 * 15,\n  })\n);\n```\n\n### configuration\n\nThe constructor for this middleware accepts 3 arguments:\n\n1. **secret** the secret used to sign the JWT token (required)\n2. **cookieName** the name of the cookie that holds the token (optional)\n3. **cookieOptions** the options to use for refreshing the token (optional)\n\nThe **secret** is required to verify the token. This middleware will throw an exception on startup, if it not provided.\n\nThe **cookieName** will be used to parse the token from a cookie, when no \"Authorization\" header is provided. Note that you will need to install a cookie parser beforehand to parse the cookies. (Example shown below.)\n\n```js\nconst cookieParser = require('cookie-parser');\nconst { authMiddleware } = require('@merlin4/express-auth');\napp.use(cookieParser());\napp.use(authMiddleware('my super secret key', 'authToken'));\n```\n\nIf **cookieName** is not provided, then this middleware will ignore cookies and a cookie parser is not required.\n\nIf **cookieOptions** are also provided, then the auth cookie will be refreshed on every request, using the provided options. For security it is recommended that you provide the following options:\n\n- `maxAge`, will set an expiration time in milliseconds for the auth cookie.\n- `httpOnly: true`, will prevent the cookie from being read by front-end javascript code.\n- `secure: true`, will prevent the cookie from being sent over HTTP.\n\nSee the [res.cookie()](https://expressjs.com/en/4x/api.html#res.cookie) for a full list of the available options.\n\nIf **cookieName** or **cookieOptions** are not provided, then the cookie will not be automatically refreshed.\n\nWe recommend using the [config](https://www.npmjs.com/package/config) package to help set these options.\n\n```js\nconst config = require('config');\nconst cookieParser = require('cookie-parser');\nconst { authMiddleware } = require('@merlin4/express-auth');\napp.use(cookieParser());\napp.use(\n  authMiddleware(\n    config.get('auth.secret'), \n    config.get('auth.cookie.name'), \n    {\n      maxAge: parseInt(config.get('auth.cookie.maxAge')),\n      httpOnly: config.get('auth.cookie.httpOnly'),\n      secure: config.get('auth.cookie.secure'),\n    }\n  )\n);\n```\n\n### req.auth\n\nOnce the middleware is installed and configured in the application. A new field will be accessible on the **Request** object to your other routes.\n\n```js\napp.get('/api/auth/me', (req, res) =\u003e {\n  const auth = req.auth;\n  // If a valid auth token is provided, then req.auth will be the token's payload.\n  // Otherwise req.auth, will be be undefined.\n  // ...\n});\n```\n\n## isLoggedIn middleware\n\n*Requires **authMiddleware** to be installed first.*\n\nThe **isLoggedIn** middleware checks that the user is logged in. It will send a 401 error if the user is not authenticated.\n\n**Example:** Allow **authenticated users** to access the route.\n```js\nconst { isLoggedIn } = require('@merlin4/express-auth');\n\napp.get('/api/auth/me', isLoggedIn(), (req, res) =\u003e {\n  const auth = req.auth;\n  // ...\n});\n```\n\n## hasAnyRole middleware\n\n*Requires **authMiddleware** to be installed first.*\n\nThe **hasAnyRole** middleware checks that the user is logged in and has at least one role. It will send a 401 error if the user is not authenticated. It will send a 403 error if the user has no roles.\n\n**Example:** Allow users with **any role** to access the route.\n```js\nconst { hasAnyRole } = require('@merlin4/express-auth');\n\napp.get('/api/auth/me', hasAnyRole(), (req, res) =\u003e {\n  const auth = req.auth;\n  const authRole = req.auth.role;\n  // ...\n});\n```\n\n## hasRole middleware\n\n*Requires **authMiddleware** to be installed first.*\n\nThe **hasRole** middleware checks that the user is logged in and has one of the allowed roles. It will send a 401 error if the user is not authenticated. It will send a 403 error if the user does not have one of the allowed roles.\n\n**Example:** Allow **admins** to access this route.\n```js\nconst { hasRole } = require('@merlin4/express-auth');\n\napp.get('/api/admin', hasRole('admin'), (req, res) =\u003e {\n  const auth = req.auth;\n  const authRole = req.auth.role;\n  // ...\n});\n```\n\n**Example:** Allow users with either the **admin or moderator** role to access this route.\n```js\nconst { hasRole } = require('@merlin4/express-auth');\n\napp.get('/api/mod', hasRole('admin', 'moderator'), (req, res) =\u003e {\n  const auth = req.auth;\n  const authRole = req.auth.role;\n  // ...\n});\n```\n\n## hasPermission middleware\n\n*Requires **authMiddleware** to be installed first.*\n\nThe **hasPermission** middleware checks the user has at least one of the listed permissions. It will send a 401 error if the user is not authenticated. It will send a 403 error if the user does not have one of the listed permissions.\n\n**Example:** Allow users with the **manageUsers** permission to access this route.\n```js\nconst { hasRole } = require('@merlin4/express-auth');\n\napp.get('/api/user/list', hasPermission('manageUsers'), (req, res) =\u003e {\n  const auth = req.auth;\n  const permissions = req.auth.permissions;\n  // ...\n});\n```\n\n**Example:** Allow users with either the **viewUsers or editUsers** permission to access this route.\n```js\nconst { hasRole } = require('@merlin4/express-auth');\n\napp.get('/api/user/list', hasPermission('viewUsers', 'editUsers'), (req, res) =\u003e {\n  const auth = req.auth;\n  const permissions = req.auth.permissions;\n  // ...\n});\n```\n\n## fetchRoles utility function\n\nThe **fetchRoles** function will read the assigned roles from a user document and fetch all of roles from a data source, in parallel.\n\n**Example:** Fetch the user from the database, and then fetch all of the assigned roles.\n```js\nconst { fetchRoles } = require('@merlin4/express-auth');\nconst user = await db.findUserById(userId);\nconst roles = await fetchRoles(user, role =\u003e db.findRoleByName(role));\n```\n\nThis function assumes that the user has a **\"role\"** field which specifies their role(s). \nThe user object may be in any of the following states:\n\nUser has **no role:**\n```js\n{ ...userData, role: null }\n```\n\nUser has **a role:**\n```js\n{ ...userData, role: \"admin\" }\n```\nUser has **an array of roles:**\n```js\n{ ...userData, role: [\"admin\", \"manager\"] }\n```\n\nUser has **a map of roles:**\n```js\n{ ...userData, role: { admin: true, manager: true, editor: false } }\n```\n\nAll of the above data structures are supported by **fetchRoles**\n\n## mergePermissions utility function\n\nThe **mergePermissions** function will merge the permissions of the user and their assigned roles into a combined permissions map.\n\n**Example:** Fetch the user from the database, fetch all of the assigned roles, and then merge all of the permission maps.\n```js\nconst { fetchRoles, mergePermissions } = require('@merlin4/express-auth');\nconst user = await db.findUserById(userId);\nconst roles = await fetchRoles(user, role =\u003e db.findRoleByName(role));\nconst permissions = mergePermissions(user, roles);\n```\n\nThis will read any user specific permissions from the user document, such as:\n\n```js\n{ ...userData, permissions: { canLogin: true } }\n```\n\nIt will also read any permissions granted by a role, such as:\n```js\n[\n  { name: 'Technical Manager', permissions: { manageUsers: true } },\n  { name: 'Product Manager', permissions: { manageProducts: true } }\n}\n```\n\nThe combined permissions map would be as follows, for the data above:\n```js\n{\n  canLogin: true,\n  manageUsers: true,\n  manageProducts: true\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaulsmithkc%2Fexpress-auth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpaulsmithkc%2Fexpress-auth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaulsmithkc%2Fexpress-auth/lists"}