The Same Origin Policy would normally prevent your scenario from taking place:
GET http://api.example.com/me/token/generate
// parse the response
The response cannot be parsed through a third party domain making requests to your domain. The browser will normally block it due to the SOP.
I say normally because you have also added the following response header to relax the Same Origin rules:
header("Access-Control-Allow-Origin: " . $_SERVER["HTTP_ORIGIN"]);
Under the following misconception:
The reason I "need" that is that, I'm not only using the REST API on the domain itself through forms and JavaScript. But I'm doing requests using cURL in C++.
This header does not have any bearing on cURL. The header is parsed by browsers only, implementing the SOP. It does nothing to prevent direct requests coming for a web client.
Solution
On your api.example.com domain, only allow the front-end to make requests through it using the user's browser:
Access-Control-Allow-Origin: example.com
On your example.com site, send the following header with all API AJAX requests:
X-Requested-With: XMLHttpRequest
See this answer for info on thisSee this answer for info on this. In a nutshell, this header cannot be sent cross domain without CORS being enabled.
Verify on your API backend that this header is present when a request is received. If it is not then it is an CSRF attack.
On your server-side requests using cURL, simply add the header manually. e.g.
X-Requested-With: cURL
As you're verifying that it is present, these requests will succeed.
Finally, add some authentication using cookies. Your logged in website users should have an authentication ticket that can be sent in a cookie, and you should have one for your backend cURL requests to use. This will ensure that nobody can use your API without permission. You may want to restrict the actions that web users can make using authorisation levels because otherwise they may try to maliciously execute a function that only your cURL server tool should do.