From 6e5e7ab22f29ef6adf9652cfd267af353270cf37 Mon Sep 17 00:00:00 2001 From: Arjun Patel Date: Fri, 14 Jan 2022 00:07:12 -0800 Subject: [PATCH] cleaning things up and getting the cookies way somewhat working but it's just a pain...keep it client side maybe --- contexts/authContext.js | 17 +++- ... nirvana-for-business-firebase-adminsdk.js | 4 +- package-lock.json | 71 +++++++++++++++++ package.json | 2 + pages/api/auth/validateToken.tsx | 19 +++-- pages/teams/index.tsx | 78 ++++++++++++++----- services/firebaseService.js | 16 ++++ 7 files changed, 174 insertions(+), 33 deletions(-) rename nirvana-for-business-firebase-adminsdk.json => nirvana-for-business-firebase-adminsdk.js (97%) diff --git a/contexts/authContext.js b/contexts/authContext.js index 9217983..405cf72 100644 --- a/contexts/authContext.js +++ b/contexts/authContext.js @@ -1,6 +1,7 @@ import { getAuth, GoogleAuthProvider, onAuthStateChanged, signInWithPopup, signOut, User } from "firebase/auth"; import React, { useContext, useEffect, useState } from "react"; import firebase from '../services/firebaseService' +import nookies from 'nookies' const AuthContext = React.createContext(null); const googleProvider = new GoogleAuthProvider() @@ -12,12 +13,20 @@ export function AuthProvider({ children }) { const [loading, setLoading] = useState(true) useEffect(() => { - const unsubscribe = onAuthStateChanged(auth, user => { + const unsubscribe = onAuthStateChanged(auth, async (user) => { console.log('change in auth') + if (user) { + setCurrUser(user) - // will be null or the firebase logged in user - setCurrUser(user) - + // set the token in the cookies for ssr verification + const token = await user.getIdToken(); + nookies.set(undefined, 'token', token, { path: '/' }); + } else { + nookies.set(undefined, 'token', '', { path: '/' }); + + setCurrUser(null) + } + setLoading(false) }); diff --git a/nirvana-for-business-firebase-adminsdk.json b/nirvana-for-business-firebase-adminsdk.js similarity index 97% rename from nirvana-for-business-firebase-adminsdk.json rename to nirvana-for-business-firebase-adminsdk.js index 12c8f4a..55f29e9 100644 --- a/nirvana-for-business-firebase-adminsdk.json +++ b/nirvana-for-business-firebase-adminsdk.js @@ -1,4 +1,4 @@ -{ +const serviceAccount = { "type": "service_account", "project_id": "nirvana-for-business", "private_key_id": "8720d0ab82c42545bb151e3e394d03d81acdb208", @@ -10,3 +10,5 @@ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-e05xh%40nirvana-for-business.iam.gserviceaccount.com" } + +export default serviceAccount \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index e5edcd5..dbdaa49 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,9 @@ "antd": "^4.18.3", "firebase": "^9.6.2", "firebase-admin": "^10.0.1", + "isomorphic-unfetch": "^3.1.0", "next": "12.0.7", + "nookies": "^2.5.2", "react": "17.0.2", "react-dom": "17.0.2", "react-icons": "^4.3.1" @@ -3289,6 +3291,14 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/copy-to-clipboard": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz", @@ -5672,6 +5682,15 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "node_modules/isomorphic-unfetch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz", + "integrity": "sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==", + "dependencies": { + "node-fetch": "^2.6.1", + "unfetch": "^4.2.0" + } + }, "node_modules/jest-worker": { "version": "27.0.0-next.5", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.0.0-next.5.tgz", @@ -6473,6 +6492,15 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.77.tgz", "integrity": "sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==" }, + "node_modules/nookies": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/nookies/-/nookies-2.5.2.tgz", + "integrity": "sha512-x0TRSaosAEonNKyCrShoUaJ5rrT5KHRNZ5DwPCuizjgrnkpE5DRf3VL7AyyQin4htict92X1EQ7ejDbaHDVdYA==", + "dependencies": { + "cookie": "^0.4.1", + "set-cookie-parser": "^2.4.6" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -8025,6 +8053,11 @@ "semver": "bin/semver.js" } }, + "node_modules/set-cookie-parser": { + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz", + "integrity": "sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg==" + }, "node_modules/set-immediate-shim": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", @@ -8741,6 +8774,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/unfetch": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz", + "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==" + }, "node_modules/unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -11717,6 +11755,11 @@ } } }, + "cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + }, "copy-to-clipboard": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz", @@ -13524,6 +13567,15 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "isomorphic-unfetch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz", + "integrity": "sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==", + "requires": { + "node-fetch": "^2.6.1", + "unfetch": "^4.2.0" + } + }, "jest-worker": { "version": "27.0.0-next.5", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.0.0-next.5.tgz", @@ -14185,6 +14237,15 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.77.tgz", "integrity": "sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==" }, + "nookies": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/nookies/-/nookies-2.5.2.tgz", + "integrity": "sha512-x0TRSaosAEonNKyCrShoUaJ5rrT5KHRNZ5DwPCuizjgrnkpE5DRf3VL7AyyQin4htict92X1EQ7ejDbaHDVdYA==", + "requires": { + "cookie": "^0.4.1", + "set-cookie-parser": "^2.4.6" + } + }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -15290,6 +15351,11 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" }, + "set-cookie-parser": { + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz", + "integrity": "sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg==" + }, "set-immediate-shim": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", @@ -15851,6 +15917,11 @@ "which-boxed-primitive": "^1.0.2" } }, + "unfetch": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz", + "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==" + }, "unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", diff --git a/package.json b/package.json index e60ae48..b3c2edd 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,9 @@ "antd": "^4.18.3", "firebase": "^9.6.2", "firebase-admin": "^10.0.1", + "isomorphic-unfetch": "^3.1.0", "next": "12.0.7", + "nookies": "^2.5.2", "react": "17.0.2", "react-dom": "17.0.2", "react-icons": "^4.3.1" diff --git a/pages/api/auth/validateToken.tsx b/pages/api/auth/validateToken.tsx index 74c12f8..b812d9d 100644 --- a/pages/api/auth/validateToken.tsx +++ b/pages/api/auth/validateToken.tsx @@ -1,11 +1,12 @@ -import { credential } from 'firebase-admin'; -import { initializeApp } from 'firebase-admin/app'; +import fbAdm, { credential } from 'firebase-admin'; +import firebaseAdmin, { App } from 'firebase-admin/app'; + import { NextApiRequest, NextApiResponse } from 'next'; -import serviceAccount from '../../../nirvana-for-business-firebase-adminsdk.json' +import serviceAccount from '../../../nirvana-for-business-firebase-adminsdk' -initializeApp({ +const adminApp = firebaseAdmin.initializeApp({ credential: credential.cert({ privateKey: serviceAccount.private_key, clientEmail: serviceAccount.client_email, @@ -13,8 +14,10 @@ initializeApp({ }) }); -export default validateToken = async (req: NextApiRequest, res: NextApiResponse) => { + +export default async function(req: NextApiRequest, res: NextApiResponse) { console.log('Validating token...'); + try { const { token } = JSON.parse(req.headers.authorization || '{}'); if (!token) { @@ -23,8 +26,10 @@ export default validateToken = async (req: NextApiRequest, res: NextApiResponse) message: 'Auth token missing.' }); } - const result = await validate(token); - return res.status(200).send(result); + + const verifiedToken = fbAdm.auth().verifyIdToken(token) + + return res.status(200).send(verifiedToken); } catch (err) { return res.status(err.code).send({ errorCode: err.code, diff --git a/pages/teams/index.tsx b/pages/teams/index.tsx index 3c5d612..f8df2cc 100644 --- a/pages/teams/index.tsx +++ b/pages/teams/index.tsx @@ -4,6 +4,9 @@ import { useEffect } from "react" import UserService from '../../services/userService' import { User } from "../../models/user" import { GetServerSidePropsContext } from "next" +import nookies from 'nookies' +import firebaseAdmin from 'firebase-admin' +import unfetch from 'isomorphic-unfetch' /** * figure out where to take the user based on everything @@ -11,16 +14,30 @@ import { GetServerSidePropsContext } from "next" function RouteHandler({ user }) { const { currUser, logOut } = useAuth() const router = useRouter() + const userService: UserService = new UserService() useEffect(() => { - // if not authenticated, take user to the login - if (!currUser) { - console.log('not authenticated...routing from dashboard to teams home') - router.push('/teams/login') - } - - // if user has no profile, then go to create profile + (async function() { + try { + // if not authenticated, take user to the login + if (!currUser) { + console.log('not authenticated...routing from dashboard to teams home') + router.push('/teams/login') + } + + // get user + const user: User | null = await userService.getUser(currUser.uid) + console.log(user) + // if user has no profile, then go to create profile + if (!user || !user.firstName || !user.lastName || !user.nickName) { + + } + } catch(error) { + console.log(error) + router.push('/teams/login') + } + })(); }, [currUser]) return ( @@ -28,24 +45,43 @@ function RouteHandler({ user }) { ) } - export async function getServerSideProps(context: GetServerSidePropsContext) { - // get user data - const userService: UserService = new UserService() + // const cookies = nookies.get(context); - var user: User | null = null + // var user: User | null = null - try { - user = await userService.getUser("asdf") - } catch(error) { - console.log(error) - } + // if (cookies.token) { + // try { + // const headers: HeadersInit = { + // 'Content-Type': 'application/json', + // Authorization: JSON.stringify({ token: cookies.token }) + // }; + // const result = await unfetch('/api/auth/validateToken', { headers }); + // console.log(result) - // Pass data to the page via props - return { props: { - user - } - } + // // get user data + // const userService: UserService = new UserService() + + // // the user is authenticated! + + // // FETCH STUFF HERE!! 🚀 + + // // user = await userService.getUser("asdf") + // } catch (e) { + // // let exceptions fail silently + // // could be invalid token, just let client-side deal with that + + // console.log(e) + // } + // } + + // // Pass data to the page via props + // return { props: { + // user + // } + // } + + return { props: { }} } export default RouteHandler diff --git a/services/firebaseService.js b/services/firebaseService.js index 2cabff9..af290dd 100644 --- a/services/firebaseService.js +++ b/services/firebaseService.js @@ -39,3 +39,19 @@ console.log('initialized firebase') setPersistence(getAuth(), browserSessionPersistence) + +// import { credential } from 'firebase-admin'; +// import { initializeApp } from 'firebase-admin/app'; + +// import serviceAccount from '../nirvana-for-business-firebase-adminsdk' + +// if(typeof window === 'undefined') { +// console.log('initializing firebase admin') +// initializeApp({ +// credential: credential.cert({ +// privateKey: serviceAccount.private_key, +// clientEmail: serviceAccount.client_email, +// projectId: serviceAccount.project_id, +// }) +// }); +// }