Skip to content

Guide seems to not work with NextJS 10 #16

Open
@AndreasJacobsen

Description

@AndreasJacobsen

This guide seems to no longer work with nextjs 10+.

Tested using code with my own specifications and copy paste from this repo.
I also tested using both nookies and js-cookies

What happens:
Token gets set correctly on login page, I can see the token in the applications panel of my chrome devtools. Whenever the token is used in SSR the token is shown as invalid by firebase and deleted from the front end cookie storage.

When trying to use this token on a SSR page the token dissapears, firebase gives an error stating

    code: 'auth/argument-error',
    message: 'First argument to verifyIdToken() must be a Firebase ID token string.'

My auth.tsx (at this point copy paste from this repo, tried replacing nookies with js-cookies but got the same issue)

//auth.tsx
const AuthContext = createContext<{ user: firebaseClient.User | null }>({
    user: null,
});

export function AuthProvider({ children }: any) {
    const [user, setUser] = useState<firebaseClient.User | null>(null);

    useEffect(() => {
        if (typeof window !== "undefined") {
            (window as any).nookies = nookies;
        }
        return firebaseClient.auth().onIdTokenChanged(async (user) => {
            console.log(`token changed!`);
            if (!user) {
                console.log(`no token found...`);
                setUser(null);
                nookies.destroy(null, "token");
                nookies.set(null, "token", "", { path: '/' });
                return;
            }

            console.log(`updating token...`);
            const token = await user.getIdToken();
            setUser(user);
            nookies.destroy(null, "token");
            nookies.set(null, "token", token, { path: '/' });
        });
    }, []);

    useEffect(() => {
        const handle = setInterval(async () => {
            console.log(`refreshing token...`);
            const user = firebaseClient.auth().currentUser;
            if (user) await user.getIdToken(true);
        }, 10 * 60 * 1000);
        return () => clearInterval(handle);
    }, []);

    return (
        <AuthContext.Provider value={{ user }}>{children}</AuthContext.Provider>
    );
}

export const useAuth = () => {
    return useContext(AuthContext);
}
//authenticatedPage.tsx
export const getServerSideProps = async (req, ctx) => {
  try {
    const cookies = nookies.get(ctx);
    //Always fails here
    const token = await firebaseAdmin.auth().verifyIdToken(cookies.token);
    console.log("Token is:", token)

    return {
      props: {
        data: "Worked!"
      },
    };
  } catch (err) {
    const cookies = nookies.get(ctx);
    return {
      props: {
        data: "Did not worked!"
      },
    };
  }
};

const Revisions = ({ data, ctx }) => {
  const { user } = useAuth();
  return (
    <Layout>
      <Container>
        {/* always returns no user signed in */}
        <p>{`User ID: ${user ? user.uid : 'no user signed in'}`}</p>
        <p>test</p>
      </Container>
    </Layout>
  );
};

export default Revisions

Relevant versions:

    "firebase": "^8.2.10",
    "firebase-admin": "^9.5.0",
    "next": "10.2.3",
    "nookies": "^2.5.2",
    "react": "17.0.1",

What have I tried?
Shifting from nookies to js-cookies
Using the encode option with nookies

nookies.set(null, "token", token, { path: '/', encode: v => v  });

Edit:
Tested with NextJS 11, same issue.
It seems like the issue happens in auth.tsx when token is being unset if no user is present. The token gets unset when ran un an SSR page.

    return firebaseClient.auth().onIdTokenChanged(async (user) => {
      if (!user) {
        setUser(null);
        // Cookies.set("token", "Satt fra greia");
        // nookies.set(null, "token", "",);
        return;
      }

by commenting out the destruction of the cookie things begin working. But this seems to be like a very sub-optimal and possible insecure solution.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions