Secure Ajax call On Rest Api - javascript

This question has been asked to me in a interview. i search on web but can't find a thread that explains it in a way that makes sense to me.
Suppose is i had a web service which return a list of something and available
In public Domain(Any body can use That) For security User need A key to Access that web service.
How can i use That web service securely in Ajax.
Problem is if i use Ajax to access that web service any body can able to see my private key,
I suggest for a encryption but i have to pass that key in decrypt(as i get )in form
Than i suggest for a mediator file(at server side) on which i can call that web service but what if somebody directly access that mediator file (i know same origin policy )
i really want to know what are the possible solution to overcome to these problem and what is best practice to make a secure ajax call on rest

In fact, there is a dedicated security flow in OAuth2 for this particular use case called "Implicit Grant Flow".
You could have a look at these links for more details:
http://www.bubblecode.net/en/2013/03/10/understanding-oauth2/#Implicit_Grant
https://www.rfc-editor.org/rfc/rfc6749#section-4.2
If you don't use OAuth2, you can propose the user to authenticate and get back an access token. You could store it within the local storage of your browser but you need to be very careful with XSS. This question (and its answers) could provide you some hints regarding such issue: What are (if any) the security drawbacks of REST Basic Authentication with Javascript clients?.
Hope it helps you,
Thierry

We are using cookies for this. And like the Session we have stored the secure key on the Web-Server. With the Cookie we can get the secure key. So he just see the "key" of his key. There is no option to hide all information from the client. But you can show him information, he cant use directly.
But at all, there is the fishing problem. If someone fishes your cookies, he has your "key" of your secure key. Many others are doing it simular. E.g. Facebook.
This is not specific for Ajax calls, but since it works for both, normal GETs and AJAX Calls, it would be a solution.

If you do not have 100% control of both client side and server side, you may want to use client-side authenticate solution (e.g. Oauth 1 or 2).
If you do have 100% control of both client side and server side, easy way is to use basic authenticate + SSL.
What our project is :
- I have a restful service. We provide restful service in SSL.
- Only our partner companies can use it through internet.
What we did is:
- They have their username/password in their request (is a Ajax) in their internal application (not public-accessed web page)
- sample as following restful code (you can test by Postman):
// to inject request
#Context
private HttpServletRequest request;
#GET
#Path("/testAuth")
#Produces(MediaType.APPLICATION_JSON)
public Response testAuth() {
// TODO
// this is only a template for doing authentication in the near future
String returnString = "";
//check if authenticated
String authorization = request.getHeader("Authorization");
if (authorization == null || authorization.toUpperCase().startsWith("BASIC ") == false) {
//no authenticated
returnString = "{\"testAuth\", \"need authentication\"}";
return Response.status(401).entity(returnString).build();
} else{
String credentials = authorization.substring("Basic".length()).trim();
byte[] decoded = DatatypeConverter.parseBase64Binary(credentials);
String decodedString = new String(decoded);
String[] actualCredentials = decodedString.split(":");
String ID = actualCredentials[0];
String Password = actualCredentials[1];
String Result = userAuthenticate(ID, Password);
returnString = "{\"testAuth\", \"" +
" (" + Result + ") \"}";
return Response.status(200).entity(returnString).build();
}
}

Related

Authenticate requests from frontend that doesn't have tokens

Not sure if the title summarises my question well.
Basically, I am trying to authenticate routes such as checking if user exists etc. I only want to allow
requests coming from my frontend application to be approved, but, since no user is signed in there is no token to send.
Api request -
mywebiste/checkUser/email
This route is unprotected on my backend because no user is logged in.
BUT I want to protect this route, in such a way that it's accessible only from the frontend.
Some ideas I came up with were adding specific headers tag from the frontend and check them on the backend, but that could be easily replicated, is there something more secure like using tokens etc.
I am using React and Node.js
Same origin policy is going to give you some basic protection, but basically if an API endpoint is exposed publicly, it's exposed publicly. If you don't want that route to be publicly accessible you need to add access control.
If you use that route to check if a user is already registered, you could, for example, merge it with the user registration route and send a different error code if the user already exists (which is not a great idea because it leaks which emails are registered on your system).
You can verify that a request was originated by a user (by authenticating him) but you cannot verify that a request comes from a particular client because of these two reasons :
If you include some API key in your client (web page or other), it's easily retrievable by everyone (the best thing you could do is offuscate it which makes things slightly harder but still possible)
If you send an API key over the network it's easily retrievable as well
The only thing you could do is prevent other web pages from calling your backend on behalf of the user, by using CORS (which is actually active by default if you dont specify an Access-Control-Allow-Origin header)
I ended up creating a kind of working solution, so basically, I create a new base64 string on my frontend and attach that to the header while making a request to the backend. The base64 string is different every minute, so even if the header is copied, it differs every minute and is combined with your secret key.
I have made a package so that people can use it if they want - https://github.com/dhiraj1site/ncrypter
You can use it like so
var ncrypter = require('ncrypter');
//use encode on your frontend with number of seconds and secret key
var encodedString = ncrypter.encrypt(2, 'mysecret1')
//use decode on your backend with same seconds and secret
var decodedString = ncrypter.decrypt(encodedString, 2, 'mysecret1');
console.log('permission granted -->', decodedString);

Securing public API with PHP

I am creating a SPA blog website with PHP/MySQL and a Javascript frameworks, still haven't decided which one yet.
The idea is that I am willing to create an API and consume it using Javascript, but I want to protect the API, so that no one can access /posts/ for example and get a list of all the posts.
I am not requiring any registration and I don't have a users system.
How would I go about it?
Thanks
You might be able to hard code whitelisted IP addresses, but as Steve pointed out in the comments: it's either public or it's not.
I'd go with some little registration functionality that generates API-keys that can be used to access your API.
It has been pointed out that a public API is public, however there are some steps that could take to make it more difficult for consumers other than your UI to access it.
The problem is akin (though not the same as) Cross Site Request Forgery, and you can use a variation of any of the prevention techniques listed to mitigate unauthorized access to your API.
The simplest implementation might be something like this:
index.html
<?php
$mytoken = uniqid();
$_SESSION['token'] = $mytoken;
?>
<input type='hidden' name='apitoken' value='<?= $mytoken;?>' >
some-api-endpoint.php
<?php
if($_GET['apitoken'] !== $_SESSION['token']) {
header("HTTP/1.0 403 Forbidden", true, 403);
}
If someone wants to access your public API, they will be able to, but they will have to put forth at least a little bit of effort to do so.
Using a JWT service will work just as well.
Have a look here: introduction to JWT
You can also use an api key and secret which will be passed on initial session auth for your service.
Here's a Stackoverflow answer that helps explain what you'll need to do: key and secret in php
If you're really lazy, you can just use basic authentication or digest auth to auth on the client side. (This is not advisable and has security risks as if you're not using ssl the passwords are passed as plain text in the request)
Another article for your information: PHP HTTP Authentication

How to call external ADFS secured WCF Service within Sharepoint via Javascript in an ADFS environment?

Previously on our little Sharepoint environment: We used integrated windows authentication for everything. On some of our sharepoint sites we integrated some custom javascript application logic that was calling a non-Sharepoint WCF service, which was also secured by windows integrated authentication in IIS. It just worked, since the windows identity of the current Sharepoint User was passed down to the javascript AJAX request and on to the WCF service. The WCF service used the identity information to perform some logic and returned the call.
Then we set up Sharepoint with ADFS 3.0 which broke our javascript application code since windows integrated auth was no longer working. My question: What is the proper way to fix this? It's clear that we have to modify the external WCF service to support ADFS claims based auth. We even thought about migrating the WCF service to a .NET web api with ActiveDirectoryFederationServices BearerAuthentication.
But on the javascript side, how to call that service with the current logged on user? I understand that Sharepoint is keeping a "FedAuth" cookie with information about the current user. Can I use that token for the external web service? Any help is appreciated.
UPDATE: This did NOT work since the FedAuth cookie is HttpOnly protected and can not be accessed in javscript. So we dumped the entire idea and created a proxy webservice directly hosted in Sharepoint. Looks like this is working, but it is ugly...
This is how we solved it:
We looked at the source code of the Sharepoint STS, especially at the point where they create the FedAuth cookies and create the signature for the tokens. You can find this in the SPSessionSecurityTokenCookieValue class in the dll Microsoft.Sharepoint.IdentityModel.
//excerpt from the ValidateSignature method
RSACryptoServiceProvider key = (RSACryptoServiceProvider) SPSecurityTokenServiceManager.Local.LocalLoginProvider.SigningCertificate.PublicKey.Key;
CspParameters parameters = new CspParameters {
ProviderType = 0x18,
KeyNumber = (int) key.CspKeyContainerInfo.KeyNumber
};
if (key.CspKeyContainerInfo.MachineKeyStore)
{
parameters.Flags = CspProviderFlags.UseMachineKeyStore;
}
using (RSACryptoServiceProvider provider2 = new RSACryptoServiceProvider(0x800, parameters))
{
provider2.ImportCspBlob(key.ExportCspBlob(false));
string s = this.BuildValueToSign(options);
byte[] buffer = Convert.FromBase64String(signature);
flag = provider2.VerifyData(this.m_EncodingScheme.GetBytes(s), this.m_SigningScheme, buffer);
}
We replicated this method in our WCF service and can now validate the values of a FedAuth cookie. Of course, you need to have the same certificate that Sharepoint uses for its Token Service (extract it via MMC, for example).
Now we are able to call the WCF service via javascript, pass the values from the user's current FedAuth cookie and confirm the identity of a user by validating the signature of the cookie. Then we can safely work with the UserKey/UserName values of the cookie in our application logic.

OWIN cookie authentication get roles on client side

I'm developing an application where backend is asp.net owin based.
In Startup.cs I have IAppBuilder.useCookieAuthentication() { ... }. After successfully authenticated, current user with its roles can be accessed via HttpContext in all my web api controllers.
My javascript client side needs a knowledge about these roles in order to know how to display specific items. For example: user having administrator role can see additional tabs.
My question is: what's the best way to 'transfer' these roles to client side. Is it by writing some endpoint which will return these roles, or any other way?
Thanks
I totally agree with #cassandrad !
But if you want to access it as plain text, than you have to provide your own implementation of TicketDataFormat in the CookieAuthenticationOptions
public class CustomAccessTokenFormat : ISecureDataFormat<AuthenticationTicket>
{
// If you want to do custom serialization and encryption
public string Protect(AuthenticationTicket ticket)
{
return "UserName|Role1|Role2|..."; // your raw text serialization goes here
}
// Deserilaize and decrypt the ticket
public AuthenticationTicket Unprotect(string strTicket)
{
return new AuthenticationTicket(null, null); // deserialize the plain text here into an AuthenticationTicket object
}
}
You don't need to pass information about roles or permission in “raw” state to the client-side. Instead, you should have AuthenticationTicket — the thing that holds all information protected and encrypted. So, if you are using correct implementation of OWIN middleware, there is no need to do something by yourself — middleware will add all the necessary data to your response(inside cookies), client only need to resend this information back to the server next time when he wants to access some resources on the server.
And yes, I'm implying that you shouldn't have any information about permissions on your client-side — it is not secure.

protect http request URL

i am getting remote JSON value into to my client app as below.
var $Xhr = Ti.Network.createHTTPClient({
onerror : function($e) {
Ti.API.info($e);
},
timeout : 5000,
});
$Xhr.open("GET", "http://***********.json");
$Xhr.send();
$Xhr.onload = function() {
if ($Xhr.status == 200) {
try {
Ti.API.info(this.responseText);
} catch($e) {
Ti.API.info($e);
} finally {
$Xhr = null;
}
}
};
My json URL is static. i would like to protect this URL from stranger eyes after creating APK file or publishing for iOS.
Also my server side support PHP. I have thouhgt MD5, SHA etc. but i didn't develop any project about this algortim.
Do you have any suggestion or approach?
Thank you in advance.
I would just say that it is not possible for you to "hide" the end point. Your url will always to visible to the user because otherwise user's browser wouldn't know how to actually post it to your server.
If you meant to only hide the json object, even that is not totally possible. If your javascript knows what the values are then any of your client smart enough to understand javascript will be able to decode your encoded json object. Remember, your javascript has decoded object and a user would have full access to it. There is no protection against that. At best, you can hide it from everyday user by encoding to with md5 or sha as you put it.
I you wish to restrict access to app user only, you will need to authenticate your users first.
Once they are authenticated, you should generate a hash by concatenating userid (or any user identifying data) and a key that you know (a string will do it), and hashing it using any hashing method, md5 would be enough for that kind of usage I guess, SHA is good anyway.
The next step would be to send this hash with every AJAX request to your server. consider it as an additional data.
Finally, server-side, before treating the request and fetching the data to be sent, just generate a hash the same way you did in your app, using the userid of the requesting user and the same "secret" key you chose. You can now compare both hashes and see if they're identical. If not, then it's probably that someone tried to forge a request from outside your app.
Note that it could be possible for someone authenticated to get his hash (which depends on his ID) and then use it in one of his applications, so it may be a good idea to track the requests server-side in order to check if there's any suspicious usage of your API. You could aswell change your "secret key" regularily (forcing an update of your app though) or define an array with a different key for each day of the year in both your app and server code, so that each individual hashkey will change everyday, recurring each year.

Categories