{"id":28241839,"url":"https://github.com/significa/significa-auth-next","last_synced_at":"2026-04-28T18:06:54.659Z","repository":{"id":57940016,"uuid":"527625875","full_name":"significa/significa-auth-next","owner":"significa","description":"Auth-related functions to handle access and refresh tokens in NextJS projects.","archived":false,"fork":false,"pushed_at":"2023-04-13T09:27:54.000Z","size":266,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-08-08T22:26:23.059Z","etag":null,"topics":["nextjs"],"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/significa.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-08-22T15:34:33.000Z","updated_at":"2022-12-07T15:44:49.000Z","dependencies_parsed_at":"2023-01-29T23:01:11.542Z","dependency_job_id":null,"html_url":"https://github.com/significa/significa-auth-next","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/significa/significa-auth-next","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/significa%2Fsignifica-auth-next","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/significa%2Fsignifica-auth-next/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/significa%2Fsignifica-auth-next/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/significa%2Fsignifica-auth-next/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/significa","download_url":"https://codeload.github.com/significa/significa-auth-next/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/significa%2Fsignifica-auth-next/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32392392,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-28T14:34:11.604Z","status":"ssl_error","status_checked_at":"2026-04-28T14:32:37.009Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["nextjs"],"created_at":"2025-05-19T05:08:54.004Z","updated_at":"2026-04-28T18:06:54.653Z","avatar_url":"https://github.com/significa.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Significa's auth methods to handle JWT sessions on NextJS projects\n\nThis is work in progress and only suitable for internal use.\n\n## Description\n\nThis package solves JWT-based authentication by saving the refresh token in an http-only cookie (accessible only server-side) and the access-token + a session indicator with the expiration date in client-acessible cookies.\n\n- server-side api routes that handles all session cookies\n- server-side route restrictions\n- server-side token refresh\n- client-side token refresh (interval + window focus)\n- client-side access token access (e.g.: for client-side API calls)\n\n## Using the package\n\n1. Generate a new github PAT (Classic Personal Access Token).\n   Grant `read:packages` _Download packages from GitHub Package Registry_.\n\n2. Run `npm login --scope=@significa --registry=https://npm.pkg.github.com`.\n   In the interactive CLI set your GitHub handle as the username and the newly generated PAT as the password (email can be anything).\n\n3. `npm install @significa/auth-next`\n\nMore info: [Working with the GitHub npm registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry).\n\n## Configuration\n\nCreate a `lib/auth.ts` file to create your auth's config.\n\nThis package exposes a main `Auth` class that should be initialized with your project's configuration:\n\n```tsx\n// lib/auth.ts\n\nimport { Auth } from '@significa/auth-next'\n\nimport { API_URL } from 'common/constants'\n\nexport const auth = new Auth({\n  accessTokenKey: 'project_token',\n  sessionIndicatorKey: 'project_session',\n  refreshTokenKey: 'project_refresh_token',\n  /* configuration for the handler in Next's API Routes */\n  serverHandlers: {\n    login: {\n      fetch: (email, password) =\u003e {\n        return fetch(`${API_URL}/auth/login`, {\n          method: 'POST',\n          headers: {\n            'Content-Type': 'application/json',\n          },\n          body: JSON.stringify({\n            email,\n            password,\n          }),\n        })\n      },\n      parseResponse: async (res) =\u003e {\n        const { data } = await res.json()\n\n        return {\n          accessToken: data.access_token,\n          expires: data.expires,\n          refreshToken: data.refresh_token,\n        }\n      },\n    },\n    refresh: {\n      fetch: async (refreshToken: string) =\u003e {\n        return fetch(`${API_URL}/auth/refresh`, {\n          method: 'POST',\n          headers: {\n            'Content-Type': 'application/json',\n          },\n          body: JSON.stringify({ refresh_token: refreshToken }),\n        })\n      },\n      parseResponse: async (res) =\u003e {\n        const { data } = await res.json()\n\n        return {\n          accessToken: data.access_token,\n          expires: data.expires,\n          refreshToken: data.refresh_token,\n        }\n      },\n    },\n    logout: {\n      fetch: async (refreshToken: string) =\u003e {\n        return fetch(`${API_URL}/auth/logout`, {\n          method: 'POST',\n          headers: {\n            'Content-Type': 'application/json',\n          },\n          body: JSON.stringify({ refresh_token: refreshToken }),\n        })\n      },\n    },\n  },\n})\n```\n\nIf you're using [Directus](https://directus.io/), you can use `createDirectusHandlers` instead:\n\n```tsx\n// lib/auth.ts\n\nimport { Auth, createDirectusHandlers } from '@significa/auth-next'\n\nimport { API_URL } from 'common/constants'\n\nexport const auth = new Auth({\n  accessTokenKey: 'project_token',\n  sessionIndicatorKey: 'project_session',\n  refreshTokenKey: 'project_refresh_token',\n  serverHandlers: createDirectusHandlers({\n    url: API_URL,\n  }),\n})\n```\n\nFinally, you can create some aliases for page restrictions:\n\n```tsx\n// still in lib/auth.ts\n\nexport const withRestriction = auth.restrictions.withRestriction\nexport const withSessionRefresh = auth.restrictions.withSessionRefresh\nexport const withGuestRestriction = withRestriction.bind(null, (isAuthed) =\u003e\n  isAuthed ? '/app' : false\n)\nexport const withAuthRestriction = withRestriction.bind(null, (isAuthed) =\u003e\n  isAuthed ? false : '/login'\n)\n```\n\n## Use\n\n### 1. Create API Routes\n\nCreate a `pages/api/auth/[path].ts` file.\n\n_If you passed `basePath` in your `serverHandlers` config, make sure you create the file in the appropriate path_\n\n```ts\nimport { auth } from 'lib/auth'\n\nexport default auth.server.handler\n```\n\n### 2. Login / Logout\n\n- To login, just do a POST request to `auth.server.paths.login`.\n- To logout, do a GET request to `auth.server.paths.logout`.\n\n#### Example `useLogin` and `useLogout` hooks\n\nYou can create some hooks to centralize all the login/logout logic:\n\n```tsx\n// useLogin.tsx\n\nimport { useRouter } from 'next/router'\nimport { useState } from 'react'\n\nimport { auth } from 'lib/auth'\n\nexport const useLogin = ({\n  onSuccess,\n  onError,\n}: {\n  onSuccess?: () =\u003e void\n  onError?: () =\u003e void\n} = {}) =\u003e {\n  const { push, query } = useRouter()\n\n  const [loading, setLoading] = useState(false)\n  const [error, setError] = useState(false)\n\n  const login = async ({\n    email,\n    password,\n  }: {\n    email: string\n    password: string\n  }) =\u003e {\n    setLoading(true)\n\n    try {\n      const res = await fetch(auth.server.paths.login, {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n        },\n        body: JSON.stringify({ email, password }),\n      })\n\n      if (!res.ok) throw new Error()\n\n      if (typeof onSuccess === 'function') {\n        onSuccess()\n      } else {\n        // push to app by default\n        push(typeof query.returnTo === 'string' ? query.returnTo : '/app')\n      }\n    } catch (error) {\n      setError(true)\n      onError?.()\n    } finally {\n      setLoading(false)\n    }\n  }\n\n  const resetError = () =\u003e {\n    if (error) setError(false)\n  }\n\n  return { login, loading, error, resetError }\n}\n```\n\n```tsx\n// useLogout.tsx\n\nimport { useRouter } from 'next/router'\nimport { useState } from 'react'\n\nimport { auth } from 'lib/auth'\n\nexport const useLogout = () =\u003e {\n  const { push } = useRouter()\n\n  const [loading, setLoading] = useState(false)\n\n  const logout = async () =\u003e {\n    setLoading(true)\n\n    try {\n      const res = await fetch(auth.server.paths.logout)\n\n      if (!res.ok) throw new Error()\n    } catch (error) {\n      // at least clear client-side cookies\n      auth.client.clearAccessToken()\n      auth.client.clearSessionIndicator()\n    } finally {\n      // redirect anyway\n      push('/')\n      setLoading(false)\n    }\n  }\n\n  return { logout, loading }\n}\n```\n\n### 3. Page restrictions / Session refresh\n\nFinally, you can use the aliases in 'lib/auth' to lock routes:\n\n```tsx\n// pages/app/index.tsx\nimport { withAuthRestriction } from 'lib/auth'\n\nconst AppHomepage = () =\u003e \u003cdiv\u003eHello from App\u003c/div\u003e\n\nexport const getServerSideProps = withAuthRestriction()\n\nexport default AppHomepage\n```\n\n`withRestriction` already refreshes the session if necessary but, if you need, you can trigger a session refresh server-side by using `withSessionRefresh`:\n\n```tsx\n// pages/index.tsx\nimport { withSessionRefresh } from 'lib/auth'\n...\n\nexport const getServerSideProps = withSessionRefresh()\n```\n\n## `useRefreshSession`\n\nThis package also exports a `useRefreshSession` hook that can be used to make client-side refreshes at a certain interval or whenever the window gains focus:\n\n```tsx\n// _app.tsx\n\nimport { useRefreshSession, getDateDistance } from '@significa/auth-next'\n\nimport { auth } from 'lib/auth'\n\nfunction MyApp({ Component, pageProps }: AppProps) {\n  useRefreshSession({\n    refreshPath: auth.server.paths.refresh,\n    shouldRefresh: () =\u003e {\n      const expiryDate = auth.client.getSessionIndicator()\n\n      if (!expiryDate) return false\n\n      return getDateDistance(new Date(expiryDate)) \u003c= 30\n    },\n    onRefresh: () =\u003e {\n      queryClient.invalidateQueries(useMeQuery.getKey())\n    },\n  })\n  })\n\n  return ...\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsignifica%2Fsignifica-auth-next","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsignifica%2Fsignifica-auth-next","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsignifica%2Fsignifica-auth-next/lists"}