{"id":23045301,"url":"https://github.com/fronterior/next-auth-firestore-adapter-example","last_synced_at":"2025-08-14T23:31:42.776Z","repository":{"id":44988513,"uuid":"487167893","full_name":"fronterior/next-auth-firestore-adapter-example","owner":"fronterior","description":"firestore adapter example in next-auth","archived":false,"fork":false,"pushed_at":"2022-07-30T14:43:15.000Z","size":199,"stargazers_count":24,"open_issues_count":1,"forks_count":5,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-03T03:11:13.196Z","etag":null,"topics":["firebase","firebase-auth","firebase-authentication","firestore","next-auth","next-auth-provider","nextjs","todomvc"],"latest_commit_sha":null,"homepage":"https://next-auth-firestore-todo-mvc.vercel.app","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/fronterior.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-04-30T03:01:43.000Z","updated_at":"2025-03-05T10:24:53.000Z","dependencies_parsed_at":"2022-07-19T18:03:39.219Z","dependency_job_id":null,"html_url":"https://github.com/fronterior/next-auth-firestore-adapter-example","commit_stats":null,"previous_names":["fronterior/next-auth-firestore-adapter-example","lowfront/next-auth-firestore-adapter-example"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/fronterior/next-auth-firestore-adapter-example","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fronterior%2Fnext-auth-firestore-adapter-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fronterior%2Fnext-auth-firestore-adapter-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fronterior%2Fnext-auth-firestore-adapter-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fronterior%2Fnext-auth-firestore-adapter-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fronterior","download_url":"https://codeload.github.com/fronterior/next-auth-firestore-adapter-example/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fronterior%2Fnext-auth-firestore-adapter-example/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270499985,"owners_count":24595149,"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","status":"online","status_checked_at":"2025-08-14T02:00:10.309Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["firebase","firebase-auth","firebase-authentication","firestore","next-auth","next-auth-provider","nextjs","todomvc"],"created_at":"2024-12-15T21:19:31.590Z","updated_at":"2025-08-14T23:31:42.479Z","avatar_url":"https://github.com/fronterior.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Firebase adepter auth process with custom token example in Next Auth\n\nExample of a firebase adapter that works with firebase authentication. A firebase is a database that has rules functionality for use by both servers and clients. If use firebase on a client, if rule is not set, all data accessible to the client is accessible to anyone who can read the code. When storing user, account, and session data in the next-adapter in the firebase, if rule is not set, all data will be public. This example uses the method of sign in using customToken to protect the data in the firebase at the frontend. After sign in through next-auth's provider, allow api endpoint that issues customToken of the firebase service on the server. When working with the firebase database at the frontend, if the client is not currently sign in as customToken, the user receives a token from the customToken api endpoint and then sign in and proceeds with the database operation. This example was created as a fireestore target, but can also use the same method for the firebase realtime database if necessary.\n\n### Database Structure\n```\nfirestore root\n├── _next_auth_firebase_adapter_ [collection]\n│  └── store [document]\n│     ├── account [collection] # account scheme from next-auth\n│     ├── session [collection] # session scheme from next-auth\n│     ├── user [collection] # user scheme from next-auth\n│     └── customToken [collection]\n│        └── \u003csession token\u003e [document] # same as session token in next-auth and when issuing custom token, it is included in additional claims.\n│           ├── exires [field]\n│           └── token [field]\n└── store [collection]\n   └── \u003cuser email\u003e [document]\n      └── store [collection]\n         └── \u003cuser data uid\u003e [document]\n            ├── checked [field]\n            └── label [field]\n```\n\n1. Go to [firebase console](https://console.firebase.google.com/project) and select your project. \n\n2. In `Project settings \u003e Service accounts \u003e Firebase Admin SDK`, for server, click \"Generate new private key\" and download \"Generate Key\" and write it in the `FIREBASE_ADMIN_CONFIG_` key of `.env.local`.\n\n3. In `Project settings \u003e General`, Click \"Add app\" at the bottom of the page, add a web app for frontend, and record the contents in the `.env.local` file.\n\n4. Add a new rule as follow in `Firestore Database \u003e Rules`\n```\nrules_version = '2';\nservice cloud.firestore {\n  match /databases/{database}/documents {\n    match /{document=**} {\n      allow read, write: if false;\n    }\n    match /store/{userId}/{document=**} {\n    \tallow read, write: if request.auth.token.id == userId;\n// \u0026\u0026 exists(/databases/$(database)/documents/_next_auth_firebase_adapter_/store/customToken/$(request.auth.token.sessionToken)); // To enhance security, after sign out, the issued custom token is deactivated and has a session method security level, but database read costs are added for each task.\n    }\n  }\n}\n```\n\n5. Add adapter to `pages/api/auth/[...nextauth].ts`.\n```ts\nconst app = initializeApp(firebaseConfig);\nconst db = getFirestore(app);\n\nexport default NextAuth({\n  providers: [\n    GoogleProvider({\n      clientId: process.env.GOOGLE_ID,\n      clientSecret: process.env.GOOGLE_SECRET,\n    }),\n  ],\n  adapter: FirebaseAdapter(db),\n});\n```\n\n6. Add custom token endpoint to `pages/api/auth/token.ts`.\n```ts\nexport type CustomToken = {\n  token: string;\n  expires: string; // date\n};\n\nexport async function getCustomToken(sessionToken: string) {\n  const tokenDocRef = db.collection('_next_auth_firebase_adapter_').doc('store').collection('customToken').doc(sessionToken);\n  const tokenDoc = await tokenDocRef.get();\n  if (!tokenDoc.exists) return;\n  const { token, expires } = tokenDoc.data() as CustomToken;\n  if (Date.now() \u003e new Date(expires).getTime()) return;\n  return token;\n}\n\nexport async function updateCustomToken(sessionToken: string, token: string) {\n  const tokenDocRef = db.collection('_next_auth_firebase_adapter_').doc('store').collection('customToken').doc(sessionToken);\n\n  await tokenDocRef.set({\n    token,\n    expires: Date.now() + 60 * 60 * 1000,\n  });\n\n  return token;\n}\n\nexport function getSessionToken(req: NextApiRequest) {\n  return req.cookies['__Secure-next-auth.session-token'] ?? req.cookies['next-auth.session-token'];\n}\n\nasync function handler(req: NextApiRequest, res: NextApiResponse) {\n  if (req.method !== 'GET') return res.status(403).json(false);\n  const session = await getSession({ req }) as Session;\n  if (!session) return res.status(403).json(false);\n  const sessionToken = getSessionToken(req);\n  const { user } = session as unknown as {\n    user: NonNullable\u003cSession['user']\u003e;\n  };\n  const email = user.email as string;\n  let token = await getCustomToken(sessionToken);\n  if (token) return res.json(token);\n\n  token = await admin\n    .auth()\n    .createCustomToken(email, Object.assign({}, additionalClaims?.(session), { sessionToken }));\n\n  await updateCustomToken(sessionToken, token);\n\n  return res.json(token);\n};\n```\n\n6. Run `npm run dev`\n\nNow use your firebase data in the client, or even if the firebaseConfig is exposed, the data in the next-auth is protected private. If an commented rule is added, customToken issued after sign out is not available.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffronterior%2Fnext-auth-firestore-adapter-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffronterior%2Fnext-auth-firestore-adapter-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffronterior%2Fnext-auth-firestore-adapter-example/lists"}