DEV Community

Cover image for Creating a Reddit Clone Using React and GraphQL - 04
Rasika Gayan Gunarathna
Rasika Gayan Gunarathna

Posted on • Edited on • Originally published at rasikag.com

Creating a Reddit Clone Using React and GraphQL - 04

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 }),
});

Enter fullscreen mode Exit fullscreen mode

Now we are adding few settings to the session object.

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.

name prop.

Name of the cookie. (qid)

maxAge property in the cookie 

The maximum age for the cookie 

httpOnly prop in the cookie 

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

secure prop in the cookie 

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

sameSite prop in the cookie

This will protect from csrf attacks.

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 }),
...
Enter fullscreen mode Exit fullscreen mode

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

 

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

Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

But, here we will get an error saying,

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

Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

Top comments (0)