Secure API Call in React JS - reactjs

I have an API that I want to make a request to from my frontend, which is built using React. However, I don't want anyone to be able to see the API call in my code, because if someone just opens the inspect window, then they can see the API call. I've thought of perhaps adding some sort of header to be sent as authentication in the request, but that doesn't work either because you can just see the code if you inspect the site.
How would I do this? My API returns a private key that I can't just store in a variable directly within my code.
Sorry if this question doesn't make sense, but I appreciate all the help.

Your frontend code is insecure and observable by default. There is no secret in the frontend.
If your API returns confidential data that should only be accessed by the appropriate user you will have to implement authentication of any sort.
A user would then for example provide a password in order to call the API or he logged in before and got a token (e.g. JWT) that he sends with every request to authenticate. There is a user identity on every request then and your backend can decide if the user is allowed to get that private key.
If you really really want to make it difficult for someone to see your frontend code your router might provide a feature like "protected routes" that require such a token in order to access certain routes of your application. It will still always be possible to get the frontend code because the business logic has to stay on the backend.

Related

How do authentication tokens and authorization work in reactjs?

I'm new to reactjs and I've ben trying to understand how the authentication token works to protect routes. In various tutorials people get that token from an api when logging in a user, and then store it along with a "isAuthenticated" variable set to true in localStorage. Then when routing they check if isAuthenticated is true, without any api call to verify the token. Is that safe? I was trying to implement authorization in the same way, by just adding some isAuthorized variable, but can't both of these be tampered with since react works client side?
Of course they can. Whatever is on the client is fully controlled by the user. There is no "client-side authorization". Such features (access control to certain functionality on the client) is usually a user experience feature, like why show something to the user that won't work anyway.
All authorization must be done server-side.
This inherently means that it's usually ok to have page structures (views) without data in the client for anybody to see, the point is that data from the backend will be authorized and will only be available to appropriate users.

Client Side Rendering and API Security [duplicate]

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.
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.
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.
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]
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.
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?)
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.

Authentication using React and Pyramid (microservices architecture), how to store "session data"?

How are you?
Me..? Well, I'm having some trouble, haha!
I'm using a microservices API architecture on a project where the APIs and GatewayAPI is developed with Python's Pyramid framework, and the main frontend is built with React.
Simple workflow ilustration: https://imgur.com/ifRLLOo
The problem is: where do I safely store the authenticated "session data", like username, user_id, first_name? After logging in, I don't want to make new requests to the user's API just to get these information that will be constantly used.
I know I can store this coded data in the JWT token and store the token in the cookies or the localStorage, but is this the right place? And is this the right process?
If this is the right place, do I need, everytime, to send the decoded data to the frontend as part of the GatewayAPI response?
Thank you for the reading and I hope you guys can save me!
You can store the JWT in a cookie or localStorage it does not matter. I personally do so in localStorage.
Regarding your question about decoding the data, this is handled by the backend. All you need to do is include the JWT in every API call and the API will know which user is calling without the need to send the data back and fort.
I would also recommend you create tokens with an expiration date for added security.
For examples you can take a look at pyramid_jwt

REST API in MEAN stack, passed id vs id from session

I'm building a web app using MEAN stack.
While building the REST API I see a lot of examples with the following endpoint
/api/contacts/:id
for GET, PUT and DELETE methods.
I did something different, I enabled session in the Express framework and now I can see the user document id (for mongoDB) under req.session.req.payload._id when I do a HTTP request which enables me to access the document.
That why I also don't need to expose the user document id in the URL when I do
a HTTP request.
My question is which method is better and safer to use?
Also, how can I get the user id in Angular to pass to the HTTP request in case I don't use sessions.
And a final one... I also use JWT as middle-ware before calling the function which updates the DB. This gives me some sense of security but wouldn't it be possible for a user with the correct token to do HTTP requests with different ids and by that getting, updating and deleting other users data?
This won't be possible with the current method I'm using (sessions)
When you need to pass the user ID to the endpoints then your client code will need to know that and it's the backend that needs to provide it somehow - either as part of the returned toked or usually as part of the response to a successful login request. The client can store it in a cookie or a local storage to use later.
It is not very practical, though, to have to provide the ID of the user in every route like:
/api/contacts/:id
When your users need to be able to access other users contacts then you may need to use the ID in the route and you may not want to have another set of routes for a situation when the user wants to manipulate his or her own contacts.
What I've seen sometimes done in practice in situations like this is to use a special value for the ID like "me" and have your backend translate all routes like this:
/api/contacts/me
to:
/api/contacts/:id
where :id is the ID of the user who made the request, taken from the session. This can be done with a middleware to substitute the value for all routes at once, and then your normal controllers could use it like it was provided in the route to begin with.

How to protect my api call from CSRF attack

I am working on angular js app,and tried to make a simple login page and tried to request my server API for authenticate my login call.Here what and how i planned to do.
Note: I am assuming that server is responsible for validating my token and request.
Provide username password to server via API call.
On getting authenticated the server will generate a token for my App(through which i made a call).
I stored this in my browser's COOKIE.
This Cookie (auth token) will be further used by app to to make each and every HTTP call to API.
Now this approach is working fine for me,but I believe it is openly available for CSRF attack.
In order to avoid the CSRF attack from my browser,i provide APP id or (version id) to my code which also travel with cookie to the API for http call.
The idea behind using this version id or App id,is this can be treated as a signature of my code,ie request is coming from the signed (verified) app who has alloted token=cookie value.
i just want to know how better my approach is and how much secure it is for my basic app point of view and for my major (wide project) app.
Here i am trying to show via a rough diagram
apologies for this tiny view and bad handwriting of the diagram.
Backend frameworks like Laravel have this pretty built in: csrf-protection.
You can pass the token to Angular by using angular's constant function: $provide#constant.
So after you initialize your app you could say: angular.module('myApp').constant('<?php echo csrf_token(); ?>'); and Laravel would do the rest. If you would want to implement a technique like this yourself, you should look into Laravel's source code: https://github.com/laravel/framework/blob/a1dc78820d2dbf207dbdf0f7075f17f7021c4ee8/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php.
Adding App ID + Version ID to each request won't protect your system from a CSRF attack, unless these are in a custom header - and if they are you might as well just use X-Requested-With because any non standard header is protected going cross domain, provided you haven't enabled CORS with an open policy.
The reason that checking App ID + Version if set in the query string or POST data is that the attacker can readily gain this information to add the App ID + Version ID to their cross site requests. Another method that would work for you is the Double Submit Cookies technique. Generate a random 128 bit string using a CSPRNG and then set this as a cookie value (e.g. CSRFCookie). On each request to your API, also pass this value. e.g. in the query string: CSRFCookie=<generated value>. On the server side you simply check that the values match. An attacker does not know the cookie value, therefore they cannot add the same value to the query string.
This method does have some minor vulnerabilities, only really exploitable in a MITM scenario or if you do not control all subdomains. Short answer: Use HTTPS only for all your subdomains and implement HSTS.

Resources