Welcome back.
I want to do a quick review of our security and how our app is working right now because putting a secure
web app online is a very very important responsibility of the Web Developer. Let's go back to our codebase.
There's two main problems that I see so far.
The first thing is that we're not doing anything called validation.
If I'm going to signin here and I go to my signin controller if a user doesn't enter the proper e-mail
or enters something that we don't expect maybe leaves that e-mail field blank or the password field blank
Well what happens then? And same with the register.
If we go to register and a user doesn't type in the proper email or name or password we technically
still register them because if we leave email blank name blank password blank they'll just enter a blank
user into the database.
Let's go to the app and show you what that means.
If I leave this blank and click register look at that I'm entered into the app and if I go back to the
database
and go to users I see a blank user. And this isn't very harmful, but it showcases one important topic
that you really want to focus on in your app and that is validation - making sure that when you communicate
between the front end and the back end there's a few layers of security.
First the Front-End will do its own validation.
For example if we go to the sign in page or the register page within our Front-End within our re-act
app we'll actually check before when we click register will have an on Submit button.
And on submit is going to check to make sure that the name is not empty the email has proper email format
such as having an at sign or a dot com at the end and then password will have some sort of validation for
let's say it has to be greater than six characters. And now the front end sends that validated information
to the backend and an important thing that you want to make sure with your server is that the server
never trusts anything received from the front end.
So it should do its own validation.
That is to check email name and password and make sure there are values that it wants to enter and transact
into the database.
One way we can do this. Well we can simply say that if email or name or password and we can just do the
not so that is the opposite.
So if this is empty they'll turn to true.
If this is empty they'll turn to true, this is empty they'll turn to true.
So if any of these are empty we can just respond status
400
and we can just respond with incorrect form submission.
Let's save this and see what happens.
I'll save. The one thing I want to do is actually go back to my database and hove my PSQL running
here.
If I go to login or users I want to delete the empty user.
Now
and this one is well perfect.
If I go back here and try to click register
I still get the register.
That's because if I go back I see that I get an error here
and I get "can't set headers after they are sent".
And this is a little bit of a trick because if you go here and open up the console.
All right we have a bad request from the server but this if statement gets run and then it continues
on and does this as well because remember in order to end execution within a function we have to say
return.
So that way if this gets run it returns from this function and this part never gets run.
Let me save that go back to our app now let's just refresh here. We'll just do a blank user.
Again we're getting logged in because now when we go to the front end if you remember in our register
file on the front end when we click register.
Well we're fetching
and we're just checking if user and this user because we're responding in here with incorrect form submission
user will be that.
So let's just check here for ID. We save and remember, this is something that we did with our signin
as well in the previous videos if we go back go back to register try to register.
It's not letting me because if I open up the console I have failed to load resources.
If I go to network, try that again go to register I get "incorrect form submission".
So that is really really important.
The server and the client should do its own validation and make sure that it handles all possibilities.
If an attacker for example enters some really really bad piece of code instead of an email. Well we need
to validate against that and make sure that we take proper action based on that.
So we can add things like this into other parts of our app especially ones where we accept input.
Luckily for us that's for our register and then we have our signin as well.
And then for the signin we can simply just copy and paste and here we using request dot body dot email
and password so we can simply just again restructure it
password from request dot body
we'll remove the name
and again and we'll just remove the request dot body from these just to make it a little bit cleaner.
And if I save this this should work as well.
Let's go to signin, make sure I'm not able to sign in.
Perfect.
And if I go to Wes at gmail dot com One two three sign in I'm able to sign in.
All right so that's the first part of the security I wanted to cover.
There's obviously a few more things that we can do here but I think you get the idea.
The next thing, and another major flaw in our app, is that when we submit an image let's grab this
and let's open up the tab.
The network tab here click detect
and if you look at the image endpoint well that when we take care of.
But if you look at the outputs this is where we're asking API clarifai for the request.
If I click on this and look at the headers and I look at the authorization I get the key with DCB17e...
And if I go back to the Front-End and under app dot js
DCB17e...
That's our API key.
We're making our API key which in my case is a free one.
But when you're using an API that costs money somebody could steal this information and use your API
to just load that API with requests and make you pay a lot of money and you never want to do this when
you're playing as a developer on your own project.
That's fine.
But things like this shouldn't happen.
So one thing we can do to avoid this is actually move this to the backend instead of the front end.
Let me show you how we can do that.
We're going to go back to our front end and in our front end I'm actually going to copy the clarifai
information to the Backend and remove it from the front end.
So if you remember we need to just install clarifai on the back end so I'm going to stop the server and
do NPM install clarifai so that we have the package dot json
we will import it this time using require.
So let's go to our handle image
and then the handle image we'll just import and instead of import we'll do const clarifai equals require
clarifai and we'll just copy exactly what we have in our app and want to remove this going to cut
this out
use our API key right here.
Then scrolling down we take a look at where we use our API key in our case it's here app.models.
And here we want to just do the clarifai and then grab our response.
So this bottom part we can keep.
We just need the clarifai call to now be coming from the backend so we'll copy that.
Go back to our back endand
let's put that in place because we have app now from the new instantiation of clarifai and we will now
need to grab the input.
So it sounds like we'll need a new endpoint. Let's clean this up a bit and do predict
clarifai
let's do it over here just so we can see better. I'm gonna minimize this a bit
and app dot models predict we will predict it with our request dot body dot input which we obviously
don't have.
But now we know that we need the input and we can wrap this around a function just like this.
We can say const handleApiCall and this one will receive a request response
and we'll just move this up here.
So now we can just say handle API call at the bottom over here and on our server we can create a new
endpoint for Image and we can do a post request because we'll add it to our request dot body and
we'll just call that imageurl
and the imageurl endpoint will have the handleApiCall.
It won't need the database. We'll definitely need to import it but we have it on the image object already.
OK so if I save this we now need to make sure that we receive the body with the URL, so going to
the front end.
We'l say that on submit we need to fetch and let's just copy this.
What we have here for now. We want to fetch imageurl.
It's going to be a post method and we'll have a json of input and that input will simply be that this
state DOT input. That's going to give us a response and that response will keep trickle down this way.
But keep in mind that because this is a fetch we'll have to do response dot json.
So that's simple enough to do let's fix the indentation here and we'll do a dot then response equals
response dot Jason
We'll save and we'll want to go back and make sure that this is working.
So let's go to our server go to image and make sure that we're responding here with dot then data and
this data will have a response dot json
of data. Whatever this gives us. If there is some sort of an error we'll do a catch.
I will say response status 400.
We'll do.
json "unable to work with API". Let's save. We'll see if this works the first time.
It usually doesn't but if we sign in with Wes at Gmail dot com 1 2 3 sign in, we have a bit of an issue.
Let's go to consol - failed to fetch
Oh we need to actually NPM start our server.
All right and now we get some errors.
All right.
We have missing brackets so we're just we just made a bit of a syntax error here and that's because
I forgot a period in here.
Let's save that.
And if we go to our front ends running, back end is running. Let's close this and try this again.
All right I'm signed in.
If I copy this image again. Moment of Truth.
All right.
We're getting the image, but the response - something's not working. We have failed to fetch the server response
with a status of 500.
So we get an error in the server and it looks like
handle API call is not a function.
So let's go to server and my terrible spelling mistake again. This always gets you with the spelling.
Let's try that once again.
We'll clear this and detect. No errors.
All right.
Look at that.
That's working.
Amazing.
I see no errors in my API or the front end.
So that wasn't bad.
And if I actually go back to the request, go to the network tab and let's check this I'm going to press
detect if I go to imageurl.
We're not seeing any of our keys.
The only thing we're seeing is a response which is the response that we get from clarifai but our server
is running in our own environment and nobody has access to it.
So let's go over what we just did.
We created a new endpoint and because we now have our own controllers and it's regarding the image we
can add it to the image controllers and within the image controllers we create a new function and just
pretty much copy and paste it exactly like we had on the front and we responded with Json data and
this Json data is now getting sent as response dot Json.
So on the front end we simply created a fetch request that sent the input and we responded with a response.
So not much really changed on the front end except for the fact that now we're hiding the API key.
And instead of having clarifai here we have it on the backend.
I hope that was some valuable security tips for you.
There's lots of things when it comes to security and it definitely is something that you have to get
used to as you have more and more years of experience.
But having that general rule of making sure that your machine or in our case your codebase of front
end and back and never relies on the security of the other always focuses and make sure that whatever
inputs it gets from other places outside of itself is always validated.
And we protect any secrets that we have from the outside world.
Never trust anybody is pretty much the motto in security.
So I hope that was insightful and I'll see in the next video.