Accessing external / non template / non angular2 element and reading its value with Angular2 - asp.net-mvc

I am developing an Angular2 and integrating it with my ASP.NET MVC application.
To prevent CSRF attacks we have used Anti-Forgery Tokens in ASP.NET MVC helper function, which renders an input type inside the body.
Now I want to read this value and append it to the headers of all my ajax calls in my angular2 app.
I was not able to find a way how to read this value and pass to http wrapper service.
This is how the DOM looks:
<html>
<head></head>
<body>
<input name="__RequestVerificationToken" type="hidden" value="6fGBtLZmVBZ59oUad1Fr33BuPxANKY9q3Srr5y[...]" />
<my-app>
</my-app>
</body>
</html>
Thanks.

You can access it with jQuery selector:
<html>
<head></head>
<body>
<input name="__RequestVerificationToken" id="input_element" type="hidden" value="6fGBtLZmVBZ59oUad1Fr33BuPxANKY9q3Srr5y[...]" />
<my-app>
</my-app>
</body>
</html>
Component
checkValue(): string {
return $('#input_element').value();
}
This is not the most elegant way to do what you need, but it is the only one, since angular doesnt allow access to anything outside scope.
I actually used this to change css link in my tag located in tag.
But
Also consider the comments, that there is a better way to implement token based communication. You can actually save your token in localStorage after authentication procedure, or any other REST call. Take data from result of that REST call and localStorage.setItem('token', value).
You can create HttpInterceptor, custom one, where you can modify every REST call to have that token. Example of that:
https://medium.com/aviabird/http-interceptor-angular2-way-e57dc2842462

Thanks for your suggestions everyone.
So here is what I did after researching and from all of the above suggestion.
I created a window-ref service that returns me the window object and also has the getToken() method.
Then I inject this service in my http wrapper service.
The window ref service has the getToken() method that will check if the document object is present and if it finds the element with the provided name "__RequestVerificationToken" it will returns its value.
If the element is not present then blank value or null is returned.
While in the HttpWrapper service I check if the returned value from getToken() is blank then don't append the "__RequestVerificationToken" header else append it.
I followed this https://juristr.com/blog/2016/09/ng2-get-window-ref/ link for the window ref service.
I did'nt wanted to make another call to get the token from the server, because this call would obviously wont have any security token attached to its request headers and this would have made this call unsafe. An attacker could have easily called this method and got the token and successively attached it to next calls.

Related

How to access currently requested URL in a Grails GSP file

If I have a simple GSP (using Grails 2.3.6):
<% page import=org.me.Widget %>
<header>
<!-- Header stuff -->
</header>
<body>
The requested URL is ${url}!
</body>
How do I inspect the HTTP request URL (the current URL the server is responding to) and inject it into the ${url} variable?
Note: I need to do this inside of GSP and not from inside a controller, if at all humanly possible, even if it is a violation of best practices.
you could try
def var = request.forwardURI
forwardURI - Useful for obtaining the current request URI since the request object’s requestURI property returns the original URI, not the matched one.
You can even check for additional methods added to the request object here
You have quite a few options in a GSP to find out the current URL.
First, you can always access the request object which is an HttpServletRequest. Using methods such as getRequestURL() or getRequestURI(), you can inspect the request.
${request.getRequestURL()}
However, actionName and controllerName may be more useful. Both of these properties are exposed to the GSP within the model. With these you can construct the URL current using the standard createLink tag if needed.
${createLink(controller: controllerName, action: actionName)}
These should give you enough options to accomplish what you need.

Why does #Html.AntiForgeryToken() generate different tokens in same response?

A single Razor view contains several forms, each with its own call to #Html.AntiForgeryToken()
<form id="f1">
#Html.AntiForgeryToken()
</form>
<form id="f2">
#Html.AntiForgeryToken()
</form>
As I understand it, both of these anti forgery tokens should be the same.
<form id="f1">
<input name="__RequestVerificationToken" type="hidden" value="duVT4VtiYybun-61lnSY1ol__qBwawnELooyqT5OSrCJrvcHvDs_Nr9GLxNxwvBaI4hUcKZVkm6mDEmH2UqNorHD1FnJbKJQLWe8Su_dhy_nnGGl5GhqqC3yRGzcxbBM0" />
</form>
<form id="f2">
<input name="__RequestVerificationToken" type="hidden" value="ZMISz3IWHU_HCKP4FppDQ5lvzoYhlQGhN1cmzKBPz4OgDzyqSUK3Q1dqvw1uHsb4eNyd9U3AbFcnW8tR7g1QS8Dyhp0tFc-ee1sfDAOqbLCcgd3PDnLCbXx09pnPREaq0" />
</form>
Why are the values different?
Surely they should be the same, because they are sent in the same Response from the server?
The documentation says nothing about calling it once only.
I am afraid that won't work.
The antiforgery token also travels in the response cookie, so yours will contain just the last token, and therefore the first form will always fail.
You can try to do something like this:
#{
ViewBag.Title = "Index";
var token = Html.AntiForgeryToken();
}
<form id="f1">
#token
</form>
<form id="f2">
#token
</form>
I have tried it, and the same token is used in both forms.
The values HAVE to be different. Not because of implementation inner workings or API voodoo but because each form represents an independent request to the server.
If the forms had the same token, once an attacker knew the token value for one form he would be able to trick the server into accepting the data sent by the other forms, although they were not submitted by the user, defeating the protection provided by the AntiCSRF Token.
The objective of the token is to provide a random id parameter, making it very hard for the attacker to fool the application into thinking that it was the logged in user that filled the form.
For those that are not acquainted with CSRF attacks, please take a look here.
The Anti-Forgery token is not compared directly - the server has to unprotect it first and compare the protected data inside. Having different protected tokens doesn't necessarily mean they contain differing data.
What the System.Web.Helpers.AntiXsrf.TokenValidator compares is the SecurityToken inside the decrypted AntiForgeryToken instances. These instances, however, also contain an AdditionalData field, a UserName field and a ClaimUid field.
Also, the SecurityToken inside the AntiForgeryToken is directly copied from the (current if it is valid, else the freshly generated) AntiForgery cookie inside AntiForgeryWorker.
Given that all that data is serialized, encrypted then encoded, you may have variances in the protected token due to differences between the AdditionalData between tokens or it is likely due to a pseudorandom nonce used in the encryption process (which it likely uses, since I can test 2 completely different tokens as valid against the same cookie).
Surely they should be the same, because they are sent in the same Response?
The Response has nothing to do with it. #Html.AntiForgeryToken() is a static method of HtmlHelper which generates a unique token that is added to the html and the response cookie. Your calling the method multiple times so your generating multiple tokens.
If it did not generate a unique token each time it would hardly be secure.
#Html.AntiForgeryToken() basically generate encrypted value based on the cookie and form data. So if you declare and use this #Html.AntiForgeryToken() for each than it will generate two different _RequestValidationToken. Better declare one global #token variable with #Html.AntiForgeryToken() method and it will create a single token for each request.
These are not equal antiforgerytoken commands.
The MVC is generate uniqe for all uniqe commands.
So you shouldnt wait same generated ID. As I know :)
Thank you buffjape, for your comment

Get QueryStrings in browser url in jquery get request

I would like to send a get request with jquery but the get function does not put the query strings in the address bar.I tried setting async to false but it still does not work.
$("#searchForm").submit(function (event) {
var x = $("#category").serialize();
$.get("Home/test", x, function (data) {
alert(data);
});
event.preventDefault();
});
The code above does not put the query strings in the address bar like a normal get request would.
hence i should have in the browser address bar something like Home/Text/?category=laptop
for example
any other solutions to specify what querystrings i can put in the address bar are welcome.
form id="searchForm" action="#Url.Action("Index")" method="get">
<input type="text" name="search" id="search />
<div id="price">
<input type="text" id="PriceMin" name="PriceMin" />
<input type="text" id="PriceMax" name="PriceMax" />
</div>
<input type="submit" value="submit"/>
</form>
as an example i dont want in the url querystrings of
?search=volvo&PriceMin=&PriceMax=
In other words, the input fields that are null should not be placed in url on a get request.
thx.
Found something and its working why i didnt think of this before is beyond me
$("#searchForm").submit(function (event) {
if ($("#PriceMin").val() == "") { $("#PriceMin").prop("disabled", true); alert("isnull");}
});
i disable the input field if it is "" just before the form is sent.Thus the query string of "priceMin" is not sent because the element is disabled.
The reason why the address bar doesn't change is because when you make an AJAX request with javascript, this request is made in the background. The whole point of AJAX is to make requests without navigating away form the current page. If you change the url in the address bar that would trigger the entire page to be reloaded. So what you are trying to achieve is impossible. You could use the fragment portion of the url (the part that follows the #). You could modify this part of the url without causing the browser to navigate away. Take a look at the following article: http://ajax.rswebanalytics.com/seo-for-ajax/#!ajax-crawlable-urls
Thus you could have the following url:
http://example.com/Home/Text/#category=laptop
In order to manipulate the fragment portion of the url in javascript you could use the window.location.hash property. Bear in mind though that this part of the url is never sent to the server. It is only intended to be used on the client.
As far as your second question about the empty strings is concerned, there's no way to achieve that in pure HTML. You will have to write javascript. Basically here you will have to subscribe to the .submit event of the form and manually build the target url that you will redirect to and exclude parameters that have empty values. Then manually redirect to this url using the window.location.href property. Also don't forget to cancel the default action of the submit by returning false.

Firefox bfcache issue?

I am having trouble with only firefox. My page shows a tree structure that is loaded via ajax as the user clicks on the nodes they want to expand. The problem I'm having with firefox, and only firefox, is that it will expand the nodes on the first page load. But after that firefox caches it weird and the node header, not children, of the ajax request gets carried over to the new page. This is an issue because the node's header that is carried over contains information that determines if the node has retrieved it's children.
<div class="node topbar"
<input type="hidden" id="foo" name="hasretrievedchildren" value="1"/>
...
</div>
It should be as it is on the first page load.
<div class="node topbar"
<input type="hidden" id="foo" name="hasretrievedchildren" value="0"/>
...
</div>
My Javascript checks for a nonzero value on that input to do the AJAX call.
Is this a bfcache issue?
I'm lead to believe it's not because I added
window.onunload = function();
to the js file and in a script tag and neither fixed it which this article
https://developer.mozilla.org/en-US/docs/Using_Firefox_1.5_caching
says should invalidate the bfcache.
I'm using asp.net MVC 4 and I tried using the MVCdonutcaching to set this page and partial views to not cache. But that didn't work either.
Maybe it's the bfcache, maybe it's not.
I had to face the same problem some time ago. The browser caches were causing some strange behaviour on our forms, and it was affecting the expected results of the page.
Someway to solve itSomething you can do in order to make the program load always the correct value (assuming you are loading it from ) is to initialize the value through your Javascript.
If you use JQuery, you should use:
<script type="text/javascript">
$(document).ready(){
//Assign your items values here
}
<script>
You can also use the onload handler in JS.
Hope this helps.
I was able to solve the problem. Firefox caches all form data even hidden inputs. Since I was using a hidden field to store the flag that enabled the AJAX request it would reload the form data with the flag set. I moved it to a custom attribute and it works exactly as it should.

How to localize javascript files in a Struts 2 app

I wrote an Struts 2 application and want to localize it. Now I am using javascript and I would like to put the scripts out of my HTML template to an own javascript file.
When I do it, my s:text tags are not rendered (of course).
Question is how can I localize my javascript files with Struts 2 in a clean way? I would like to avoid to use another technique than the properties files i currently use.
Thanks,
Christian
If you want to stick with your resource bundles back at server, one way possible would be to save your javascript files as .jsp file and serve them with an action so this way your struts tags in your javascript files will get a chance to retrieve the data from server and return the file upon request.
Personally I prefer to keep client messages in javascript files and server messages in resource bundles. This way you can save a .jsp processing IMHO.
You can use a hidden field in your JSP and pass its id to the external JavaScript file and get its value like follows.
In your JSP,
<s:hidden id="warning" value="%{getText('propertyKey')}"/>
(hidden field poplated with the value of the property key in the resource bundle)
Call your external JS method from the same JSP,
<s:a href="%{deleteSelected}">
<img src="<s:url value='/images/delete.gif'/>" border="none"
onclick="javascript:return displayWarning('warning')"/>
</s:a>
In external JavaScript file,
function displayWarning(message) {
var ret = true;
ret = confirm(document.getElementById(message).value);
return ret;
}
<script type="text/javascript">
var mytxt='<s:text name="my.text.prop" />';
alert(mytxt);
</script>
This is also possible, but you cant have them inside a function.You should assign relevant properties to global JS variable at the time of page load. Almost same concept slimier to use hidden variables.

Resources