‫The last feature that we're going to implement
‫in this section will be to add a fake authentication.
‫And I'm going to explain what I mean by fake in a minute.
‫So in a typical front end application
‫like a typical React application,
‫user authentication usually works in three steps.
‫First we get the user's email and password
‫from a login form and check with an API endpoint
‫if the password for the given user is correct.
‫Then in the second step,
‫if the credentials are actually correct,
‫we then redirect the user to our main application
‫and we save the user object in our state.
‫And finally, as a third step
‫we need to protect the application from unauthorized access,
‫so from users who are not currently logged in.
‫And so we're going to implement these three steps
‫over these three lectures.
‫Now the part where the fake authentication comes into place
‫is basically in the first step,
‫because we will not ask for the user credentials from an API
‫but instead we're going to have a hard coded user object
‫in our application and we'll simply check
‫if the user and passwords are correct.
‫So we're basically going to only have
‫one user in this example.
‫But this is just to demonstrate you early on
‫how authentication works.
‫But then of course in a later project
‫we will implement some real authentication,
‫so where the data actually comes from a real database
‫with real users.
‫All right.
‫So remember how I said earlier
‫that we're going to store the user
‫that is logged in into state
‫and we will also store into state
‫whether the user is currently logged in or not,
‫so that we can protect our application
‫from unauthorized access.
‫And so in order to do that,
‫let's create another context
‫where we can store that state
‫and give the entire application tree access to that state.
‫So let's come here to our context folder
‫and here I will create
‫a FakeAuthContext.jsx. Okay.
‫And let's get started.
‫And here, let's actually just call it "AuthContext"
‫and drop the, "fake", part.
‫So create context.
‫And here we don't pass in any initial value.
‫And then let's also add our custom provider.
‫So AuthProvider, which will as always receive the children
‫and so really notice how this is
‫basically always the same recipe that we follow
‫when we implement a new context in this way.
‫So right here, let's also immediately return
‫the AuthContext.Provider
‫and then place the children right here.
‫And let's also immediately create our custom hook.
‫So useAuth.
‫So this is basically all the boiler plate code here
‫that we are writing right now,
‫which again is basically almost the same,
‫almost always the same, I mean.
‫So use context with the AuthContext
‫and then we check if that value is undefined.
‫So if it is, then we throw that new error
‫saying that this
‫context was used
‫outside the AuthProvider.
‫Now, okay.
‫And so with this in place,
‫let's now actually think about what we need to do.
‫So let's just come back here to our application
‫and then here we already have the login form, right?
‫So basically what we want to happen
‫when the user clicks on this button here
‫is for our application to call a login function.
‫And so that login function is where we will then check
‫if the user's credentials are correct.
‫So we need a login function, probably here,
‫which will do that.
‫And also we can see here in our final application
‫that we have a logout button.
‫And so we also need that.
‫So clicking those two buttons will then
‫create the actions that I mentioned earlier.
‫So setting the user to authenticate it
‫and storing the user in state.
‫So let's now create
‫first these functions and then the state itself.
‫So let's just call this one here login
‫and it will need the email and the password.
‫And then we also need the logout function,
‫which doesn't need any input.
‫And then we need those two state variables
‫where one contains the user object
‫and the other one stores whether the user
‫is currently authenticated or not.
‫So let's actually do that again using a reducer
‫because these two state variables
‫will always be updated at the same time.
‫So I really like to use a reducer in this situation,
‫even though if it's a really small reducer.
‫So let's call those user and is authenticated.
‫And then we also get the dispatch function.
‫So use reducer
‫with the reducer function and the initial state.
‫So let's create those.
‫Initial state.
‫So our user will be null in the beginning
‫and is authenticated, will be false.
‫And finally the reducer
‫who gets access to the current state and the action.
‫And here we can immediately create our two only types,
‫so there are only going to be really two actions here.
‫So that's the login action
‫and then later the logout.
‫So here we want to return
‫the user that should be set to the action.payload.
‫And of course is authenticated set to true.
‫Now since here we are actually setting
‫both the user and he is authenticated
‫you might think that we don't even need this part, right?
‫So that this would be exactly the same.
‫And actually it is because we are indeed.
‫When we do this, replacing both user and is authenticated.
‫However, we should always, always keep this here
‫because this makes our code more future proof.
‫So imagine that in the future
‫we add some other state variable here
‫and so then we would have everywhere to remember
‫to then add this back.
‫And so with this,
‫there will never be any problem with that.
‫But anyway,
‫now our second action here
‫and here the user, when we logout,
‫will simply be back to null
‫and is authenticated back to false.
‫So we could even return the initial state here.
‫And now our defaults,
‫let's just throw new error,
‫like this.
‫Okay. And so now we are ready to pass everything here
‫into our context value.
‫So that's going to be the user,
‫the is authenticated state,
‫the login function
‫and the logout function.
‫And again, we could actually also pass
‫the dispatch function here instead of these two.
‫But the login function here
‫will actually have some functionality and some logic
‫and so let's keep it here.
‫And also in the real world, it would make an API call.
‫So right here, that's not going to happen
‫and so this is actually a showcase
‫that a context actually doesn't have to do anything
‫with data fetching.
‫So this one will simply contain these two state variables
‫and will then broadcast them
‫to our entire application tree.
‫All right?
‫And now here we can check whether the
‫coming in email and password are correct.
‫And so again, this is where we would
‫typically have an API call
‫but now we will just compare them to a fake user.
‫So let's get that fake user object,
‫and I have it actually here in the components
‫in the user component that is part of the starter files.
‫So let's copy this
‫and not cut because that will break
‫this component here for now,
‫so let's just copy it.
‫So placing that right here outside the component.
‫And so what we can do now is to just say,
‫if the email is equal to fakeuser.email
‫and the received password is equal
‫to fakeuser.password,
‫then we can dispatch our action.
‫So the action of login,
‫with the payload of the fake user then,
‫so that's going to become our logged in user.
‫And then here, all we have to do
‫is to dispatch the
‫logout event.
‫All right.
‫And so now all we have to do here is to export these two
‫and then we're ready to use them.
‫So of course not function
‫but export the AuthProvider and useAuth.
‫All right.
‫And so with this, we have our context in place
‫and are ready to connect it with this form,
‫so with this button right here.
‫And so let's quickly move on
‫to the next lecture and do that.