Could this cause a rails to detect a CSRF? - javascript

Ok, so in my rails app on one of the pages I needed to pass a Javascript variable so that it was available to rails. Now one runs server side and one runs client side so I know this is very difficult. I looked to the internet and found a solution that involved dynamically creating a form in a function included in my external javascript page.
Basically, a form with a hidden field was made using document.createElement statements and the hidden field was given the value of what I wanted to pass to rails and then form.submit() is called so that the form is submitted. the form was given a method of post and it was given a path to go to. So when submit it called the page redirects to another page with the hidden field now in the params hash and accessible by rails with params[:param].
This worked great for a while, until we started using session to keep track of a logged in user. After clicking the button to be redirected with that dynamic form the session gets cleared. The only thing I found online about sessions being cleared is when rails detects a CSRF it clears the session.
So could what I'm doing cause rails to detect a CSRF and thus clear my session? is there any other reason the session might be cleared that anybody knows of? Also, without ajax (because I'm just not up to screwing with that, it doesnt play nicely.) is there another good way im missing to pass a javascript variable (it has to be javascript, I'm using a javascript function to get the users current location) so that it is available to rails? (I'm thinking rather than javascripting the form, I might just make a hidden form right on my page, although this is a little less elegant because anybody looking at the source can see it and wonder why its there and screw with it)
if anybody is interested, below is the code for my dynamic form function.
function post_to_url(path, params, method) {
method = method || "post"; // Set method to post by default, if not specified.
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path); //page to go redirect to when form submitted
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
//after form is submitted params is available by params[:location]
hiddenField.setAttribute("name", 'location');
hiddenField.setAttribute("value", params )
form.appendChild(hiddenField);
document.body.appendChild(form);
form.submit();
}

In any form requests, and ajax the CSRF token must be passed through. You need to create a hidden field in the form with the name authenticity_token. Then you need to grab the value from the meta tag:
<meta content="some_token_value" name="csrf-token" />
Like so:
var token = "";
var tags = document.getElementsByTagName("meta");
for(var i = 0; i < tags.length; i++) {
if(tags[i].name == "csrf-param") {
token = tags[i].content;
}
}
Then simply drop that in the value of the hidden tag, much like you did for the location value.

you can add an erb line in your javascript file:
var csrf_token = '<%= form_authenticity_token %>';
then in your requests, add 'authenticity_token' : csrf_token in the post-data.

Related

Sending Data from a JS page to an HTML page without Form or URL

I want to send a variable from JavaScript to another HTML page and be redirected to that page, but I can't use forms because the first page is purely in JavaScript and a .js file so I can't declare a form. I also can't use the URL as my data is too big. What are other options? Every tutorial I've found uses either forms or the URL. Is there an alternative?
Based on this answer, I used the following code:
function post(array) {
var method = "post";
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", "helloworld.html");
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", "array");
hiddenField.setAttribute("value", array);
form.appendChild(hiddenField);
document.body.appendChild(form);
form.submit();
}
and I call post(parameter) in another method.
It successfully redirects to helloworld.html, but how can I get the variable that I passed?
You can save the data in the localStorage and if the second page is in the same domain. The data has to be string.
Page One:
function sendData(){
localStorage.setItem("data", data);
location.href = "helloworld.html";
}
Save the data.
Page Two:
function onLoad(){
var data = storage.getItem("data");
}
Read the data.
Optional:
You could also create a JSON Object and save it with the function JSON.stringify
You can make an HTTP request from JavaScript:
// jQuery
$.get("demo_test.asp", function(data, status){
// do something
});
jQuery documentation is located here
You can use jQuery ajax API and send the data through POST request. See more:
here
or here
Edit: oops, I didn't notice that you don't have any server side handler enabled. In that case, if you do not want to use forms you can handle get/url parameters with jQuery.param() or use some routing enabling library.

How to read the value of variable in JS in the scope of JSP on the same page?

I have a JSP page in which third party sign-in plugin is used, which is JS. After sign-in is successful, the user-id obtained in JS has to be used in JSP to maintain session by storing that value.
For this, I tried 'manipulating' jQuery but that works only if the JS value is a literal or is pre-known. But here in this case, value is fetched at runtime as per sign in.
Also tried <% String s = "<script>document.writeln(var)</script>"; %>
But again the above problem. works only when value is known before hand.
document.getElementById("ppurl").innerHTML = ppurl; prints the value. But I want to store it.
So, how to achieve the purpose of passing a variable's value in JS to JSP?
Assuming your third party sign-in plugin is client-side JavaScript:
Remember that the JavaScript runs when the page reaches the client. The JSP code has long since completed and so is no longer in the picture.
You have three options that I can immediately see:
Send the data to the server using Ajax or similar.
Refresh the page (sending the login data to the server as part of the refresh).
Update whatever it is on the page that you want to have this value in it via the DOM.
#1 and #2 should be fairly self-explanatory.
For #3: Say you have various forms on the page and you want to make sure that the login token or whatever it is you get from the client-side plugin gets sent with the form using a hidden field in the form with the name tokenField. You could do this:
function putTokenOnForms(token) {
var forms, index, form;
forms = document.getElementsByTagName("form");
for (index = 0; index < forms.length; ++index) {
form = forms[index];
if (form.tokenField) {
form.tokenField.value = token;
}
}
}
You can do much the same with links in a elements (adding to the href property of each link that goes back to your server), etc.
The page outputting the JavaScript to the client cannot read data back from that JavaScript.
You need to initiate a new HTTP request (e.g. using XMLHttpRequest or setting location.href) that passes the data back to the server and then read it in (e.g. from the query string or POST data).
Store it in a cookie using JS. Read it back in JSP.
In your JS, after you get the userID, you can do:
document.cookie = 'myuserid='+userID;
In your JSP, you can read it back like:
Cookie[] cookies = request.getCookies();
String userID;
for(int i = 0; i < cookies.length; i++) {
Cookie c = cookies[i];
if (c.getName().equals("myuserid")) {
userID = c.getValue(); // c.getValue() will return the userID
break;
}
}

Get Modern Browsers to Recognize Ajax/JQuery Login and Ask to Save Password

I am using jQuery (latest) and have a entirely ajax through post login form. The form is monitored by this code:
$("form").live("submit", function(event) {
event.preventDefault();
var input = {};
input.url = $(this).attr('action');
input.data = $(this).serializeArray();
var output = Site.getResponse(input);
if(output.success) {
params = {};
params.title = 'Dashboard';
params.url = '/user/dashboard';
Page.instance().load(params);
}
});
So, essentially the browser should still recognize the post because it happens from the form's submit, I just use jQuery to stop that submit so I can process it. Is there a way to "trick" modern browsers into saving the password for my site without iframes, please.
IMHO the best way to handle login is to add this line to the end of the login script
header("Location: " . $_SERVER['HTTP_REFERER']);
or some constant url, depending on what you want. This way the page doesn't change and the form submits, therefore the browser remember's the password.

Passing POST values to intermediary page with JavaScript

I have a situation in which I am a bit confused on how to complete.
Example domains:
http://url1.com
http://url2.com
url1.com has a registration form url2.com has another form.
I need to pass the POST values from url1.com to url2.com without an actual submit happening. On url2.com I need to reconstruct the form with the POST values from url1.com and append hidden input values to the reconstructed form and then submit. I would like to completed this with JavaScript / jQuery if possible.
I would like to note that the url1.com contains a registration form with login and password.
Any advice is greatly appreciated.
Thanks in advance.
Here is how you could post to another URL:
function post_to_url(path, params, method) {
method = method || "post"; // Set method to post by default, if not specified.
// The rest of this code assumes you are not using a library.
// It can be made less wordy if you use one.
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path);
for(var key in params) {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", params[key]);
form.appendChild(hiddenField);
}
document.body.appendChild(form);
form.submit();
}
copied from here:
JavaScript post request like a form submit
There are other solutions there as well.
P.S. Regarding the security question, read here:
Are https URLs encrypted?
Essentially, all the data you pass over secure connections are encrypted, be it GET or POST. And be aware that even if you post data over regular http it could be intercepted by the man in the middle even if it is not visible for the user in the URL.

Capture all links including form submission

I am wondering how to capture all links on a page using jQuery. The idea being similar to Facebook. In Facebook, if you click on a link it captures the link and loads the same link using ajax. Only when you open a link in new tab etc. will it load the page using regular call.
Any clue on how to achieve such kind of functionality? Am sure capturing links should not be a problem, but what about capture form submissions and then submitting the entire data via ajax and then displaying the results?
Is there any plugin which already exists?
Thank you for your time.
Alec,
You can definitely do this.
I have a form that is handled in just this way. It uses the jquery form plugin kgiannakakis mentioned above. Example javascript below shows how it might work.
$("form").ajaxForm({
beforeSubmit: function(){
//optional: startup a throbber to indicate form is being processed
var _valid = true;
var _msg = '';
//optional: validation code goes here. Example below checks all input
//elements with rel attribute set to required to make sure they are not empty
$(":input [rel='required']").each(function(i){
if (this.value == '') {
_valid = false;
_msg += this.name + " may not be empty.\n";
$(this).addClass("error");
}
});
alert(_msg);
return _valid;
},
success: function(response){
//success here means that the HTTP response code indicated success
//process response: example assumes JSON response
$("body").prepend('<div id="message" class="' + response.status + '"></div>');
$("#message").text(response.message).fadeIn("slow", function(){
$(this).fadeOut("slow").remove();
});
}
});
Form plug-in can transform a regular form to an Ajax one:
$("#myForm").ajaxForm(
{beforeSubmit: validate, success: showResponse} );
It would be difficult to do what you want however for an arbitrary form. What if the form uses validation or is submitted by Ajax to begin with? The same thing applies for links. What if there are some javascript navigations scripts (window.location = Url)? If you don't have full control of the page, it will be difficult to do what you want.
Usually pages like facebook, do each event and each form separately coded, as the server-side files are usually set for each single operation / group of operations. I doubt there will be a clean way to convert a page with just a plug-in. And if it is, I see a lot of overhead.
You can do it by hand, but again that's abuse of Ajax. This isn't flash, and with using ajax for all server communications you run into a lot of problems.
Lack of history tracking.
Watching out for concurrent events and the results of thereof.
Communicating to the user that the page is changing.
Users with javascript turned off.
And much more...

Categories