I am making a Jquery Ajax web api call . That Api call requires me to pass the Api key. I have enabled CORS. Here is how my call looks currently
$.ajax({
type: "POST",
url: http://localhost:83/test/example1,
data: { name: JSON.stringify(myObject), userId: UserId },
dataType: "json",
headers: {
'apikey': 'asdfee'
});
My question is how do I securely pass this key? I don't want to directly expose the value.
Any directions please?
In short, you cannot secure the key on the client side. Anything on the client side is exposed and can be viewed by anyone.
This being said, there are ways you can attempt this.
Try to make it as hard as possible for anyone trying to get your key. This means store in something like local storage and minify your JavaScript code. This isn't 100% but it will make life harder for anyone trying to get it.
Introduce another layer in between. I have done something like this myself, this extra layer is another API. This is where you store the key and this is where you communicate with the other API. So basically you never expose the API key to the client side. Your front end call this new API and the new API calls the protected one. As I said, one extra layer in between but it does help keep the key secure.
Related
I initially setup a Web API (not any expert with web api) and followed someone's tutorial online for passing in parameters to a simple get API call.
I had originally created a GET with query strings but as the tutorial showed how using POST allows me to pass JSON to an class object in POST API parameter, it seemed a good idea.
Later on one developer said this was bad practice? Is it? Should I always use GET instead of POST which in essence is what it should be anyway... a GET call, but I like the idea of passing parameters via an object and avoiding a long API call with query strings.
So:
$.ajax({
url: '\api\getlist\1?param2=yyyy¶m3=kikkkk¶m4=88' etc
})
or
var params = ....
$.ajax({
url: '\api\getlist\',
data: params
})
What should I do, change the code back to using GET? What about caching?
You should take a look at the http documentation in w3c.
GET is recommended for reading data and POST is used to send information (write operations) into the server.
From client side perspective, you could set in jquery ajax setup, to do not use cache with the follow code:
$.ajaxSetup({
cache: false
});
It will generate a random argument on the async request to make a different request everytime, add a parameter like this: ?_=31312312312.
I have a Web API written in ASP.NET that I'm consuming via AngularJS $http.
I have enabled caching in my AngularJS factory as follows but every request still returns a response of 200, never 200 (from cache) or 304 (and by every request I mean making the same web api request numerous times on the same page, revisiting a page I've already visited that contains a Web API request, refreshing said page etc).
angular.module('mapModule')
.factory('GoogleMapService', ['$http', function ($http) {
var googleMapService = {
getTags: function () {
// $http returns a promise, which has a 'then' function, which also returns a promise
return $http({ cache: true, dataType: 'json', url: '/api/map/GetTags', method: 'GET', data: '' })
.then(function (response) {
return response.data;
});
};
return googleMapService;
}]);
Am I missing something from the AngularJS side of things? Or is this a Web API problem. Or both?
Turns out it was a Web API thing. I'd overlooked the fact that the response header clearly stated that caching was disabled.
Response as viewed in the Network tab of Google Chrome:
Upon further investigation (and as seen in the image above), caching is disabled in Web API controllers. Even the [OutputCache] attribute, which is used in regular MVC controllers, isn't supported.
Luckily I found this blog:
http://www.strathweb.com/2012/05/output-caching-in-asp-net-web-api/
which lead me to these two solutions:
ASP.NET Web API CacheOutput
CacheCow
I decided to go with CacheOutput as it lets me use attributes like:
[CacheOutputUntilToday] which supports server & client side caching.
Or if I wanted to just use client-side caching I can use something like:
[CacheOutput(ClientTimeSpan = 100, ServerTimeSpan = 0)]
Which seemed a little easier at first glance that CacheCow's approach. And easier to refactor out later if need be.
Now additional requests give me a 200 (from cache):
With a refresh giving me a 304 Not Modified:
Problem solved! Hope this helps someone else.
I am working on an ASP.NET MVC3 project, i am using Ajax jquery to communicate with my controllers. i use asp.net caching to store the results before updating the database (SQL Azure).
function SaveCustomersList() {
$.ajax({
type: "POST",
url: '/Customers/SaveCustomersList/',
data: "",
cache: false,
dataType: "text",
success: function (data) {
return true;
}
});
}
The application work fine but not for all users !!
When some users try to update the database the content passed to my DAL objects is null.
this is just happening with the users working on a network.
i have no explanation for that.
thanks for your help.
Here is a list of questions you need to answer to get proper help:
How many instances of your application is running?
Where this application is running and local network or hosted outside?
When you say "users working on a network", what do u mean? Does it mean this application is accessible to users within your network or outside network?
If this application is running in your network, and the communication between Ajax calls and controller is passing through proxy, only then Proxy could be a factor.
As you are using InProc cache the problem It is critical to know if you have multiple instances of this application. You need to understand that the communication between your Ajax and controller is instance specific and if you have local cache to handle it that will work with only one instance. However if you have multiple instance of the same application and using local cache will not work properly because there is no guarantee that connection X served by instance #1 will always be server by instance #1.
If you decided to run application on multiple instance, using distribured cache (i.e. Outside your instance) is the only choice you have comparative to internal (i.e. Insides your instance ASP.NET inproc) Cache.
[Added]
Here is a .net sample application to use Windows Azure Cache:
https://www.windowsazure.com/en-us/develop/net/how-to-guides/cache/
If you wish to use MemCache you can use #smarx solution as described below:
http://blog.smarx.com/posts/memcached-in-windows-azure
What you need to do is set up a distributed cache that allows you to cache data between multiple instances. You can use Azure Caching for this (but it is expensive!).
Setting the caching up is fairly easy, just follow this guide: https://www.windowsazure.com/en-us/develop/net/how-to-guides/cache/
I have written a web service. I am calling this web service using JavaScript. I am calling this from different domain. For that I have added [System.Web.Script.Services.ScriptService] property in the web service. From JavaScript I am calling the service using XMLHttpRequest. I tested it using Firefox and everything was fine when. But it was not working in IE.
After some searching I found that this is an issue related to Cross domain calling. I have gone through some of the questions posted here. And then I did the following changes in my code -
From javaScript I am now calling the service using XDomainRequest.
I have added following lines befor the return statements in the web-service - HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Origin", "*");
HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Credentials", "true");
return result;
It is still working fine in firefox. but in IE8 (as per my knowledge, XDomainRequest will not work in lower versions of IE) it is showing error (XDomainRequest.onerror).
Am I missing something?
The crux of your problem in IE is that XDomainRequest doesn't support the pre-flighting necessary to make a cross-domain request that includes a Content-Type header. I believe that's fixed in IE10, but even IE9 doesn't fully support CORS.
To reliably make cross-domain requests to ScriptServices in browsers that don't support CORS well, a server-side proxy is (unfortunately) your best bet.
Look into JSONP (json with padding).
Question about JSONP:
jsonp with jquery
Has some more info about it: http://api.jquery.com/jQuery.ajax/
your web service runs over HTTP right?
I don't recommend using the native XMLHttpRequest to make ajax request, maybe you should use Jquery to do this, I always do in that way and works in all modern browsers:
i.e:
function Activate(EmailId, controle) {
$.ajax({
type: "POST",
url: "/Page/Method",
data: "&EmailId=" + EmailId,
success: function (message) {
$(controle).text(message);
}
});
}
EDIT: to make cross-domain requests you can use the James Padolsey plug-In, and do something like this:
$('#container').load('http://google.com');
$.ajax({
url: 'http://news.bbc.co.uk',
type: 'GET',
success: function(res) {
var headline = $(res.responseText).find('a.tsh').text();
alert(headline);
}
});
I am trying to build an interface that communicates with a REST API for attask.com. Their API is convenient because it returns JSON. I thought that was perfect because I could forget about server-side C# code and just write the interface using jQuery and AJAX. However, when I try to make an AJAX request to their API I get an error in Chrome's javascript console:
Origin http://mysite.com is not allowed by Access-Control-Allow-Origin.
What does this mean? Is this the browser preventing the request? If so, why?
Update:
If I don't have any control over the server and it does not respond to JSONP requests, is my only option to employ a server-side REST client and have my AJAX talk to my own domain instead of attempting to go cross-domain?
I found that jQuery-JSONP is the easiest way to do this.
jQuery JSONP is an alternative solution to jQuery's implementation of JSONP
jQuery-JSONP features:
error recovery in case of network failure or ill-formed JSON responses,
precise control over callback naming and how it is transmitted in
the URL,
multiple requests with the same callback name running concurrently,
two caching mechanisms (browser-based and page based),
the possibility to manually abort the request just like any other AJAX request,
a timeout mechanism.
Sample Code to Get user profiles from YouTube
function getProfile(userId) {
$.jsonp({
"url": "http://gdata.youtube.com/feeds/api/users/"+userId+"?callback=?",
"data": {
"alt": "json-in-script"
},
"success": function(userProfile) {
// handle user profile here
},
"error": function(d,msg) {
alert("Could not find user "+userId);
}
});
}
For more samples.
Alternatively, you can use the fututre standard Cross Origin Resource Sharing that is supported on modern browsers and fallback to JSONP for the other browsers.
You'll want to use JSONP, JQuery has nice support for this built in. See JQuery Documentation for more info.
You need to make a JSONP request to perform a cross domain AJAX request, you can do this by appending
callback=?
To the URL you send the request to