Press "Enter" to skip to content

MERN Stack & GraphQL – #9 Authentication (Part 1)


you guys welcome back to cold room in
this video we’re gonna start working on
the authentication portion of a graph QL
chat application now before we get into
that I’d like to recommend that you go
back and watch one of the previous
videos that I’ve uploaded and this one
is titled authentication on the web
sessions cookies JWT and local storage
this one is a good introduction into the
topic of authentication at large and I
do recommend you go back and watch that
video first now going back to today’s
episode before we start working on the
authentication part I’d like to first
address some of the questions that you
guys raised in the comment section so
one of the questions was about the
convict J’s file and specifically you
guys we’re asking should we actually
take the secrets stored in this file and
push them to our source code on github
and the answer of course is not because
if you have secret values stored in this
file you would want to make sure that
they don’t end up in your source code so
that other people can actually read them
and utilize them for their own purposes
so to go around this one way would be to
create a dot end file and if you want to
learn more about that end files as well
as environment variables in nodejs
I’ve actually created a video titled
configuring environment variables and
nodejs this one talks about the
environment variables in a lot more
detail but for the time being I’m going
to create a dot and file so what I’m
gonna do is I’m gonna copy all the
variables from config is let me select
all of them and once we do I’m gonna go
ahead and copy them to dot N and so in
this file we can actually go ahead and
assign values to those variables so for
instance for the port will get assigned
a 3,000 the environment in this case
would be development we can also have
our database username as well as other
variables so the purpose of this file
becomes to actually supply the real
secrets to our application so instead of
putting the actual password to our
database inside of the convict J’s file
you would put it inside of the dot n
file and you would also want to make
sure to go to get ignore and also add
the dot and file inside of it so this
way the dot and file will be ignored by
yet this way you won’t be able to
accidentally commit it to your source
code so once you fill out all the
variables in your dot n file what you
could do to load them is you could
install a dot and library or package or
you could simply go to your package JSON
and you can go ahead and add an eval
command so we’re gonna do eval on the
dot and file and so what this is going
to do is it’s going to read all of the
values
and file and it’s gonna pass them to the
note Mon command this way all of the
variables stored in this environment
file will be loaded to your application
at runtime now the next question would
be do we actually need to provide the
defaults in this case and the answer is
no because assuming that you pass all
the variables from e dot and file the
defaults in this case should not be
necessary anymore but it’s a good
practice to keep them as a full box so
I’m going to keep them in this case and
once again of this eval syntax is
confusing to you make sure to go back
and watch the environment variables
video now the next question was about
validation in our application so if we
go to schemas user J s the error message
for the password field is actually
incomplete because in this case aside
from validating for special characters
and letters and digits in our password
we also check for the length of the
password so in this case the password
has to be between 8 and 30 characters
long so one thing we could do is we
could improve the error message itself
so we could mention at the length of the
password has to be between 80 and 30
characters but a much simpler solution
would be to use the built-in minimum and
maximum methods enjoy so we could say
that the minimum length has to be 8 and
the maximum needs to be 30 though in
this case we could actually bump it up
to 50 or even 100
once again this depends on the business
requirements of the application I’m
going to keep them at 54 now though of
course most people probably wouldn’t go
beyond 15 or even 10 characters long so
let’s leave it at 15 now for the regex
itself we’ll get either updated to 850
or all we can do is we can also remove
the last portion of the regex and we can
even simplify it by removing the
condition for special characters I’m
actually gonna update the error message
as well so in this case we’re looking
for at least one lower case letter one
uppercase letter and one digit and
before closing off the expression I’m
gonna put period star this is gonna mean
any character any number of times but of
course it’s gonna apply other rules as
well the last thing I’m going to do is
I’m gonna go to the index.jsp file and
I’m gonna change sign up from uppercase
to lowercase because in this case the
convention is the uppercase letter is
reserved for constructor functions and
now to update it we’ll have to go back
to resolvers so let me update the
mutation so the sign up is gonna be
lowercase like this so we can save it
and now we can actually work
on the authentication portion itself so
let’s go back to the browser what I’m
gonna be using for authentication is the
Express session package this package is
once again used as a session middleware
for Express let’s go back to the
terminal
I’ll do an ad dev on that package and
once again if you’re new to it feel free
to go back to my channel the last video
that I’ve uploaded before this one is
titled a session authentication and
Express and it actually walks you
through the different configuration
options in this package and it explains
how to set it up in a lot more detail
but assuming you have a basic
familiarity with this package we’re
gonna go back to a project and we’re
gonna go ahead and go to the index.js
file we’ll go ahead and import session
from Express session so once we create
an instance of Express we’re gonna do an
app use of session we’re gonna pass a
configuration object we’re gonna pass a
name once again I’m going to extract it
from a variable let’s call it session
name we’re gonna need to also add it to
the conflict JS file so let’s do exactly
that we’ll have a session name will
default to a session ID also have
session secret and also session lifetime
set to two hours that will have a
thousand milliseconds multiplied by 60
this will give us 60 seconds 60 minutes
or one hour multiplied by two this is
gonna give us two hours so we can save
that now we can actually import these
variables as well so let’s go ahead and
add them in our import statement so we
already have a session name we’re also
going to pass a secret set to a session
secret we’ll have a configuration for a
cookie itself but before that let’s also
not forget to set we save to false
because it’s true by default and we’ll
also set save and initialize it to false
as well now for the cookie the maximum
age is going to be a session lifetime
same site is going to be true secure is
going to be conditional depending on
whether we are in production or not so
we’re gonna set it to in prod like this
now the last property once we configure
is actually store now you may or may not
know that this library actually uses an
in-memory store by default and that
means that every time you restart the
server it’s going to clear out all this
sessions saved in a session store so to
make it more persistent what we can do
is we can actually use one of the
production ready stores so for example
we could use the Redis one in this case
we can go ahead and use the connect
rightist library so this one allows us
to wire up the session made a word to
the Redis store and so what we need to
do is we need to install this client so
let’s go ahead and do that I’m gonna go
back to the terminal let’s do it you’re
an ad of connect Redis so now to use it
we need to import it and also call it
with the session middleware so let’s do
that let’s import connect Redis from
connect Redis we’re gonna go ahead and
create a Redis store I’m gonna call
connect Redis with session and once we
do we’re gonna create an instance of a
store we’re gonna new up Redis store
like this it will pass in a few options
in this case we’re gonna pass a host a
port as well as password and of course
all these options are also documented on
the website so you could see we can pass
a host but can also pass an existing
clients but in this case we’ll limit it
to a host a port as well as a password
over here so what I’ll do is I’ll
reference existing variables let’s call
them Redis hosts
read a sport as well as Redis password
so let’s go ahead and also add them to
our config and once again I’m going to
add defaults to these variables so for
example this could be a localhost
typically the port will be 63 79 and a
password could be secret now of course
these values will vary depending on the
environment so you would need to copy
these values and also paste them to your
dot and file and make sure you
initialize them with the actual secrets
so you could connect your Redis store
now in this case what we can do is we
can either install Redis locally we
could also set up a docker container
alternatively we could also use Redis as
a service so for example you could go to
Redis labs com
now here you can create a free account
and once you do you can go ahead and
create a database of course for free if
you go to the configuration section
you’re going to find out the address to
this server with the actual port as well
as the password that you can use so I
already have an existing database I’m
going to use this one for the tutorial
and of course once you have the
credentials make sure to put them to
your dot and file
don’t put them to the context es file
because the config is religious the
fullback or your seeker
but once again the actual secrets would
go to the dot and file so once you do we
can go ahead and back in our index.js
file we can once again the copy these
variables and also put them over here so
once we set up a store we can actually
pass it to our session middleware so
this way it’s going to use a Redis store
and this way the sessions will not be
lost even when the server restarts so
once this is done we can go to our user
resolvers and so looking at the users
query what we could do here is we could
call a method so for example check
signed in we could also reuse this same
method in other queries as well but for
the signup mutation it would make sense
to call it check signed out for example
so all of these helper functions we can
actually go ahead and extract them to a
separate file so let’s create a file
called auth j/s we can go ahead and
create a constant this will be a
function to check if the user is signed
in now in this case we have access to
the context and from that context we
need to get access to the request object
so if we could do context dot request
this is going to give us access to these
session and once we have access to the
session we can read any variables stored
in that session so for example we could
access the user ID so we’re gonna put in
later on so now to enable the access to
the request object we can go back to our
index J’s file and then we’re going to
pass in a property to our poll server to
configure a context this will be a
function it’s going to accept a context
object what we can do is we can extract
the request and response objects out of
it and we can return them in a separate
object like this so once we do that we
should be able to go back to our users
query and now we’ll have access to the
request object in the context so now
once we have the request object we can
access the session on it so one thing we
could do is we could pass the session
itself to the function we could also
pass the user ID if it’s present but I
think it makes sense to pass the entire
request to the function and let the
function figure out whether the users
signed in based on that request object
so let’s do exactly that so back in our
oath j/s so be a function that accepts a
request object and it’s going to check
if the request session contains a user
ID now there is a few things we could do
here if the request does
contain a user ID on this session we
could actually go ahead and throw an
exception so let’s do an F here if we
don’t have a user ID we’re going to
throw an exception in this case we can
refer back to a polo server package we
can go to error handling and let’s look
for authentication error as you can see
it’s one of the errors so that we can
reuse so let’s copy it I’ll paste it in
over here and we’re also gonna have to
import it so let’s do exactly that
authentication error from Polo server
express like this and we can also pass
any custom error message you must be
signed in now this function of course we
can export from this file and so back in
our resolvers we could either import the
function alone from auth one level up or
we could also import everything from
that file because we’re also going to
have other functions like checks signed
out for example this will be another
function as well so to import all of
them what we can do is we can import
everything from that file as off for
example so this way we can do auth dot
check signed in we’ll do the same thing
over here and now in there we’re gonna
do auth checks signed out once again
we’re gonna extract requests from the
context and we’re gonna do the same
thing over here as well so now that
we’ve done that let’s go back to this
file so here we’re gonna do the reverse
of this operation so if the user is
actually logged in we’re gonna say that
you are already signed in like this and
of course we’re gonna do an export of
that function now this condition in the
if is actually repeated so we can
extract it into a separate function we
can call it signed in once again it
takes the request and returns request
session user ID so in this case we can
call that helper function sign in with
the request object once again if we’re
not signed in in this case we’re gonna
throw an error saying that you have to
sign in in order to perform this action
but in checks signed out we’re going to
call signed in like this and if the user
is signed in we’re going to throw an
error saying that you are already signed
in let’s also add another query we’re
gonna call it me well this will be a
function that will tell you what user
you’re signed in as in this case we’re
gonna have to do an auth check signed in
before anything also gonna need to work
on
projection as well and once that’s done
we can do return course we also need to
have all the parameters so roots are X
context and info will grab requests from
context and we’re going to return a user
find by ID and we should expect to have
a request session user ID in there and
of course if we don’t this section over
here should fail because it’s going to
call it check signed in function this
one fails when you’re not signed in and
if you are signed in we’re gonna find
the user by user ID store it in this
session and we’re gonna return that user
back to the client now we already have
the signup mutation it might also help
to work on the sign in mutation as well
so let’s do a sign-in function once
again we’ll have a root orgs context and
info let’s get the user ID from request
session once again will extract session
from context like this next we could put
the check signed out condition so in
this case if the user is already signed
in it doesn’t make sense to call that
mutation once again in fact what I’m
actually going to do is I’m going to put
a condition so if the user is signed in
we’re going to simply return back that
user so we’ll do a user find by ID and
we already have the user ID so instead
of throwing an error we’re just going to
return back the user and this is similar
to the sign up mutation where we create
the user and return it back to the
client once it’s created so in fact by
the end of this sign-in mutation we’re
also going to return back a user so in
the same note let’s go back to our type
definitions I’m going to add another
mutation let’s call it sign-in we’re
going to ask for an email as well as
password and we’ll return back a user
once again I’m not going to put an
exclamation point because this operation
might fail and if it does we’re gonna
get back an error and not the actual
user object and since we’re in the same
file I’m also going to add another
mutation let’s call it sign out and this
one will not take any parameters we’re
just going to return back a boolean to
indicate whether the sign out was
successful or not
so now let’s save this file and back in
here we’re gonna add another function
let’s call it sign out we’ll have roots
args contact
and info let’s get the request object
from there now once we establish that
the user is not logged in we’re gonna
have to go ahead and validate the
argument passed to the query so let’s
call join us validate will pass the arcs
we’re also gonna have to pass in this
schema which we’re gonna have to create
now if you remember we already have a
schema to sign up a user in this case
we’re gonna add another schema now
because in this case for validating for
multiple fields including email username
name and password this will not work if
we want to only validate the email and
the password fields once again for the
sign in mutation we only have the email
and password so if we try to use the
same object to validate that payload
it’s always going to fail because we’re
gonna miss the name as well as user name
fields so in this case we could do a
named export of sign up and now what do
we want to do well we want to call enjoy
that object and ideally you’ll want to
specify the list of keys and then want
to pass for the assign application we
want to pass the email username name and
password right so this could be a
separate object but if I wanted to
create a constant for sign-in in this
case we’re gonna call joy object we will
also have a set of keys but in this case
the set will be different because we
only want to validate the email and the
password in fact let me bring them on
one line so what we can do is we can
create separate constants for every
field so let’s do an email then a – a
username
we’ll have name and we’ll also have
password like this and now this old
export default we can remove so we’re
gonna have to named exports for these
sign up in sign and mutations and now
back in the index file we’re going to
export everything from user like this so
now once we do let’s go back to this
file we’re gonna pull in a sign up as
well as sign in once again these are
gonna match the two named exports in
this file sign up and sign in so let’s
pull both of them in we’re gonna pass in
this sign in schema and we also want to
make sure that we don’t abort early I’m
going to pass aboard early sets of false
just like we did in the sign up mutation
before so I’m gonna have to call a wait
on it because this is an asynchronous
operation so I’ll add a sync to the
function so once the validation is done
we’re gonna try to do a you
finally so let’s the user find one and
we’re gonna pass in an object with a
condition for the email address in this
case we’re targeting our X dot email
so let’s actually extract them from the
arguments object let’s have an email in
password or marks so we can go ahead and
pass the email in there and of course
we’re gonna do and wait on it because
it’s asynchronous so if we don’t find
the user we could throw an error but
because this logic is similar to what we
have in the authorized file let’s go
ahead and create a helper function so
we’re gonna call it attempt sign-in
we’re gonna accept the email and the
password of the user in question so this
will be a function let’s go ahead and
remove this logic from here so now once
we export it we can go ahead and call
auth dot attempt sign in with the email
and password this case I’ll just
reference them directly and now we’re
gonna expect to get a user object by the end of this operation

Please follow and like us: