'Protected Route by checking JWT saved in user's cookie

I just finished implementing Google social authentication in my NextJS + DjangoRest project following this blog post. I am trying to figure out how to make protected routes that will redirect users if they’re not logged in.

This is how I did it so far:

  • when user logs in, it saves the jwt_token in the cookie as httponly
  • uses axios with “withCredentials: true” to access the API endpoint which returns current user data(i.e. email)
  • saves the user data as a useContext(). When protected page loads, check if UserContext is empty or not and redirects to login page if it is empty.

The obvious problem is the UserContext is reset whenever user refreshes the page, even when the JWT token is still present in the cookies. And I have a feeling this isn’t the right way to implement this.

So how would I implement a similar feature in a non-hacky way? I cannot read jwt-token from cookies in the frontend as it is httponly. Is there a safe way to read user’s JWT token from cookies to test for authentication?



Solution 1:[1]

I modified @Matt's answer slightly and typescript-friendly to solve my problem. It simply checks the user's cookies if they have a jwt_token value inside.

import cookies from 'cookies'

export const getServerSideProps = async ({
  req,
}: {
  req: { headers: { cookie: any } };
}) => {
  function parseCookies(req: { headers: { cookie: any } }) {
    var parsedCookie = cookie.parse(
      req ? req.headers.cookie || '' : document.cookie
    );
    return parsedCookie.jwt_token;
  }

  const isAuth = parseCookies(req);

  if (typeof isAuth === undefined) {
    return {
      redirect: {
        destination: `/auth/sign_in`,
      },
    };
  }
  return {
    props: {
      isAuth,
    },
  };
};

Solution 2:[2]

So if I am reading your question right then you can use getServerSide props on your page to detect if the user is authenticated with your api.

function Page({ isAuth }) {
    return (
    <>
      <div>My secure page</div>
      //if you return data from your token check api then you could do something like this
      <div>Welcome back {isAuth.name}</div>
    </>
    )
}

export default Page



export async function getServerSideProps(context) {
    const isAuth = await tokenChecker(context.cookies.jwt) // In your token checker function you can just return data or false.
    if (!isAuth) { //if tokenChecker returns false then redirect the user to where you want them to go
        return {
            redirect: {
                destination: `/login`,
            }
        };
    }
//else return the page
    return {
        props: {
            isAuth,
        },
    }
}

If this is not what you mean let me know and i can edit my answer.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tyler Kim
Solution 2 Matt