Client Side Rendering and API Security [duplicate] - reactjs

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.

Related

Is it ok to pass OAuth access tokens to the Client

i'm still pretty new to web-development I worked myself through Web Development with Node and Express by Ethan Brown and currently i'm trying to get a good understanding for the examples given by Full-Stack React Projects by Shama Hoque.
Currently i'm trying to refactor a lot of things that used to be server-side-rendered to be handled in the React SPA client. One of these things includes a simple GitHub widget, my previous flow worked like this:
The client user authenticates with my server using a GitHub OAuth app.
The server stores the access Token returned to the callback in a database on the server.
The server makes calls to the GitHub API using the user access Token stored in the database.
The server processes the results, renders it in HTML and sends it to the client.
However I realized that there is also possibility to implement it like this.
The client user authenticates with my server using a GitHub OAuth app.
The server passes the access Token returned to the callback back to the client
The client makes calls to the GitHub API using the user access token obtained from the server.
The client processes the results and renders it apropiately.
As far as I understand there is no inherent security risk doing this(a malacious user could interecept the access token when the oAuth provider redirects to the callback either way) and both flows have their up and downsides (e.g. 2nd flow produces less load on the server but also sacrifices control). Since I'm new to this and I came up with the 2nd flow myself I wanna double check if this is something thats ok to be doing or I've missed something, if so, what did I miss? Is there any other major down or upsides i'm not considering?
What you've implemented is the OAuth Authorization Flow. In this flow, the client (aka the browser) never gets the access token. Only your webserver gets it. And thus the client cannot make calls to the resource server (github). Your webserver makes the calls on the client's behalf.
You say:
a malacious user could interecept the access token when the oAuth provider redirects to the callback either way
However, if you implement the flow correctly, this is not true. This is because once you authenticate with the resource server, it only gives the browser an authentication code. This code is just a temporary ticket that can be exchanged for an access token. However, to exchange a code for the access token, you have to know a client secret. Only your web server knows the secret. So your browser sends the code to your server, and your server calls the resource server (github) with the code + secret to get the token.
The second flow you describe is the OAuth Implicit Flow.
This flow is very much what you described: After the user authenticates with the resource server, the browser ends up with the access token and just calls the resource server directly.
Both flows are very common. The Implicit flow is slightly less secure because there is more opportunity for Bad Guys to get access to the token in the browser's memory (or local storage, or cookie storage). The Authorization Flow is a bit more secure because the token stays on your server, and you do not have to depend upon users to keep it secure.

How to secure client data in Angular JS?

I have developed a single page AngularJS application. For data retrieval/storage, it communicates with REST APIs over https. As per client requirement, i need to implement Client Authentication. i.e., As the application is based on REST APIs, how can we ensure that the request made to API is from a valid client and not from fiddler or a tempered client.
the current approach is:
1> configure a client secret and a key in the angular app.
2> authenticate the client by requesting a token from server using this client secret and key.
3> server checks this secret and key, if validates, responds with a newly generated token.
4> all further requests from angularjs app would carry this token in header, to ensure that the request is from a valid client.
But it is not good enough, as attacker can easily capture the requests using fiddler and also can easily read the client secret and key. or can debug using firebug.
Is there any secure way to authenticate the client app?
No security possible in the case if your REST API call is been shield by any User Authentication. I mean if User need to put Username/Password then they are able to call those API then you can implement some security.
But if your requirement like follows :
Any GUEST user with any browser open your application pages, which intern call your REST API.
Then there is no security. Since any attacker can intercept your Request/Response and call it further.
Note : From security prepective, Whatever a Browser can do, any good attacker can do the same.
But if you shield REST CALL Pages with username/password validation, then you can restrict the calls from server side with proper session validation.
JSON Web Tokens (JWT - pronounced jot) might be what you're looking for. Auth0 has a swell blog post that specifically addresses AngularJS + JWT.
You cannot trust the client to validate anything. If the user is using Firebug or Fiddler to "trick" your application then all you can do is verify the information server side to ensure it is valid.
You can trust the client to keep the user's session safe (to some extent), but if you can't trust the user then you can't trust anything the client sends to you.
If you need to ensure the integrity of a piece of data that is held client side you can use a MAC (Message Authentication Code) which is effectively a hash of the message appended to a server-side secret key that can be later verified. Sometimes this is (incorrectly) called signing. JWTs are the current standard to accomplish this.
It depends at the end of the day what threat you are trying to keep your application safe against - if it is a game with high scores that runs on the client, there's not much you can do to prevent the user from altering their score before it is sent to the server. If you need to trust such data, run it server side.

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.

How to Secure an API Call made from a mobile application without username/password?

I have bought an API that can be used in a mobile application. API includes the Key and username as expected.
Within the app, this API needs to be called on Payment confirmation.
I found that using tools like Fiddler, one can see the request made by the application. If that is the case, it is just a matter of seconds to fully get access to the API signature.
It would be of great help if someone can help out/add to this issue.
My thoughts:
Use a server to make this API call instead of calling it directly
from the application.
If a server is used, the issue would still exist as the API call made to the server(eventually which calls the bought API) can also be interrupted/accessed
How to secure the call made to the server from the application?
Technologies: Angular JS, Node JS, Ionic framework
Look at my answer to this question. Instead of using the user name and password, your backend could provide an additional resource that allows the user to create a token with a special scope.
In your AngularJS application you can use the $http or $resource services (if the ngResource module is included) and obtain such kind of token that allows you to access only the parts of your backend your client really needs.
This token must be cached at the client side and included in the header of each request.
In AngularJS storing the token in the header of each request can be done at a central place if you are using the config function of the module you created.
app.config(function($httpProvider) { $httpProvider.defaults.xsrfCookieName = "TOKEN" }
AngularJS also provides some additional security features. For example you could use the JSON vulnerability protection mechanism. If you are using this, your backend had to add the characters )]}', (you could also override the default characters) to each JSON response body.
For other clients the JSON response will be invalid Javascript code, but in your AngularJS application the characters will be automatically removed.
UPDATE
The best way for implementing security for your application would be reading and understanding the OAuth2 specification.
In this video from minute 11:36 to 17:26 the JavaScript flow is described.
This site provides some implementation of the standard for different programming languages.
Some of the aspects in this standard are that all clients and redirect urls must be registered in an additional authentication server. Client are identified by a unique client id.
To avoid that some other application intercepts your requests for extracting the token, the original token should only be active for a small amount of time and each api request must be SSL encrypted.
For providing Single sign-on also refresh tokens can be used.

Secure REST API without user authentification (no credentials)

I've been struggling for 2 days now on how to secure a REST API without user authentification.
What does it mean ?
In my AngularJS application I identify an user by sending a GET request to an existing service (companydomain/userinfo) which I must use. I'm not sure how this work since I am not the author of this piece of code but the point is that I get the information about the user in the response as JSON (active directory name, phone in the company...).
This is all I have to identify an user.
What I did
Now, I found a lot of resources talking about OAuth, unique token, etc. but nothing seems to match with my issue. I implemented a token system but it's plain useless since I can't be sure of the authenticity of the requester.
User open the application. Application ask the service about the information related to the user. companydomain/userinfo
Application request a token to the server (nodejs & express), based on the information returned. /api/token/get/{user_info}
Server generates an unique token and store it in memory with expiration date and owner. The server also check in the table "authorized users" if the user exists (based on the active directory name), if not a new entry is added to it.
Application send the token along each request to the API. /api/entry/delete/{entry_id}
I think you see what is wrong here, an attacker could easily make a corrupted request to the API to get a legit token. So my question is :
How can I manage to secure my API since users don't use credentials to authentify ?
I hope my question is clear enough and at this point I am not even sure I can get around this issue without adding a credentials system.
You might want to look at Passport. It is a platform that allows you to easily add authentication to your application. There are many authentication strategies available. I am using Passport in a Node.js application implementing my own hmac strategy.
To authenticate, the client request includes an API ID to identify who the caller is and also includes an signature of a specified part of the message that includes things like the HTTP method, the API ID, a date value and some other header values, like maybe content-type. What data to include in the string to sign is up to you in your implementation, but the client and server must create and sign the same strings for the authentication to work. The signature is created by doing an hmac hash of the string using a shared secret.
On the server side, you use the API ID to retrieve the shared secret (possibly from a database or the filesystem) and perform the same hash on the request. If the hmac values match then you've authenticated the request. To prevent playback attacks, the date is included in the signed part of the request and must be within a certain window of the server's current time. For example, you might reject the request if the timestamp is more than 30 seconds old.
To enable a new user of your API, you generate a new API ID and shared secret. You give both of those to your API user and you store them for look up in your database or filesystem. The user must sign the requests with the shared secret and include the ID in the request.
The Hawk strategy provides much of this functionality, but we decided to roll our own hmac strategy.
Because you say that the user info endpoint returns active directory name, I assume you're on the Windows platform.
If so, why not use Windows integrated authentication (Kerberos) to authenticate your users without asking them for credentials? This will only work within your active directory domain, but is completely transparent to your service.
You can still call the user info endpoint and verify that the info it returns is for the same user that is calling your REST service.
If you need to call services that do not support Windows integrated auth, you could generate a security token (sign it to guarantee integrity) and make the other services trust this token.

Resources