razzle icon indicating copy to clipboard operation
razzle copied to clipboard

Example with http-only cookies

Open rwehresmann opened this issue 4 years ago • 15 comments

❓Question

I'm migrating my SPA to razzle, and some changes were needed to make it work with SSR. I was saving the JWT for authentication in the localStorage, this's what I had:

const PrivateRoute = (props) => {
  const token = localStorage.getItem(BrowserStorageKeyEnum.Jwt);
  let isTokenExpired = false;

  if (token) {
    const decodedJwt = jwt.decode(token);
    const currentTimeInSeconds = moment(Math.floor(Date.now() / 1000));
    const expirationTimeInSeconds = decodedJwt.exp - currentTimeInSeconds;

    if (expirationTimeInSeconds <= 0) isTokenExpired = true;
  }

  if (token && !isTokenExpired) {
    return <Route {...props} />;
  } else {
    return (
      <Redirect
        to={{
          pathname: RouteEnum.Login,
          state: { from: props.location }
        }}
      />
    );
  }
};

export default PrivateRoute;

But this needs to change now. The alternative that I saw was to use http-only cookies, but I couldn't figure out how to implement this. If someone could give me some directions, I would appreciate it.

rwehresmann avatar Sep 10 '20 19:09 rwehresmann

You need to create a express route that checks if the token is expired. I would make two react providers that checks for expired token, one for server-side and one for client side. Server-side provider checks the token in the express view that renders the react app before rendering. Client-side provider checks the token by doing a request to the route that checks if the token is expired.

fivethreeo avatar Sep 10 '20 19:09 fivethreeo

https://hasura.io/blog/best-practices-of-using-jwt-with-graphql/

fivethreeo avatar Sep 10 '20 20:09 fivethreeo

Would be cool to make a full featured example with keycloak and hasura.

fivethreeo avatar Sep 10 '20 22:09 fivethreeo

I may add it here later

https://github.com/fivethreeo/razzle-with-docker-nginx

fivethreeo avatar Sep 11 '20 16:09 fivethreeo

Thanks, it would be helpful! I'm having a hard time to figure it out how to implement the providers :sweat_smile:

rwehresmann avatar Sep 11 '20 19:09 rwehresmann

I have set up a deployment with keycloak now. https://github.com/fivethreeo/razzle-with-docker-nginx

But not quite sure how to do jwt with it.

fivethreeo avatar Sep 13 '20 22:09 fivethreeo

If you can make your spa work in this example I can do the changes to it to make it ssr capable. You may want to modify nginx/default_dev.conf.template and remove the hasura and keycloak parts so you can run just your razzle build.

fivethreeo avatar Sep 14 '20 00:09 fivethreeo

This is a good start:

https://github.com/jkasun/stack-abuse-express-jwt/blob/master/auth.js

Just make the refresh token a http-only cookie.

fivethreeo avatar Sep 14 '20 22:09 fivethreeo

Thanks @fivethreeo , I'll give it a try as soon as possible. I actually found a not so pretty workaround for my PrivateRoute for now: check if is the server rendering, and if it is, just return null and wait for the client rendering. Of course, the route in question will not work for SEO, but in this case, no worries for me, because the private routes don't aim this.

rwehresmann avatar Sep 16 '20 11:09 rwehresmann

Not done yet but I have a work in progress app here: https://github.com/fivethreeo/razzle-prisma-graphqlcodegen-urql-formik-jwt

fivethreeo avatar Aug 12 '21 23:08 fivethreeo

https://github.com/fivethreeo/razzle-prisma-graphqlcodegen-urql-formik-jwt

Is working with http only cookies.

fivethreeo avatar Sep 07 '21 23:09 fivethreeo

fivethreeo What configurations should I use to keep using javascript insted of typescript ? Thank you

GuyFawkesII avatar Apr 02 '22 16:04 GuyFawkesII

This example uses graphql codegen and prisma so not sure if it is possible.

fivethreeo avatar Apr 02 '22 17:04 fivethreeo

What options do you think I have , because 70% of the project has been done in JS .

GuyFawkesII avatar Apr 02 '22 18:04 GuyFawkesII

Just remove graphql-codgen typescript plugins. Make prisma output a js client instead of typescript. Remove types from code and rename ts(x) to js(x).

fivethreeo avatar Apr 03 '22 01:04 fivethreeo