Could use some suggestions for how best to secure an API that for the time being will remain private. The backend API has been developed and will lie on its own system. The front end consumer website will have access to this API via a private API key. This is all in server side code. However, a new requirement has been made known: our website will also need to make AJAX requests to generate the code. I don't want to expose the API calls or token in the javascript code, so I'm trying to figure out options. One would be to create a REST controller on the front-end server-side which could then be called by javascript code, but this would effectively circumvent the API key security measure and therefore is not a true solution.
So what are the general practices for this? I think ideally (and I'm moving toward this, it's just not feasible time-wise currently) I would use OAuth tokens to validate requests and have some API calls(pulling in general information) not require any form of authentication etc, but even that would have some issues given the AJAX requirements. Is there perhaps some way to have client-side javascript and associated AJAX calls which will remain secure?
All this is to say - I'm currently at a loss of what to do here.
Thanks.
Edit: Current thought is to create controllers on the front end which can be accessed via ajax, which sends non-risky fetches to the API, and for risky ones relies on current user validation (e.g. user being logged in). Furthermore, logging in will not be an AJAX style request, so logging in should be a reliable security test.
You could develop a handler to accept the AJAX requests and pass them along to the private API using the normal access-token approach you would take elsewhere in non-public facing code.
That way, you don't expose the token or the API in javascript. You can build a whitelist of API calls in your handler so that it only deals with (presumably) benign AJAX requests from the front-end. This handler is both a firewall for bad requests and a way to protect the real mechanics of the private API.
If any of the API methods are potentially dangerous or destructive to data, this can (and should) be used in conjunction with the public website's authentication mechanisms.
A mockup (in PHP):
$whitelist = array(
'SomeApiCallPublicAlias'=>'RealApiMethod',
'AnotherPublicAlias'=>'SomeSafeApiMethod'
);
$call = $_POST['call']; // <-- SomeApiCallPublicAlias
if (!array_key_exists($call, $whitelist))
die('permission denied');
$data= $_POST['data'];
// hook in to the private API, pass the data, return the response
$response = make_private_api_call($whitelist[$call], $data);
die(json_encode($response));
Related
I am curious if anyone has a solution to this unique situation as I have a solution currently, though I feel it is not the most optimal.
The Situation.
I have built an MVC style web application that talks to a web API through http (authenticating via JWT). My web application is secured by appending authorization to its view controllers and redirecting to a Microsoft login endpoint - then directing back to the view where whichever given controller/function handles the request, connects to the API, appends data to the view, etc.
Preferably I would like to use JQuery/Ajax to submit http requests client-side and update a given view with whatever data the user may wish to see relative to the webpage they're on. This way I could control exactly what the user should see landing on the page any which way and submitting requests from web app to API. Also would enable better continuity between requests as there isn't actually a full refresh of the view. All in all it is my line of thought that this execution would lead to a nice user experience.
The Problem.
So the big issue that I have had to circumvent is CORS Policy. I initially attempted to use JS just as I said above but requests would be redirected to the login endpoint and blocked due to there being no CORS header appended to the request.
'So include a policy in your application and append an authorized header to your Ajax outgoing request' you might say, well... you cannot override CORS security around Microsoft's login endpoint.
My Solution.
What I have done simply instead is create HTML Forms around fields the user would pick and chose to specify what data they wanted from the API. Then carry over input data to the returned view via 'ViewData'
and using razor pages of course I can actually initialize JS variables via C# input.
Side Note
I use JS to transform the API data into graphs for the user to see. I am doing this with a JavaScript Library.
My Question to you.
This all leads me to ask then, is there a way to dynamically update a view without using JS? I require a method that can hit the login redirect without being blocked because the request initiated client-side.
Every solution I am aware in some way, shape, or form utilizes JS to make the request. So I am at a loss for how to truly get the functionality I am after without having my requests get blocked due to CORS Policy.
Thanks in advance y'all.
Given a public API which triggers OTP verification to users, is there a way to prevent such an API from abuse/spam?
This API is public and have business reasons so offering on public side.
API is developed using Java Spring MVC and has CORS enabled to allow from a specific domain. However this alone may not prevent spam hits.
Do I need to protect the API with SessionID? (but sessionId too can be easily grabbed from browser for spam)
Is there a fool proof way to detect the incoming requests are originated from a specific domain and are AJAX requests only? This could potentially limit the calls. (scripts are ruled out)
Do I need to use captcha type service?
This (preventing public API spam) appears to be a common scenario. Is there a best practice to weed out the spam calls?
Consider a web application that consists of only HTML and JS for Front end and that communicates with a Web API.
I am trying to protect my application against CSRF attacks and for that I have took reference of this article.
Using the methods in this article, I am able to generate Anti CSRF tokens and pass it to the client. However it depends on first AJAX call that must happen before making regular CRUD operation calls.
With this approach, I need some clarity on few things as well as some alternatives if any. Consider a client visits this web application (which is protected by AJAX based Anti CSRF token), and keeping his session open, he visits a malicious website that contains page that makes the same AJAX calls to get CSRF tokens (assume that attacker is aware of this process), I suppose he can use the headers to make unintended calls thus resulting in an attack.
So how can I protect my application against these?
Please provide more detail regarding this, or if its misleading then help me by providing correct details so that I can tackle it better.
First of all you should use an encrypted communication with the server so the attacker won't be able to read any header data.
If your attacker uses the same calls as you do, he is not be able to guess the anti XSRF token that you use in your calls. A new token is generated for every call to your API. I hope this page helps you with some details:
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet
I think if we use token based authentication, client have to pass authentication token in each request. And if client do not store it in browser cache and store it in localStorage then browser will not send token in call automatically. And if our service receive any request without auth token then it will discard the request.
I'm new to the whole client-side SPA world. I'm using the above technologies, which seem quite promising. However, one huge snag that I can't get over easily is the lack of built-in security. I had to manually roll out the user authorization, which IMHO should be part of the framework.
Now that I have that sorted, I'm getting major headaches with vertical security: where one user is logged in but can easily access other users' info by changing a few parameters in the browser console. I could pass the userId with every call and then compare it with the one on the server, but I was hoping that there would be an overarching solution that doesn't pollute the breeze data calls with user ids.
For example, let's say there's a call from the data service like this:
function getItems(){
var query = breeze.EntityQuery.from('Items').expand("Person");
return manager.executeQuery(query);
}
this will get all the items, not good. So let's limit by userId:
function getItems(userId){
var query = breeze.EntityQuery.from('Items').where("userId", "==", authentication.userId).expand("Person");
return manager.executeQuery(query);
}
in the second example, we get the userId from the authentication service, which stored the userId when the user was logged in. However, a malicious user can easily go the browser console and change that value.
Of course, I could pass the userId using withParameters(...) and compare it with the current one on the server, but I'd have to do that for every call, which doesn't seem right. Is there a better way to secure calls with the trusted user id?
#Ali - I understand your pain and your concern. You are right to fear any form of so-called security that relies on information passed in the URL. Fortunately there are excellent answers to your concerns and Breeze apps work well with them.
For example, have you studied the ASP.NET Breeze/Knockout Template? It uses Forms Auth for authentication and guards the Web API controller with an [Authorize] attribute. Only logged-in users can access any of the controller methods.
That authentication also sets the IPrincipal which the Web API controller makes available through its User property. You'll see User passed to the constructor of the TodoRepository. In that repository you'll find guard logic to restrict query and saves to just the Todo information belonging to the requesting user.
Look at the network traffic. You won't find any user identifying information in the URL or the request/response bodies. You will see an encrypted authentication cookie in a header.
An obvious flaw in the example is that the client/server traffic takes place in the clear. You must add transport level security (HTTPS) before you go to production. But this is a demo after all.
Why not just do this in the controller?
If the Web Api is secured with [Authorize] then you can get the users ID in the controller and make sure that the data returned is for the currently logged in user.
My question is that suppose, in my web app, I use ajax to call upon methods on the server side, isn't it creating a security hole in the app? Like, say I have an option for the user to deactivate the account, which can be done by clicking a button. This is done via Ajax.
So, can't a hacker send a request to the server to deactivate the account instead of the user?
HELP!!!
My question is that suppose, in my web app, I use ajax to call upon methods on the server side, isn't it creating a security hole in the app?
From a security perspective, there is no difference between an HTTP request that involves JavaScript and one which doesn't (e.g. that uses a regular form, or is handcrafted).
… but you can't call methods from the client, you can only make requests to URIs. The server might cause a method to be called based on receiving a request to a specific URI.
So, can't a hacker send a request to the server to deactivate the account instead of the user?
They could, which is why you need (trustworthy) authentication / authorisation and CSRF protection (just like you would for a request to disable an account that didn't involve Ajax).
This is not a problem with AJAX alone, but with any arbitrary HTTP request that wants to authenticate/maintain a session. The user needs to be authenticated in some way in order to make requests, this is usually done with cookies. Using AJAX does not make the matter any worse though because it is still a HTTP request.
Authentication alone is not enough though, someone could always be listening on the wire and capture the authentication cookie, and thus get hold of the session - "become you". The only solution here is to encrypt the connection on a lower OSI layer level (using SSL/TLS). This is why you should always use SSL when it comes to authentication.
This Ruby on Rails security guide has a great explanation on how to deal with AJAX requests that could be potentially exploited. It's not specific to RoR so the concepts can apply to any platform.
One way to reduce the risk of cross site requests is to use POST for actions that modify or delete data.