Okay guys.
So in the first part we started validating the token.
The current problem is that the CSRF token doesn't exist anywhere yet.
That's why we need to jump to the CSRF function and generate it first before we attempt to validate
it.
By the way, I think we should stick to adding the strict types everywhere.
Let me start with this.
All right.
Next up let's add a function that can generate the token.
I can call this generate CSRF token.
No arguments here and it returns a string.
Now the CSRF token needs to be random and it needs to be automatically generated.
And it needs to be also kind of unique.
I would also like to add a constant, which would be a setting, And this would be the token length.
So just how many characters there are in a token?
And another setting I'd like is the token expiry time.
Let's call it lifetime and this is in seconds.
So let's multiply by maybe 30.
This is 30 minutes.
Okay.
Going back to the generation token is essentially some random bytes.
So let's generate the random bytes using this PHP function and the length of the random string.
We've got a constant for that.
So this is CSRF token length.
So from this function let's return this token.
And I'd like to test this function.
Test it manually.
That's why I'm just going to call it.
Inside this file.
So we just make sure it is called on every single page and we stop the execution.
Okay.
So I can just refresh the page.
And this is how it looks like.
As you see, it's not really characters that make a lot of sense.
And to convert this binary characters which just contain some bytes that just don't have a corresponding
character.
So to make it look like an actual string, we're going to use another function called bean to hex.
It just converts the binary data which we've just generated to hexadecimal representation.
Now this is how our token would look like.
So this is still safe and still unique.
As you can see, when I'm refreshing it is different every single time.
There is really a low chance that we're gonna generate the same token for your user, and the malicious
user that tries to send the form in his name.
There's almost zero chance this will happen.
That's why now we should store this in the session, which we do by setting it on the super global.
So we've got the CSRF token itself and that's just the token we've generated.
And another thing we need is the token time.
So basically when was this token generated.
This is the token time for that.
We're just going to use the PHP time function that will generate the current Unix timestamp, which
is the seconds that have passed since the so-called Unix epoch.
So this function generates a new token.
I think we need another function for this CSRF functionality to be really useful.
That will just return the current token.
This would be called get current CSRF token doesn't have any parameters and returns a string.
Now the job of this function is to check if there is a valid Non-expired token already and return if
it exists, but if it doesn't exist, if there is no current token or the token is just invalid, we
need to generate a new one and return it.
So the job of this function is to take all the mental overhead of implementing CSRF tokens in forms
from the mind of a future implementer, someone who would have to use this functionality.
Whether this is ourselves or some other developer, all you need to do is first make sure you call this
function within a form markup, and then on the root handler that handles the submission of the form,
you validate the token.
So there are only two steps you need to think about.
Now let's implement this function.
So let's start with an if statement that will check if we already have the token and token time inside
the session, because if we don't then we're just going to regenerate it.
So we use Eset to check if two values exist inside the session the see us arrive?
Token.
And the other one is the CSRF token time.
They are both crucial and they both need to be set on the session token time.
So this is the first condition that would trigger the token regeneration.
And in this case we can just return generate CSRF token.
We are just generating it if it doesn't exist now if it does exist we return it straight from the session.
So we just get session CSRF token.
Now there is another condition here.
So if it doesn't exist or it is expired we also need to regenerate it.
So this other condition is calling the time function and subtracting Attracting the token generation
time.
So this would be the session CSRF token time.
And if the result of that is more than the CSRF token lifetime, why do we don't have this.
All right so I've misspelled the constant name.
This should be CSRF token lifetime.
So again if the current time minus the time when the token was generated is more than the expected lifetime,
we need to regenerate the token.
Now it seems that we are using this session super global directly a lot of times, and we are typing
this as a key.
So CSRF token token time.
It's easy to make mistakes here to misspell the name and then.
Well, this can be pretty dangerous.
If we just misspell one of those names, it might break the whole functionality.
That's why I'd like us to add additional functions that will be responsible for returning the current
token and time, and also setting the current token and time, because those are always connected.
So let's add a function that will be called get CSRF token and time.
This will always return an array and it just returns right away.
It would be super simple.
It will just contain the entries of the session, which is the CSRF token or null.
And the other element is the CSRF token time or null.
Now, we never have a case where you're gonna be setting the current token and not setting the time.
That's why we also need to set CSRF token and time.
We should always pass a valid token and time does an integer.
This is void, doesn't return anything.
And.
We should be using this code.
And I think we don't actually need the time.
We can just generate it.
Now here let's call set current token and time passing the token.
Now in this place we should be fetching the token.
Now inside this function get current CSRF token.
We're going to use an array destructuring, getting token and time, and the function is called get
CSRF token and time.
So now we have it much simpler.
We can check for the token and time because it would be null if we don't have it inside the session.
And additionally we can even add one another function so we can write a function called is token expired.
It would return boolean and we might pass the token time here, which can be nullable.
And we just return whether time is exactly null or the current time minus the time from the argument
is more than the CSRF token lifetime.
The token is expired.
Now we can simplify this function even more.
We regenerate the token if we don't have the token or time in the session, or if the token is expired,
for which we pass the time.
So it's time to start using the token inside the form.
First, let's jump to the contact get root.
That's the place where we are going to get the current CSRF token.
Just the token, because that's the only thing that we need for the form.
So we're going to be passing some data to this form template.
This can be called CSRF token.
And we can call get current CSRF token.
We are done here.
Now let's jump to the template.
And this is our placeholder for the token, so the token is directly connected to a single form submission.
Every single form should have its own token.
It's not really possible to have 2 or 3 form submissions at the same time.
You can only submit one, so if there is a token generated, we just need to make sure we validate it.
And to have the token sent together with a form, we can add another input of type hidden.
This won't be visible, but the data would be sent together with a form.
It will be called CSRF token and the value will just come from our data.
So this is we echo the data CSRF token.
That's the value we have just passed from the root handler.
And the only thing left is to verify this token.
When this is submitted to the specific route handler, which we already do, we just don't have this
verifying function implemented.
Now, after we save the changes, let me refresh the form and open the DevTools.
I'd like to locate this hidden input.
So let me zoom in here.
I think you can see the form.
And here we've got some inputs and labels.
And there it is.
This is our hidden input with the CSRF token name and the value that was generated and will be valid
for the next 30 minutes unless it expires or you submit the form.
And in that case we're going to be generating a new token for the next submission.
Now, I think we can conclude at this point.
And in the final third video we are going to implement the token verification.