Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Mushr00m's avatar

Some questions about API creation

Hi !

I'm creating a simple API for my app to receive forms POST to it. Only 2 routes on my API, so a very simple one. But I have some "problems" :

1- I want to use basic.auth to authentificate websites that send their forms to my API, but I don't want to use my Users table/model because it's not "users" in my case but 4 websites, so is it possible to use the auth.basic but providing hard coded login/password from a file or a config ? Not the DB (or if the DB, and other that Users table).

2- Does it make sens to have a CSRF filter for POST requests on an API ? I'm not sure about this... and if it does make sense I don't know how to provide the token in my remote form. Also if it doen't I don't know either how to disable my global CSRF protection for routes starting by "api/v1" :

Route::when('*', 'csrf', ['post', 'put', 'patch']);

3- Is it secure enough to use HTTPS via self-signed certificate and cURL to make my API calls ?

0 likes
15 replies
MikeHopley's avatar
Level 17

I don't think it makes sense to have a CSRF filter when you are expecting the POST to come from another site. CSRF stands for Cross Site Request Forgery. It occurs when you are sent POST data from another site but you intended to get post data only from your own site.

The filter works by inserting a session token into your form and then checking the POST data contains a token matching the one stored in your session. This ensures that the request came from your site.

By using the CSRF filter, you can be certain that the incoming POST data is what you expected -- because you defined what was sent and which route it was sent to.

When the POST data is supposed to come from an outside site, this does not apply. They could send you anything. So all your filtering is done after the POST request. Applying the CSRF filter would just mean no one could use your API.

As for self-signed HTTPS:

The security of HTTPS does not depend on who signed the certificate. Verisign or yourself -- it makes no difference to the encryption and tunnelling. So for your own development on localhost, a self-signed certificate is perfectly fine.

However, a self-signed certificate is not trustworthy. The browsers trust a small number of agencies to verify the identity of a website. When you buy a SSL certificate, what you are really buying is an identity check -- a bit like a passport.

In some ways it's a bit of a racket, and money for old rope. But really, once you get out of development and into production, you need to buy a certificate to ensure user trust.

3 likes
bashy's avatar

The above is perfectly correct.

CSRF is needed whenever it's possible that someone can unknowingly be sending data that would change something by doing so. If someone could write a bit of JavaScript (or similar) on a page that would execute automatically to send data as stated above, you need a CSRF token.

Mushr00m's avatar

@Mike Hopley : Thanks for your answer. In my case the HTTPS will be use only from server to serve via cURL and only from my websites to my app, so no needs to be more than self-signed certificate.

About my question about the CSRF filter. Right now I use this :

Route::when('*', 'csrf', ['post', 'put', 'patch']);

It's on my routes.php and protect every routes but I want to disable it for my routes starting with "api/v1", how should I do that ?

Thanks

Mushr00m's avatar

No in this case it will protect everything under "api/v1". What I need is to protect everything Except "api/v1".

austenc's avatar

@Mushr00m, you could use route groups.

Route::group(array('before' => 'csrf'), function()
{
    // Your (non-API) routes here
});

// API routes outside the group
Mushr00m's avatar

@austenc : In this case it means that all the routes inside the group will have the CSRF filter. In the example I gave in the first post, it was nice because in one line I was creating a global filter only for Post/Delete/Put request.

So the group option is my last solution, if I found nothing else because I would have to put all my Get routes outside of it and I like to list my routes by sections and not by request verbs.

Mushr00m's avatar

Didn't know about that one ! Thanks it looks like what I need ;-)

Mushr00m's avatar

Oooops I made the topic "resolved" but nobody answered my question 1 ^^ A bit to fast I think... Any ideas for question 1 @austenc ?

austenc's avatar

There's a lot of ways you could go about that. You mentioned you don't want to use a database, but that seems like the best option. Why not have a users table and then a UserTableSeeder that simply seeds the values (hard-coded into a config file or into the seeder itself) you want into the table? It will be much easier to extend user account functionality in the future and you won't have to make any custom auth logic.

Mushr00m's avatar

The thing is, my Users table is already filled with 50 users that can access the App but do not have right to post anything though the API. The API is only to sync content from other websites. So those other website will call the API to post some data into the DB of the App. It's not made to be accessible for users. That's why I though a hard coded login/pass per website is the most easy way. Or maybe like you said an other DB table but not the Users one.

bashy's avatar

Why not just add an API key and store it in a config or env var?

2 likes
MikeHopley's avatar

Yes, an API key seems like the way to go. Just like what Stripe does, for example.

In your case, if you are the only person who consumes the API (via your sites), then maybe you don't need the "public key" part, just the "secret key" (i.e. password).

Just a thought about using the self-signed certificate: from what you say, I think it should be fine. Just be sure to check what your website users see in the browser. You don't want any security warnings popping up!

Please or to participate in this conversation.