WebApi Method with single value and AngularJs $http json handling - javascript

I am encountering an issue and I ran out of ideas, I need some guidance towards the origin and/or the solution:
Server Side
I added the standard Microsoft Web Api Controller class "ValuesController" which looks like this:
public class ValuesController : ApiController
{
public string Get(int id){ return "value"; }
...
Client Side
In my AngularJS Controller function I have a simple get
$http({method:'GET',url: '/api/values/1'}).success(function(data){
$scope.value =data;
})
The HTML looks like this:
<input type="text" ng-model="value" />
The weird thing(the issue) is that I get: "value" in my input instead of just value (no quotes).
To avoid misunderstandings, I am getting this:
Instead of this:
And of course the questions are: why?? and how do I fix it*?
*hopefully the answer will not be returning an object instead of a simple string :)

I have the impression that this is due to security vulnerabilities in the JSON format. In the documentation of the $http service there is section called JSON Vulnerability Protection that suggests that Angular takes a few precautions to avoid an attack.
They recommend the reading of the following article: Anatomy of a Subtle JSON Vulnerability which as far as I can see delves into a case similar to yours.
Bottom line, I think you will have to return a full JSON object and not just a string. An alternative is to make sure you are getting a JSON object, by doing
$scope.value = JSON.parse(value)

The preferred (Angular provided solution) is
$scope.value = angular.fromJson(data);

Related

Prevent XSS - Remove <Script> Tags in JSON

I am trying to prevent JavaScript injections via JSON in a JObject like so:
public class JsonService : IJsonService
{
private JsonSerializerSettings _jsonSerializerSettings = new JsonSerializerSettings()
{
StringEscapeHandling = StringEscapeHandling.EscapeHtml
};
public JObject SanitizeJson(JObject jsonToSanitize) {
string sanitizedJsonString = JsonConvert.SerializeObject(jsonToSanitize, _jsonSerializerSettings);
JObject sanitizedJson = JObject.Parse(sanitizedJsonString);
return sanitizedJson;
}
This is all good fun, until I realize that my input looks like this:
{
"submission": {
"firstName": "<script>document.write('script kiddie');</script>",
"birthday": "05/21/2015",
"submit": []
}
}
My "sanitizedJsonString" looks like this:
"{\"submission\":{\"firstName\":\"\u003cscript\u003edocument.write(\u0027script
kiddie\u0027);\u003c/script\u003e\",\"birthday\":\"05/21/2015\",\"submit\":[]}}"
And my "sanitizedJson" looks like this:
{{
"submission": {
"firstName": "<script>document.write('script kiddie');</script>",
"birthday": "05/21/2015",
"submit": []
}
}}
Note that while the formatting into a string does escape the javascript, it's right back in the code the moment I turn it back into a JObject. In other words, a script gets saved to the database. My end goal is not to have form submissions (that come through as JSON I don't control) get saved in the db. I DO need to serialize the string back into a JObject on trip back to client, so I need it cleaned from the JObject. I am tempted to do str.Replace("<",""), etc, but that's obviously not a real solution.
How do I accomplish cleaning out the <script> tags?
Additions from comments:
I am getting JSON from third-party front-end.
I am sending back JSON to third-party front-end, some of which will be rendered as html.
Edit 2:
Tried AntiXSS via NuGet, it is not compatible with .NET Core: https://www.owasp.org/index.php/.NET_AntiXSS_Library
I think the best option is to reject the input JSON when you see any suspicious characters in it. But when that is not possible, we can at least validate it for XSS attack.
I was in the same boat & I found a pointer in another question here: AntiXSS in ASP.Net Core
Hope you can carve out your solution from this reference as well.

Laravel - Modifying data for API only for convenience

Let's assume the following data that is exactly being returned like it's stored into database:
[
{
"user_name": "User 1",
"photo_file": "user1.jpg"
},
{
"user_name": "User 2",
"photo_file": "user2.jpg"
}
// ...
]
I want to use this data in a JavaScript application but I'd like to append a full path of the user's photo, like doing a treatment for the data before returning it to the API. How can I do that using Laravel?
I assume at present you're just converting the results of your query into JSON and returning that. This works, but it does mean the response is tightly coupled to your database structure, which is a bad idea. Ideally you should have a layer of abstraction to handle adding and formatting data, kind of like a view layer in MVC.
There are plenty of solutions for this. I use Fractal for my Laravel API's. It allows you to easily customise the output of a particular endpoint by specifying a transformer that will render that object for you. That way you can easily choose the data to display and format it how you wish.
Accessors are good for this.
Let's assume your data is stored in a model called Customer. I would write an accessor like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Customer extends Model
{
protected $appends = ['photo_file']; // In order to see the new attribute in json dumps
public function getPhotoPathAttribute()
{
$name = $this->getAttribute('photo_file');
if(!isset($name))
return null;
return '/full/path/to/image/' . $name;
}
}
This way you can now call $customer->photo_path and it will return `/full/path/to/image/image_name.jpg' (or null if the attribute is not set).
Edit:
In order to show this attribute in jsons (without specifically calling $model->photo_path) you will also need to add protected $appends = ['photo_file'] to the model (updated).
I would recommend against overriding original name (so I leave photo_file attribute untouched).
If you are building Laravel API, sure, as Matthew said, go and check Fractal. But don't forget to Dingo, the best tool for building API at Laravel. And it uses Fractal too.

Using meteor and blaze how to convert template to string for an email body?

And how can I set the value of this now? Ie in js? All i see is how to do in handlebars.
From Meteorpedia :
http://www.meteorpedia.com/read/Blaze_Notes
Take a look at "How to render a template to HTML with data"
var toHTMLWithData = function (kind, data) {
return UI.toHTML(kind.extend({data: function () { return data; }}));
};
Use it like this :
var myTemplateAsString=toHTMLWithData(Template.myTemplate,dataContext);
Which is equivalent to previous Spark code :
var myTemplateAsString=Template.myTemplate(dataContext);
Currently Meteor does not natively support server side rendering of templates, and since you are sending emails from the server this creates an issue. Server side rendering is on the Meteor roadmap, but for now we can use a package. its called "Handlebars-server" and it can be found here: https://atmospherejs.com/package/handlebars-server
With Handlebars-server you can compile handlebars templates into strings for use in emails. The package's readme should get you started and show you how to set data context.

Passing objects from NodeJS to client and then into KnockoutJS viewmodel

So thanks to SO I can pass an object from node to the client, but then getting it into a knockout view model is a bit awkward. These are the steps I have so far (I've included links to the relevant lines as they appear in my github project. Thought the context might help.):
Apply JSON.stringify and pass to the jade file
recipeJSON: JSON.stringify(recipe);
Wrap this in a function in a header script that just parses the JSON and returns the result
script
function getRecipeObject() {
var r = '!{recipeJSON}';
return JSON.parse(r);
}
Call this function and pass the result to a view model constructor
self.recipe = ko.observable(new Recipe(getRecipeObject()));
This works but is there a better way?
Question clarification (Edit): I feel step 2 shouldn't be necessary. Is there a way to directly pass the JSON from node to the Recipe() constructor, without the getRecipeObject() acting as an intermediate step? I tried passing recipeJSON in directly like so
self.recipe = ko.observable(JSON.parse('!{recipeJSON}'));
That doesn't work I think because its not a jade template and has no access to the variable.
According to the answer to this question rendering data into scripts is bad practice and I should instead make an XHR call on page load instead.
Edit
I just saw you linked a github repo! So you're already familiar with most of this...you even have an endpoint set up at /recipe/:id/view, so now I'm really confused...what isn't working out for you? Just the last step of deserialization using ko.utils.*?
Sorry about all the exposition -- I thought this was way more rudimentary than it actually was; I hope no offense taken there!
You really don't want to return a script to execute -- instead, treat this as a DTO: an object that just stores data (no behaviors). An example would be:
{
recipeID: 12,
reviewIDs: [42, 12, 55, 31],
rating: 4.2
recipeName: "A super tasty pie!"
}
This object (representation) is a projection -- a simplified version of the full data stored in the database.
The next step is to create an endpoint to access that data on the server. Let's assume you're using Express:
var app = express();
app.get('/recipes/:recipeID', function(req, res) {
var recipeID = req.params.recipeID;
// It would be cool if this existed, huh?
getRecipeAsync(recipeID, function(recipe) {
res.status(200).json(recipe);
});
});
If you send a GET request to your (hypothetical) application (let's say it's https://localhost:8080/recipes/12), you'll get json representing the (admittedly imaginary) recipe with ID 12.
You can accomplish getting the JSON with jQuery (or any other library that makes XHR nice and pretty)
var recipeID = 12;
$.ajax({
url: "/recipes/" + recipeID,
type: "GET"
}).then(function(recipe) {
console.log("Hey! I got the recipe: %O", recipe);
// Note: you might need to use ko.utils.fromJS(recipe) if the returned
// data is JSON that ISN'T deserialized into an object
var recipeObservable = ko.utils.fromJS(recipe);
});
That's about everything you need to know. Obviously, the devil's in the details, but that's basic idea; let me know if that helps!

Knockoutjs templatefiles and localized resx files

Experimenting with building a SPA app on top of Web API I have come across a problem.
In my project i use Resource.resx files to localize the information displayed.
This is not problem when I create views in .cshtml format, but when I use Knockout templates i get a problem since they are .html and I can no longer access the Resource.resx directly.
I'v considered a few options, including, sending the localized strings together with the model from Web API, creating javascript variables in the .cshtml file and accessing them in the .html and creating a javascript localization file(that either contain constants, or get the values from the .resx ).
Anyone got any good ideas on how to work around this?
Edit:
Ok, the two most viable solutions that I can think of is to print the localized strings in the .cshtml file, like this:
#functions{
public string LocalizedString()
{
return Resource.MyLocalizedString;
}
}
<input id="LocalizedString" type="hidden" value="#LocalizedString()" />
and then get the value using jquery and the id of the input
$("#LocalizedString").val()
so I can populate a localized.js file that i can reference troughout the application.
The other option is to create a wep api service that serves a json list of the strings that i need in my application.
public HttpResponseMessage Get()
{
var localString = new Dictionary<string, string> {
{"FullName", Resource.ACC_FullName},
{"LastName", Resource.ACC_LastName},
{"FirstName", Resource.ACC_FirstName}
};
return Request.CreateResponse(HttpStatusCode.OK, localString);
}
witch would return this JSON
{
fullName: "Fullt navn",
lastName: "Etternavn",
firstName: "Fornavn"
}
This could then be stored in localstorage (I know the inital question was knockout related, and this code is angularjs, but i know you can do it in a similar matter with knockout)
gets(): void {
this.http({ method: 'GET', url: '/api/locals' }).
success(function (data, status, headers, config) {
angular.forEach(data, function (value, key) {
localStorage.setItem(key, value);
});
}).
error(function (data, status, headers, config) {
this.$log.warn(data, status, headers, config);
});
}
witch can then be used on the pages using
localStorage.getItem('Key')
EDIT: in the case of AngularJS you can just utlilize $http inbuilt cache, pretty smart.
The first solution will probably make the variables availabe in the DOM faster, atleast they'll be there when the scrips execute, but I don't like the idea of cluttering my html with stuff that's not really supposed to be there.
The other solution cleans up the html, but i'd have to make a api call to get the values, and the values would not be availabe untill that call was returned. witch means I'd probably need to delay the execution of scripts that rely on the values beeing there until it's done. But the response isn't going to be very large, we are talking maybe 50-100 strings in total (for my site atleast).
Now, I haven't implemented any of these solutions myself yet, and I don't know if they are any good. So if anyone got any comments or ideas i'd like to hear them.
I had a similar problem. Since I have no experience with Knockout.js I am not sure if it helps you. I have a string named Test in my resource file and I am able to have it shown on the front end using the following line of code in my cshtml:
#Html.Raw(WmsWebMvcProto.Properties.Resources.Test)

Categories

Resources