Protected Routes | Creating a RESTful API with ReactPHP

Protected Routes | Creating a RESTful API with ReactPHP


Welcome back, in the last two videos we have
added user signup and user sign in. In this video, I want to make sure that we
can also protect routes. We have this token that we can store on our
client, now I want to make sure that we can use that token to access certain routes on
our backend, that are protected. So, it’s time to add some protection. We have our products and our orders routes. There are some routes that we don’t want to
protect. For example, getting all products. That makes sense to be an unprotected route. Because if we were to create a frontend for
our shop here, we probably want to be able to view all our products even for unauthenticated
users. The same is true for a GET route to a specific
product. Typically we want to allow our users to get
more product information. However other routes like creating a new product
or deleting products or changing them and maybe all order-related routes including the
GET route here are protected routes. We want to make sure that not every user can
access them. And therefore we need some way to protect
these routes. A good approach would be a middleware, which
we can easily add to our route. When this middleware runs it determines does it make sense to continue or the user isn’t authenticated. So, let’s create a new class. We can name it explicitly ProtectedRoute. The idea is the following: this middleware
wraps a protected middleware. When the request arrives we verify the token. If everything is OK, we call the wrapped middleware. But if there is no valid token we immediately
return an unauthorized response. So, the constructor accepts a private key,
it will be needed to verify the token and a middleware or a controller that should be
wrapped and thus be protected. Then in method __invoke() we handle the request. Once the request arrives we check the token. If it is valid then we execute the wrapped
middleware. Otherwise, we return an unauthorized response. Let’s add method authorize(). Here we get an authorization header from the
request. We extract a token from the header value. If it is empty we return false. Then try to decode the token. Call a static method JWT::decode() and pass
a token, a private key, and an algorithm. We use HS256. If the result of decoding is null, it means
that the token is not valid. That’s it. I don’t want to manually create instances
of this class of each route. It will become a bit messy passing all the
time a secret key. Let’s instead create a sort of factory – a
guard. Which will be responsible for wrapping our
controllers into protected routes. Create a new class Gaurd, the constructor
accepts a secret ket. Then comes one public method protect(). It accepts a middleware and returns a ProtectedRoute. Inside we wrap a passed controller into an
instance of the protected route. Ok. Now, we need to initialize the guard and then
wrap all protected controllers inside. Open server.php and we start wrapping. We use a JWT secret key from the environment
variable. Protect the route here: when we create a new
product. Then here when we delete or update a product
and all order-related routes. That’s it. Ok. Save this and let’s try. Open requests file. At first, we need to sign up. Here we receive a token in the response. I don’t want to copy and paste it each time
I need it. So, let’s use PHPStorm global variables and
save it. After the request body we type client.global.set(). And a name of the global that we want to use. I call it “token” and a field from the response. In our case, it is also called “token”. Send this request once again, nothing changes,
but with that now we have stored a token in the global variable. So, let’s try to request all orders. As expected we receive a 401 response. But now let’s send our jwt with the request. To do it we provide an Authorization header
and use our stored variable with token. Now, if I send this I get a list of orders. So this is how we can use the token. How we added our middleware which we can now conveniently add to any route that should be protected. And we are using a jwt concept for this authentication
flow and for making sure that the client can be identified by a server and can access protected
resources without the server having to store any information about the connected clients. This is now true stateless authentication
implemented in our ReactPHP server. Now with that, we made a huge step forward
– we added authentication. And now it’s up to you continue building this
API. Of course, our tokens are not completely secure. To protect our API we can add refresh tokens,
we can implement throttling there is a lot of stuff there. I hope you enjoyed this series and you have
learned about how you can build a RESTful service with ReactPHP.

Leave a Reply

Your email address will not be published. Required fields are marked *