how do I protect a public API from abuse? - ajax

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?

Related

How to make Web Api secure against CSRF attacks in ASP.NET?

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.

Malicious requests detecting/validating requests

Application has front-end and back-end modules, front-end calls rest services from the backend written on Java/Spring.
Is there any best practices how to detect malicious request generated not by the front-end (if some user try to call service direcly from the back-end via rest client)?
Maybe generating some hash value for every request on front-end and decrypt this value on back-end validating this request?
What you need is authentication. The backend needs to authenticate either the frontend web app, or the user itself.
Probably the most common way is authenticating the frontend, which practically means that frontend and backend have a shared secret, authentication takes place upon each call, and the backend trusts the frontend. This can be achieved in countless ways from http basic auth (over https of course) to some kind of an api key mechanism (signing requests, etc.) You don't have to reinvent the wheel, depending on your usecase and threat model, http basic auth over https may very well be enough.
Another way to do things is to delegate user credentials to backend services. This is most often achieved by passing single sign-on tokens from the user to the backend, effectively impersonating the user when the frontend calls backend services. Arguably this is more secure, as for instance it does not need that level of trust between web and app, but services still need to trust the SSO component that issued the token. The point is that there is no secret for an adversary to steal (let alone from the frontend server, which may be an easier target), so it may be more difficult for an attacker to issue requests to backend services, even if some backend and/or frontend servers are already compromised.
So while I think an answer here is not the right format to go into details about how exactly to do this authentication (there really are multiple good solutions, and in every case, implementation details matter very much), at least conceptually these are your options I think.

How can I protect my WebAPI from abuse and avoid sharing API keys?

I have a Web API written in C# and hosted in Azure with Azure API Management (AAM) sitting in front of that API and throttling requests.
The clients that call the API will be javascript based and will be calling on behalf of anonymous end users. For example, the home page of a web site might call our API via javascript to present information to an end user without asking them to login.
AAM ensures that callers to the API have a valid API key. There is the potential for this key to be copied and abused though if someone grabs it from the publicly visible source.
Is it possible to use OAuth2 to obtain a JWT Access Token without human intervention and for this to be exposed on the client?
OAuth2 can issue expiring JSON Web Tokens which would lower the risk of token theft, but I'm struggling to get this going without any human intervention.
OAuth2 is mostly about end user initiated authorisation but IdentityServer3 seems to have a Hybrid approach. Could I use this Hybrid approach to get the remote web server to request a token by sending the API key from server to server first and then outputting the JWT in the web page for use by the client side script?
This would then hide the API key and only show a JWT that is of use for a few minutes.
AAM can integrate with OAuth2 and inspects JWT Access Tokens, but I don't think it understands this Hybrid flow (it may not need to as we won't be asking for user logins).
Or should I just give up and rate limit requests only?
If you can generate these hybrid JWT keys without user intervention then API Management can validate them and use one of the claims as a key for doing rate limiting. Normally rate limiting is done based on API Management subscription keys, but the new advanced rate limiting policies allow you rate limit based on any expression.
I'm not familiar with how the IdentityServer hybrid mode keys work, but usually if there is non-interactive login, then there is some kind of secret that needs to be protected. This is always a challenge when running code on the client.
The API Management HTTP API does have a method to regenerate keys. You could use this to implement your own token expiry mechanism to limit the impact of key theft.

ASP Identity OAuth token - Should I use ValidateClientAuthentication() and Secret in mobile app flow?

I have a mobile app which talks to an ASP WebAPI on the back-end.
I've implemented the token flow authentication (with the help of Taiseer's guide).
Still there is one concept I can't grasp my mind around: CleintId and ClientSecret.
From what I understand the client secret (along with client id) is meant to
block access to the end point in my API that produces tokens. This way the end point is protected from malicious users trying to poke around the API and try to gain some information by invoking it with various inputs.
Meaning, only clients which hold the secret can start an authenticaon flow. And in my case, I have only one client which is a mobile app, and it's secret is stored in a secure place (KeyChain for iOs). But I've read that those key chains can be easily dumped and dissect for the secret.
So the conclusion I came up with, is that I can get rid of the whole client secret logic, mainly leaving ValidateClientAuthentication() blank:
public async override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
return;
}
And to me it dose not seem like a security hole, but just a thin layer in the flow that is gone now. Because, again, the client secret can be easily revealed by any malicious user holding a mobile device with the app installed, and once he gets it this layer of security is useless.
Are those assumptions are incorrect ?
Can I leave the ValidateClientAuthentication() method blank ?
As you already figured out, mobile applications cannot keep their credentials private because they can be extracted from the application binaries. Not to mention that requests can be easily intercepted using a proxy server and a traffic analyzer like Fiddler or Wireshark.
With the authorization code flow (1) or the resource owner password credentials grant, client authentication is not mandatory if the client cannot safely store its credentials and thus cannot be considered as a "confidential" application (see https://www.rfc-editor.org/rfc/rfc6749#section-4.1.3 and https://www.rfc-editor.org/rfc/rfc6749#section-4.3.2).
For non-confidential applications, it's safe to call context.Validated().
Personally, I try to avoid the resource owner password credentials grant as much as possible as it clearly defeats the purpose of OAuth2: keeping your password confidential and giving constrained authorizations. If your app is fully trusted, it shouldn't be a problem, though.
In practice, using the authorization code flow without enforcing client authentication is extremely rare, as it's simpler to use the implicit flow with mobile client applications, that offers a similar security level in this case (not to mention that it avoids a second roundtrip to the token endpoint).

Securely accessing a private API from my own consumer website using AJAX

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));

Resources