ChatGPT解决这个技术问题 Extra ChatGPT

How do I secure REST API calls?

I'm developing the restful web app that using some popular web framework on the backend, say (rails, sinatra, flask, express.js). Ideally, I want to develop client side with Backbone.js. How do I let only my javascript client side interact with those API calls? I don't want those API calls to be public and be called by curl or simply by entering the link on browser.

Have all your API calls require a token that is passed to the client when your page is served?
Amazon AWS javascript SDK uses pre signed object URL :- docs.aws.amazon.com/AmazonS3/latest/dev/…

C
Community

As a first principle, if your API is consumed by your JS client, you have to assume, that it is public: A simple JS debugger puts an attacker into a position, where he can send a byte-for-byte identical request from a tool of his choice.

That said, if I read your question correctly, this is not, what you want to avoid: What you really don't want to happen is, that your API is consumed (on a regular basis) without your JS client being involved. Here are some ideas on how to if not enforce, then at least encourage using your client:

I am sure, your API has some sort of authentication field (e.g. Hash computed on the client). If not, take a look at This SO question. Make sure you use a salt (or even API key) that is given to your JS client on a session basis (a.o.t. hardcoded). This way, an unauthorized consumer of your API is forced into much more work.

On loading the JS client, remember some HTTP headers (user agent comes to mind) and the IP address and ask for reauthentication if they change, employing blacklists for the usual suspects. This forces an attacker to do his homework more thoroughly again.

On the server side, remember the last few API calls, and before allowing another one, check if business logic allows for the new one right now: This denies an attacker the ability to concentrate many of his sessions into one session with your server: In combination with the other measures, this will make an abuser easy detectable.

I might not have said that with the necessary clarity: I consider it impossible to make it completely impossible for an abuser to consume your service, but you can make it so hard, it might not be worth the hassle.


this is helpful info , but what if i want to make some auth from my backend api to another api app like a separate server , to simplify my question , i want my back-end aka node.js to send fetch request to another back-end server which is my own , for some reasons this is needed , but i want to secure the api calls , as it can access sensitive data , and i can't use sesions or jwt because i can't store them actually in browser.
@Thepyramid It doesn't matter, what the API call does on the server side, especially if the server side does another 2nd-ĺevel API call. The important part is to treat your server not as a proxy, but as an application.
can you explain more how to make as application not as proxy
What I mean is: To get a decent amount of security you need to employ all tools, that a webapp has: Sessions, an auth database, a business logic. If don't do that and just treat your server as a way to pass requests to another server, you are just using it as a proxy for that other server and are limited by whatever security that other server offers.
@PirateApp An attacker can easily just ignore the CSRF headers. They work only, if the end device is an unpatched browser
g
gview

You should implement some sort of authentication system. One good way to handle this is to define some expected header variables. For example, you can have an auth/login API call that returns a session token. Subsequent calls to your API will expect a session token to be set in an HTTP header variable with a specific name like 'your-api-token'.

Alternatively many systems create access tokens or keys that are expected (like youtube, facebook or twitter) using some sort of api account system. In those cases, your client would have to store these in some manner in the client.

Then it's simply a matter of adding a check for the session into your REST framework and throwing an exception. If at all possible the status code (to be restful) would be a 401 error.


Although there's nothing stopping them from looking at the headers and reproducing them.
@cdmckay - A token has to match a token stored in a session. Simply reproducing the header will result in "Unauthorized" response if it comes from a different session.
They can still use the same session and alter the requests before they are sent to the API though... or even using the console at runtime generate a call with matching headers/fields modifying only the parts you need...
@PotterRafed: If a user accesses his or her own valid session, that is called using an app, not attacking it. The purpose of authentication is to prevent access to other users' sessions/data.
@AndreiVolgin yeah fair enough, but it's still a vulnerability
b
bbozo

There's an open standard now called "JSON Web Token",

see https://jwt.io/ & https://en.wikipedia.org/wiki/JSON_Web_Token

JSON Web Token (JWT) is a JSON-based open standard (RFC 7519) for creating tokens that assert some number of claims. For example, a server could generate a token that has the claim "logged in as admin" and provide that to a client. The client could then use that token to prove that they are logged in as admin. The tokens are signed by the server's key, so the server is able to verify that the token is legitimate. The tokens are designed to be compact, URL-safe and usable especially in web browser single sign-on (SSO) context. JWT claims can be typically used to pass identity of authenticated users between an identity provider and a service provider, or any other type of claims as required by business processes.[1][2] The tokens can also be authenticated and encrypted.[3][4]


What would prevent a user from copying their token and using it in any other response?
@UladKasach to be honest I never went really deep into them, but afaik they're expireable, unique for your user, and encrypted by SSL (which you're of course practicing), it's the exact same idea behind oauth afaik
A
Alex from Jitbit

Set a SESSION var on the server when the client first loads your index.html (or backbone.js etc.) Check this var on the server-side on every API call.

P.S. this is not a "security" solution!!! This is just to ease the load on your server so people don't abuse it or "hotlink" your API from other websites and apps.


C
Community

Excuse me @MarkAmery and Eugene, but that is incorrect.

Your js+html (client) app running in the browser CAN be set up to exclude unauthorized direct calls to the API as follows:

First step: Set up the API to require authentication. The client must first authenticate itself via the server (or some other security server) for example asking the human user to provide the correct password. Before authentication the calls to the API are not accepted.

During authentication a "token" is returned.

After authentication only API calls with the authentication "token" will be accepted.

Of course at this stage only authorized users who have the password can access the API, although if they are programmers debugging the app, they can access it directly for testing purposes.

Second step: Now set up an extra security API, that is to be called within a short limit of time after the client js+html app was initially requested from the server. This "callback" will tell the server that the client was downloaded successfully. Restrict your REST API calls to work only if the client was requested recently and successfully.

Now in order to use your API they must first download the client and actually run it in a browser. Only after successfully receiving the callback, and then user entry within a short frame of time, will the API accept calls.

So you do not have to worry that this may be an unauthorized user without credentials.

(The title of the question, 'How do I secure REST API calls', and from most of what you say, that is your major concern, and not the literal question of HOW your API is called, but rather BY WHOM, correct?)


The second point makes no sense. If an attacker needs to load your app, he will do it (your callback is visible). And then attack.
Point 2 is in addition to point 1. The attacker still needs authentication. Point 2 only adds to that the need to actually download the html app in order to be authorized. So a call directly to the APIs without the app (presumably accessed and downloaded only after authentication) is impossible. Which is something that was requested in this question.
You can simply allow requests from your domain only.
That only limits the calls to inside the domain, so now the javascript browser-app users must be inside the domain (probably not something knd wanted) and those users can still call the API directly via curl.
What you seem to overlook is, that WHATEVER you ask your user's browser to do, can be replicated by an attacker - to make the browser do it, it must be readable.
P
Pavneet Singh

Here's what I do:

Secure the API with an HTTP Header with calls such as X-APITOKEN: Use session variables in PHP. Have a login system in place and save the user token in session variables. Call JS code with Ajax to PHP and use the session variable with curl to call the API. That way, if the session variable is not set, it won't call and the PHP code contains the Access Token to the API.