All Articles

Creating a Reddit Clone Using React and GraphQL - 04

inner peace

This is a series of posts and the previous one you can find from here.

Learning React with Ben Awad — 03

The codebase for this article that can find in here.

rasikag/reddit-clone

Now we are going to implement the user authentication for this application. To do that we are using session authentication using cookies.

We use Session to do that. It will store some data on user on our server. To store data on the server, we use Redis in-memory database. It is really fast and every request we need to check that the user is logged or not.

You can install Redis using the below guide.

Redis Quick Start - Redis

Then we are using connect-redis. All the details you can find in here.

tj/connect-redis

To install, add below command.

yarn add redis connect-redis express-session

redis is the Redis client. Then connect-redisis the connector for Redis client. express-session is our server-side session manager.

Now copy the below code from there example in connect-redis . Once you convert require you will get this error.

could not find a declaration file for module redis

This means we need to add type support. To do that, add below modules.

yarn add -D @types/redis @types/express-session @types/connect-redis

Now, we move this code bit inside of the main function and before the Apollo middleware. The order is a matter in here because Apollo middleware will you the Redis. So we need to initiate in before it.

const RedisStore = connectRedis(session);
const redisClient = redis.createClient();

app.use(
  session({
    store: new RedisStore({ client: redisClient }),
    secret: "keyboard cat",
    resave: false,
  })
);
const apolloServer = new ApolloServer({
  schema: await buildSchema({
    resolvers: [HelloResolver, PostResolver, UserResolver],
    validate: false,
  }),
  context: () => ({ em: orm.em }),
});

Now we are adding few settings to the session object.

  1. disableTouch : true

This will keep the session alive forever. unless we need to define TTL(Time to Live) and every time the user did something, the client needs to send a request that telling refresh the session time. From this, we can reduce server calls.

  1. name 

Name of the cookie. (qid)

  1. maxAge property in the cookie 

The maximum age for the cookie 

  1. httpOnly prop in the cookie 

This prop defines that front-end JavaScript code can’t access the cookie. Good for security.

  1. secure prop in cookie 

This will only allow to create and use this cookie in https environment 

  1. sameSite prop in the cookie

This will protect from csrf attacks.

  1. saveUninitialized to false

If we did not add this prop, it will create a session even we didn’t add the props. We don’t need to add an empty session. To prevent that add this prop.

Now we change the RedditContext file to use request and response object. This makes it to use type support. Then pass it to ApolloServer object.

...
context: ({ req, res }: RedditDbContext) => ({ em: orm.em, req, res }),
...

Okay, now we are adding session in user registration. First, add the req parameter in register resolver. 

...
@Ctx() { em,req }: RedditDbContext
...

Then we can access the session object. We can store anything inside a session object. In here we only need to have userId.

req.session.userId = user.id

But, here we will get an error saying,

Property 'userId' does not exist on type 'Session & Partial<SessionData>'.

To fix that, we are adding it to RedditContext ‘s request object as below.

req: Request  & {session: Session & Partial<SessionData> & {userId: number}};
// this & sign will join these types together

Okay, at this point all set up and we are going to test this. First, you need to change some setting on GraphQL playground setting on your localhost. In there, change "request.credentials”: “omit” to “request.credentials”: “include” . Unless this will not work.

To check the cookie, open the developer tools and select the Application section. Using login query, try to log in and once you successfully logged in you will see the cookie with name as qid and cookie value.

I will wrap-up this note from here. Soon I will publish the next part of this note.

If you have anything to ask regarding this please leave a comment here. Also, I wrote this according to my understanding. So if any point is wrong, don’t hesitate to correct me. I really appreciate you.

That’s for today friends. See you soon. Thank you.

References:

This article series based on the Ben Award - Fullstack React GraphQL TypeScript Tutorial.

Main image credit