I'm building a React.js application that will interact with my REST API built in Go.
React will use Javascript Fetch API to send requests to my API.
The problem is I would like to secure my API from being requested from elsewhere. No one should directly be able to access my API either through the URL or through any other client like Postman.
I know what JWT is but this does not solve my problem because anyone can access the token through the browser and then continue to request the API outside the React client using the token.
I have researched extensively but nothing has really fit my description.
Thanks a lot for you help, in advance.
This is an inherently unsolvable problem. React runs on the client. The client controls the code that it executes. Hence, any mechanism you use to restrict the API usage to just your React client will be discoverable and reusable in other client contexts. You cannot control the client, and attempts to do so will be broken if the payoff is valuable enough.
You can attempt to harden it somewhat by using short-term authorization tokens, but there is nothing preventing that token from being grabbed and reused in another context.
If you have to restrict access to an API, you should have a public API which is less dangerous or privileged, and the public API should make use of your private API, effectively proxying the calls to hide the private API, as well as to ensure that only validated queries are executed against the more privileged API.
If you could describe the problem you're trying to mitigate, though, there may be other solutions available.
Related
I am writing a REST API using Express Js and I have some questions regarding security.
My first question is what information can hackers get from a request made from the client side. Can they figure out the request link? What about the body and headers? Is body more secure than parameters/vice versa?
My second question is if I implemented a CORS whitelist that only allowed origins that I wanted to access my API, would that prevent anyone else from hitting the API endpoints? Can people find ways around CORS?
When a REST api is called from a browser client, everything should be treated as completely open. Anyone can read urls, headers, bodies, etc. There is no reasonable way around this, and you should design your system with this in mind.
CORS does not prevent someone from writing a script to call your API either. CORS does not add security, it takes it away by making it possible to call your API from browser applications on other domains. Not having CORS technically makes it harder to call your API in some contexts, and removes a potential security concern. The S in CORS stands for 'sharing', not 'security'.
Any security you need should be based on the server. For example, if you have data in your API that can only be read 1 user, then the server needs to make sure that a different user cannot read it. To do this, a user needs to authenticate itself.
I am developing a web application with Spring Boot and a React.js SPA, but my question is not specific to those libraries/frameworks, as i assume reporting client-side JS errors to the server (for logging and analyzing) must be a common operation for many modern web applications.
So, suppose we have a JS client application that catches an error and a REST endpoint /errors that takes a JSON object holding the relevant information about what happened. The client app sends the data to the server, it gets stored in a database (or whatever) and everyone's happy, right?
Now I am not, really. Because now I have an open (as in allowing unauthenticated create/write operations) API endpoint everyone with just a little knowledge could easily spam.
I might validate the structure of JSON data the endpoint accepts, but that doesn't really solve the problem.
In questions like "Open REST API attached to a database- what stops a bad actor spamming my db?" or "Secure Rest-Service before user authentification", there are suggestions such as:
access quotas (but I don't want to save IPs or anything to identify clients)
Captchas (useless for error reporting, obviously)
e-mail verification (same, just imagine that)
So my questions are:
Is there an elegant, commonly used strategy to secure such an endpoint?
Would a lightweight solution like validating the structure of the data be enough in practice?
Is all this even necessary? After all I won't advertise my error handling API endpoint with a banner in the app...
I’ve seen it done three different ways…
Assuming you are using OAuth 2 to secure your API. Stand up two
error endpoints.
For a logged in user, if an errors occurs you would
hit the /error endpoint, and would authenticate using the existing
user auth token.
For a visitor, you can expose a /clientError (or
named in a way that makes sense to you) endpoint that takes the
client_credentials token for the client app.
Secure the /error endpoint using an api key that would be scope for
access to the error endpoint only.
This key would be specific to the
client and would be pass in the header.
Use a 3rd party tool such as Raygun.io, or any APM tool, such as New Relic.
Say you're developing an application which consists of a backend HTTP API, which serves a frontend UI. The UI, upon being rendered on the client's browser, will need to make certain calls to the backend (e.g., fetch data for views). However, all these calls are can be checked on Chrome's developer console, for example. This exposes my application's overall logic and internal API endpoints.
Is this a concern for a web application? I looked around some other websites (e.g., Reddit) and I was indeed able to check an API call was being made and I even managed to reproduce it via cURL, getting the same response back.
My first idea to solve this would be to encrypt all data and have it decrypted internally in the frontend app. However, I don't think this would provide much security since the private key would have to be hardcoded in the app's source code, which can also be checked by modern browsers. Besides, this could greatly impact the application's performance.
The best I could think of was to somehow assign a token (JSON Web Tokens, maybe?) to the session (which in turn is assigned to a user). This token would be needed to make the API calls, and maybe it could have a short expiration time. However, the token can still be seen in the HTTP request.
Any ideas?
I am using bcrypts => https://www.npmjs.com/package/bcryptjs + jsonwebtokens in my MEAN app for the same. Bcryptjs creates a salt at the server side and send an encrypted token to the client. The same token is used for API calls. This makes decoding a bit harder for any phishing attempt.
Use HTTPS instead. => Are querystring parameters secure in HTTPS (HTTP + SSL)?
We intend to develop rest based api. I explored the topic but it seems, you can secure api when your client is an app (So there are many ways, public key - private key etc). What about websites / mobile website, if we are accessing rest based api in website which do not use any login for accessing contents ( login would be optional ) then how could we restrict other people from accessing rest based api ?
Does it make sense using Oauth2.0 ? I don't have clear idea of that.
More clear question could be ,How can we secure get or post request exposed over web for the website which doesn't use any login ?
If it's simple get request or post request , which will return you json data on specific input, now i have mobile website , who will access those data using get request or post request to fetch data. Well, some else can also access it , problem is i am not using Login, user can access data directly. But how can we restrict other people from accessing that data.
What do you think is the difference between securing a website that is not using REST vs one that is using REST API?
OAuth provides authorisation capabilities for your site, in a REST architecture this means a user of the mobile application will have to provide their credentials before being allowed to access the resource. The application can then decide on if that user has access to the requested resource. However you've said your website doesn't need use authorisation.
You can use certificates however good luck managing the certificate for each client. My take on it is for your explanation you don't need to secure your website because you will never be able to manage a trust relationship between the client and the server. There are some options though:
You build your own client application that you ship out to people which can verify itself with the server using a packaged certificate with the client. E.g. iOS has this kind of feature if you build for that device.
You provide a capability to download a certificate that is 'installed' in the browser and used when communicating to your REST API
Use something like a handshaking protocol so when a client wants to make the first request it says; 'hi I'm a client can we chat?' And the server responds with 'yes for the next X minutes we can however make sure you send me this key everytime you tell me something YYYYYY' (you can use something like SecureUDID or equivalent for other devices than iOS).
There are probably others but you get the basic idea. Again in my opinion if your resource doesn't need authorisation then you don't need to secure that REST API. Can I ask what kind of data are you exposing via this REST API or functionality your providing? That might help provide a better answer.
You want authorization: only some agents (mobile clients) and/or users should be allowed to access those APIs.
To solve that problem, you need identification: a way for the server to tell who is who (or what), so the right decision can be made.
There are many different way to provide some form of identification, depending how much you care about security.
The simplest is a user agent string, specific to your mobile clients. But it can be faked easily. Slightly harder to fake are client based 'secrets' - embed some kind of secret or key in your mobile client code. You can make it really complicated and secret, but as ramsinb pointed out, you can't get security this way as it would require you to be able to guarantee that the secret you're shipping with the client (wether it's code, algorithm or any other fancy construct) can't be compromised or reverse engineered. Not happening when you don't control the client.
From there, 3 choices:
Security isn't really required, don't bother
Security isn't really required, but you still want to limit access to your API to either legit users/agents or people ready to invest some time hacking your protection - go with a specific user agent or a client embedded secret - don't invest much into it as it won't block people who really want access to get it anyway
Security IS required - and then I don't think there is a way around authentication, wether it's login/password, user specific (device specific?) keys, OpenID, etc... No matter what, you'll have to add to the user burden to some extent, although you can limit that burden by allowing authentication to persist (cookies, storage....)
I have a COTS application(PLM application) which has provided few SOAP APIs to access. Since this SOAP API is highly complex, we are developing a easy to use REST wrapper service. Before invoking any API in my COTS application, authentication API needs to be invoked. In my REST wrapper web service, I have a login resource which invokes COTS SOAP login API. To keep things simple for my API users, I store the logged in user details in user session. In every other REST resoruces, I retrieve the session and check whether session has user details. If yes, I proceed and invoke the SOAP API. if not, I return proper HTTP status code. I use Apache CXF for service and client. I mandate my APIusers to maintain the session in the client like this
WebClient.getConfig(client).getRequestContext().put(Message.MAINTAIN_SESSION,
Boolean.TRUE);
In every REST tutorials, it said REST is stateless. I am doubtful whether what I am doing is correct as per REST standards. Please suggest. Thanks
Basically the idea of REST is a stateless interface. However it is common practice to use some kind of authentication for API calls since most of the time not all resources should be public (e.g. the timeline of a twitter user over the twitter API)
Therefore it is ok if you do some kind of authentication and validate a session on further requests (or maybe authenticate with every single request, e.g. with HTTP Basic Access Authentication) to check if access should be granted.
Not part of this and not the idea of a RESTful API would be to store complex session information that would really make the whole thing stateful. This for example includes storage of information of an older request for processing together with one following later.
client.getRequestContext().put(Message.MAINTAIN_SESSION, Boolean.TRUE)
This code causes cookies to be maintained in that specific client only.
If you want those cookies be available in another client, it needs to be programmed.
And if the second client receives additional cookies and you want those cookies available in the first client too, how is that possible?
I need something like a root client that maintains cookies of all sub clients. All cookies must be shared among all clients. Like a shared cookie repository for all clients. Does anyone know how to achieve this?