Categories
Web Development Web Security

How to secure individual Symfony AJAX api routes without using API Platform

Creating the Symfony route is easy. Checking if the request was sent by AJAX is again easy. But what stops a mischievous hacker from hitting that endpoint and trying to get a list of used emails or something else with a script?

What if you have routes that you want to access with AJAX without API Platform? With Symfony, standard forms created with the Form Component, your forms are CSRF protected. But, when you are sending an AJAX request to an endpoint without a form how do you protect it?

There is probably some Symfony approved way I am not aware of.

If you send the whole form you can use a different procedure and use the CSRF string stored in the form.

However, for simple situations where you need to randomly access a route you can do something similar to the CSRF form protection by generating a unique string and saving in a Session cookie and to the page/form.

Where you save the string in the page is up to you, but it should be a hidden element. This element needs a unique ID in the page so that you can access it with Javascript. A hidden input element in a form works great, otherwise use a hidden span element.(use css to hide the element).

When you need to make a request to the route you use javascript to get the value you hid in the element. Make sure it is just the unique string that you fetch not the entire element html or this wont work. Include this string with the data you are sending to the route.

Inside your route fetch the unique string that you sent in your AJAX. Then try to fetch the same unique string from your session cookies. If the string exists and matches process the request.

There are tricks you can try to use with the header like checking the users browser agent. But that is useless as it can be easily spoofed by a good hacker using something like Curl.

This unique string trick isn’t 100% hacker proof. But it makes it a hell of a lot harder.  More on CSRF attacks here.

NOTE

If you are using the Symfony forms with CSRF activated then you can use Javascript to fetch the value of the nonce hidden in the _token input element. However, if your code will make multiple ajax requests, then you might want to create the custom hidden field and generate a new unique string each time and replace it in the custom field.

Step #1 create the field

To create the field add it in the FormType definition like this. The entire class is too long so I’ll show just the add section.


->add('ajaxString', HiddenType::class, [
                'mapped' => false,
                'attr' => ['class' => 'hidden-field', 'value' => $secretString]
            ])

Notice mapped is false so that I don’t get errors.

Step #2 Build the form

Now you build the form inside the Template for the form. Mine looks like this.


{{ form_start(registrationForm) }}
        {{ form_errors(registrationForm) }}
        {{ form_row(registrationForm.email) }}
        {{ form_row(registrationForm.emailMatch) }}
        {{ form_row(registrationForm.plainPassword) }}
        {{ form_row(registrationForm.passwordMatch) }}
        {{ form_row(registrationForm.userAlias) }}
        {{ form_row(registrationForm.ajaxString, { 'id': 'ajaxString'}) }}
        {{ form_row(registrationForm.agreeTerms) }}

        <div class="d-flex justify-content-center">
            <button type="submit" class="btn btn-lg btn-success">Register</button>
        </div>

        {{ form_end(registrationForm) }}

Notice how I have the id : ajaxString line. This is currently the only way to change the ID of a form field in Symfony see How to change the id for a form input in Symfony 5+

Step #3 add initial value

Inside the controller you must add the initial value for the field and store it in a session cookie.

For this I am using a simple class which generates semi random/unique strings. This doesn’t need to be super top notch secure, it is just to make sure the request is coming from a form my app built.

To access the Session Cookie in Symfony 5.3+ you must now use RequestStack instead of Session or SessionInterface for some odd reason. It just makes it more obscure and harder to figure out how to get to sessions.


$session = $this->requestStack->getCurrentRequest()->getSession();
        $secretString = RandomStringGenerator::lowercaseUppercaseNumberString(32);
        $session->set('secretString', $secretString);

 

To check the value in the Controller route endpoint I do like this.


$secretString = $request->query->get('secretString');
        $secretString = DataSanitizer::sanitizeString($secretString);
        $string = $this->requestStack->getCurrentRequest()->get('secretString');

        if ($request->isXmlHttpRequest() && $secretString === $string) {

Note that secretString is the value sent by the AJAX request. This was the value I hid in the form field to use for this purpose.
The other line

$string=$this->requestStack->getCurrentRequest()->get(‘secretString’);

gets the value I stored in the Session Cookie. Then the if statement makes sure the two values match before processing the request. If the two strings match we know that my app built the form, added the string and my Javascript copied the string and sent it to my server. This prevents people from randomly hitting your route endpoints.

&& $secretString === $string

Links

Here is a good link to Symfony Casts about API Platform. There are many symfony casts here to learn more. I was going to post each but this link contains all of them with pretty pictures and descriptions. LOL

More about CSRF in symfony forms here in the documentation.

Categories
Resources Software Development

Microservice Communication Resources

Microservice Communication resources

In order to completely understand microservices you also have to understand networking. Communication is one of the hardest parts of microservice design, get it wrong and your system simply won’t perform. Below are some useful links that explain networking concepts.

Understanding the basics of RESTful APIs. This is a great article that covers how REST works and how to design a REST API. This article contains some very useful information and is a very quick introduction to the concept.


Understanding And Using REST APIs This is another really great article that covers API consumption. This article is quite a bit longer and more involved than the one above. This article covers REST in depth and is one of the best articles I have found on the subject.

Covered in the article is:

  • What is a REST API
  • The anatomy of a request
  • Testing Endpoints with Curl ( if you have not played with Curl then you absolutely should) CURL website
  • JSON
  • Authentication
  • HTTP Status Codes and Errors
  • Messages
  • API Versioning

Communication in a microservice architecture This article covers some basic information about Microservice communication. It makes some valid points and discusses some of the techniques and technology used for Microservice communication. This Article has some really good links listed throughout it.


Asynchronous Request-Reply pattern  This is a very useful article that covers communication between the frontend client aka browser and the server backend.


Should you use MQ/Brokers or Web services? and how they are different

 


Apache Kafka vs. Enterprise Service Bus (ESB) – Friends, Enemies or Frenemies?

This article covers :

  1. Some of the failures of SOA
  2. Streaming as a replacement for ESB
  3. Compares Apache Kafka to previous SOA architecture that used ESB
  4. Talks about Streaming and why it is the next great thing you must do
  5. Talks about large companies that use Kafka and how
  6. Talks about using Apache Kafka as a dumb pipeline for streaming apps
  7. Talks about the key differences between Kafka and ESB’s
  8. Talks about using Kafka in Legacy systems along side ESB’s and previous generation technologies

 


Application Integration for Microservices Architectures: A Service Mesh Is Not an ESB

This excellent article explains SOA, ESB, Microservices and how the hell we ended up in the current confusing word soup.
This article covers the following:

  1. The basic history of Software Oriented Architecture and Event Service Bus usage
  2. Compares a service mesh to an ESB, similarities and differences
  3. Gives a decent overview of the past usage of ESB’s
  4. Has a wonderful diagram of how ESB’s operate in a SOA system.
  5. Explains what a service mesh is

Kubernetes Service Mesh: A Comparison of Istio, Linkerd and Consul 

This article explains exactly what a service mesh is and compares a few of them. This is a very good, very informative article, one of my favorite.


REST, RPC, and Brokered Messaging – This article explores three popular styles of communication in service-oriented architectures and how to chose the appropriate style for a given use case.


Remote Procedural Calls explained in depth.


This video covers RPC even deeper than the above video. This video also covers Java RMI remote method invocation.