DEV Community

Luke
Luke

Posted on

API Design - securing user registration API endpoint with multiple clients

I'm currently working on a proof of concept system which involves a backend API which is used by multiple possible client applications, including mobile clients and a isomorphic React client.

I've largely taken care of authentication and authorization, the only remaining problem (that I can see at least) is the route to register users - POST /users/, as it is public with no authorization required. My main concern is protecting that route from malicious spamming beyond implementing CORS and rate limiting.

E.g. curl -X POST -d "{ email: 'hello@gmail.com', password: 'nahnah' }" http://host.com/api/v1/users

What would my options be here?

One solution I've come up with is force the SPA to submit the sign up form to an express route within the server that serves the SPA (it requires SSR) to make the API call on the server, meaning the browser's network tab will have no record of the API call. This would mean I'd also have to implement a CSRF token in the SPA. Or use reCaptcha?

Also, is this is just generally a bad idea?

Top comments (3)

Collapse
 
nektro profile image
Meghan (she/her)

If you are trying to reduce the chance that the URL endpoint will be used to make spam accounts, I think reCaptcha is your best bet (on the terms of its easy UX and easy to implement). Good luck whatever you choose :)

Collapse
 
mikemcguire profile image
mikemcguire

I know it's been a while since you posted this, but I found this in my own search for securing my registration endpoints. There really isn't a ton of literature online that I can find about this, or maybe my google fu is failing me. The idea of using recaptcha on an API endpoint is null and void due to the fact that APIs don't operate with a GUI.

I'm still doing some searching to find out more about best practice, but I'd be curious to hear where you landed with this.

I think a lot of this depends on how your API is designed to be used. The API that I am building is currently designed to be solely used internally. But what I currently feel as the best method of implementation is to issue client tokens to my clients. These client tokens will have a limited level of access that only let's them utilize the registration endpoint. I'm also using this method for other non auth required endpoints. After a user registers and logins the clients will the utilize the users token.

This will at least put some level of authorization behind the endpoint and prevent spam. Granted someone could reverse engineer our clients end pull the auth token out of the app and start spamming the endpoint.

You can help protect the spam via email validation and automated account cleanup.

And additional level of protection would be to have the tokens expire after X amount of time, so you'd have to setup an automated process that would issue new tokens to the clients. Which would potentially also require a new build and deployment upon reissue, which requires setting up additional automation. You could add an additional layer of obscurity by requiring the client to retrieve it's client tokens via another external service with it's own auth implementation.

But yeah this is my first time rolling my own entire auth strategy for an API that has multiple clients, and doesn't rely on any 3rd party auth services. So my thinking might be overly complex.

Collapse
 
pmigabreu profile image
Pedro Abreu

I'm currently in the same boat although my use case is a bit different as the accounts would need some manual approval, but still I don't want to have it easy to figure out the public endpoint.

I've though of, like you suggested, moving this to express and do the call from there. That should be the simplest way to hide some implementation details and hide the endpoint.

Of course there won't be a full proof (recaptcha might be a bit too much)

As mentioned I can't also find any documentation on this, seems like it should be a more usual problem