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.
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.
Then we are using connect-redis.
All the details you can find in here.
To install, add below command.
yarn add redis connect-redis express-session
redis
is the Redis client. Then connect-redis
is 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.
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
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 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 }),
...
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