Laravel 5.1 - Token Mismatch issue with Iframes on Safari Browser Only - javascript

I have created few forms in laravel 5.1, now i am using those forms on another site using IFrame. Those forms works in all browsers except Safari. When i try to submit/post data after filling up forms, i get error "CSRF Token Mismatch", I dont know what the issue here, csrf token is also being created and sent. This is only happening in case of safari browser.
Can someone guide me that how i can get rid of this issue??
Steps To Reproduce:
create a form and then use it via IFrame. after form is submitted, CSRF Token Mismatch error is generated.
How to solve this? Please help!
CODE SAMPLE:
<form method="post" action="/step1/{{$voucher->user_id}}" accept-charset="UTF-8">
<input name="_method" type="hidden" value="post">
{!! csrf_field() !!}
<div class="row" style="margin-top:15px; margin-bottom:15px;">
<div class="col-md-4 col-xs-5 hidden">
<input name="voucher_id" type="hidden" value="{{$voucher->id}}" id="voucher_id">
<input class="form-control spin text-center qty1" name="qty" id="qty" type="text" value="1" >
<input name="r_full_name" type="hidden" value="" id="r_full_name">
</div>
<div class="col-md-3 col-xs-3">
<button type="submit" class="btn btn-theme"><i class="fa fa-shopping-cart" aria-hidden="true"></i> | BUY</button>
</div>
</form>
this is sample code... AGAIN all this works perfect in any other browser (FF, Chrome) but when I put this forms into iframe in another site then I get TokenMissmatch error...

This is most likely related to how Safari handles cookies and iframes, please see the answer from this question which quotes what seems like an older version of the Safari Developer FAQ which states
Safari ships with a conservative cookie policy which limits cookie
writes to only the pages chosen ("navigated to") by the user. This
default conservative policy may confuse frame based sites that attempt
to write cookies and fail.
That would explain why you are having trouble with this.
The second answer to that question proposes a solution which can be found here. This is basically the same thing as doing a redirect to the domain that owns the cookies, setting the session and redirecting back, which is another solution which is mentioned here.

The csrf token is to prevent cross site request forgery and that's what you are doing when you use an iFrame! The token prevents random websites from submitting a form to your site. So a form using Laravel and a token is not going to work in an iFrame!
If you want to publish the form on other site, either disable the csrf token for that form or handle the submit request in your way so that it pass all the security check according to your need.

I think this post can help you, You can change your cookie politics.
Csfr token problem

send token for each request
$.ajaxSetup({headers: {'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content') } });

Test if browser is Safari and page is home page and session is not started, If yes then redirect window top url to iframe parent url
Steps to fix Laravel Token Mismatch issue with iframe on Safari using redirect is as below:
1) Add route
Route::get('/start-session', 'HomeController#startSession');
2) Add controller action
public function startSession() {
session()->put('isSessionStarted', true);
return redirect('http://www.iframeparentsite.com'); // redirect to website where iframe is hosted
}
3) Install jenssegers/agent module to detect Safari browser https://github.com/jenssegers/agent
composer require jenssegers/agent
4) Use it in controller
use Jenssegers\Agent\Agent;
5) Pass isSafari, isHomepage and isSessionStarted to view in homepage controller action
public function index()
{
$agent = new Agent();
$this->data['isSafari'] = $agent->is('Safari') && !$agent->is('Chrome');
$this->data['isHomepage'] = true;
$this->data['isSessionStarted'] = session()->get('isSessionStarted');
return view('home', $this->data);
}
6) Add blade/javascript code in page layout head section
#if ($isSafari && !empty($isHomepage) && empty($isSessionStarted))
window.top.location = "{{ url('/start-session') }}";
#endif
Redirect will happen once on homepage and will take 1/2 seconds

Related

Complex web site login with Requests

I'm trying to log in to a site using the requests module, and can't figure out how the site's login page actually works. Here's the relevant form:
<form class="ui-corner-all" method="POST" id="login" target="_top">
<div id="lift__noticesContainer__"></div>
<label for="username">Username</label><br>
<input value="" id="username" type="text" name="F783713994214KVBZZQ">
<label for="password">Password</label><br>
<input value="" id="password" type="password" name="F7837139942151QISNM">
<p><a data-at="e45a1d" href="/forgot_pwd">Forgot password?</a></p><br>
<button class="btn btn-primary" type="submit" name="F783714094216F0PPFD" value="_">LOGIN</button>
</form>
I think the name of the fields are both randomly generated (F783713994214KVBZZQ and F7837139942151QISNM), so I parse those out, but I'm not sure what to do with that information. There's no login page url specified that I can see. I've tried constructing a payload of the above strings and correct login info and posting it with no result.
When I watch the network activity in chrome's inspector, after I click the login button I can see a post to the site but there's no query string parameters (where I would expect to see the username & password).
Does anyone know what else I should be looking at to figure out where the username and password are going and how to access that via requests?
Full login page html: https://pastebin.com/vP1s9esZ
My code: https://pastebin.com/4jG13WfW
The page includes a login.js in the header, but it's only this:
$(document).ready(function() {
$("#username").focus();
// Centers the div
$("#login").position({
of: window,
at: "center center"
});
});
Thanks in advance for any help!
You're looking for Selenium if you want to automate the login flow. But, if you want to make a request to the site, start with the network monitor. Click login and grab the request that goes to the site. They would either send it as a form or a payload.
Read more of the same at What's the difference between "Request Payload" vs "Form Data" as seen in Chrome dev tools Network tab

How to post the form tag action value in ejs?

is there any know that?
I'm testing some javascript as follows
function mem_join_next() {
if (document.mem_join.email.value == "") {
alert("please input your email ID");
document.mem_join.email.focus();
return;
}
document.mem_join.submit();
}
<form name="mem_join" action="/join_step_3" method="post">
<div class="col-xs-12 id">
<p><span>EMAIL</span><span class="star">*</span>
</p>
<input name='email' class="email1" type="text" style="IME-MODE: disabled" size="11">#
<input class="email2" type="text">
<div class="email-check">email_check</div>
</div>
<div class="col-xs-6 next" align="right">
<a onClick="mem_join_next()" style="cursor:pointer">
<img src="/page_imgs/member_img/btn-next.jpg">
</a>
</div>
It's code what i want to run.
But when It is processing, the screen come out the 404 not found error.
even it is right route.
I think the post is not working
cause if i go straight way to single URL address(localhost/join_step_3) , the screen come out the /join_step_3 address screen.
but if i go From join_step_2 form next button TO join_step_3, It is 404 not found please hell me! GOD PROGRAMMERS!
If you directly typed the url and it worked means the page at localhost/join_step_3 worked using GET, because the browser url uses the GET Method.
So, it is quite possible that your localhost/join_step_3 doesn't support POST Method. Therefore, either add the post support on the page depending on the server-side scripting you use, or change method="post" to method="get" in your client html.

Log in from another php file with jquery load function

I would like to do a web site using Aptana IDE and xampp, and it has a few pages. Index page is where all users which does not log in the system and home is where all users which does log in the system must visit. I am very new to develop web site. Because of that I am changing a lot of and vital things during the development. An here my problem is began.
I have created log and sign pages separately using HTML5, CSS, Javascript, JQuery and Php. To achieve more quality service, decided to use also Ajax. These pages works correctly, log page can control validation with jquery
$('#login-form').validate({
//validation rules, messages and submitHandler(ajax code) goes here});
and with using ajax, it can communicate with php file and mysql database so can check whether the user is exist or not.
$.ajax({
type: 'POST',
url: 'log.php',
data: strAjax, //username and password
success: function(data) { //data is echoing from php file either as true or false
if(data) {
window.location.href = "home.php";
}
else {
//some error messages
}
}
});
Sign systems works like it and correctly. But I do not like the design of these pages because of emptiness. So in index file when user click log in button, the log file is showing inside a div with jquery load function.
$(".jumbotron").load("login.html").hide().fadeIn(1500).delay(5000);
Same thing for sign system as well. For good looking, I am satisfied but...
The whole system messed up. (I want to cry) I have to think before start to coding web site, very bad I know but this is my first complete web site. How can achieve a system working properly in this way? I have searched some pages on the internet and they said that the ajax can not work across the pages or something like that. I am also new to stack overflow too, so some important thing will be forgotten. I can edit if you want more information.
Thank You and Regards...
EDIT 1:
<div class="jumbotron">
<div class="container">
<h1>//sometext</h1>
<p>//some text</p>
</div>
</div>
Firstly this is showing on the screen. And when the user press login button, jquery load function running which is above. And loads login.html which works properly by itself.
<form id="login-form" class="text-left">
<div class="form-group">
<label for="lg_username" class="sr-only">Username</label>
<input type="text" class="form-control" id="lg_username" name="username" placeholder="username"
data-container="body" data-toggle="popover" data-placement="left" data-content=""
value="">
</div>
<div class="form-group">
<label for="lg_password" class="sr-only">Password</label>
<input type="password" class="form-control" id="lg_password" name="password" placeholder="password"
data-container="body" data-toggle="popover" data-placement="left" data-content="">
</div>
<div class="form-group login-group-checkbox">
<input type="checkbox" id="lg_remember" name="lg_remember">
<label for="lg_remember">remember</label>
</div>
<button type="submit" class="login-button">Submit</button>
</form>
The jquery validation works right. My rules are valid. If the inputs are ok upon my rules, it send me to home.php. I think ajax code can not work.
submitHandler: function() {
var username = $('#lg_username').val();
var password = $('#lg_password').val();
var checkbox = $('#lg_remember').is(":checked");
var strAjax = "username=" + username + "&password=" + password + "&checkbox=" + checkbox;
$.ajax({
type: 'POST',
url: 'logDeneme.php',
data: strAjax,
cache: false,
success: function(data) {
if(data) {
window.location.href = "home.php";
}
else {
//error message. but when this code run, always send to home page.
}
}
});
return false;
}
This parts all works. It does not works inside index.php. My question is why and how to handle this!
Problem 1
Your form is submitting via a GET request because the JS is not getting called (see #2 below) and the HTML is likely declared like this:
<form action='log.php'>
[...]
</form>
You must specify method='post' to submit POST data.
Problem 2
Unless you're using a jQuery plugin there is no .validate event for forms. You want to use .submit.
Finally, make sure all your javascript is in $(document).ready(function() { ... }); or it won't execute at the right time. Look in the Firefox/Chrome developer console, it's a lifesaver for debugging.

Safari 7 infinite POST request

I've get stuck with such issue. I have a form. When user submits his data, I'm sending some data via post ajax request. On success I set some data to hidden form, which has action pointing to current url subdomain, but in fact to partner site url that is set over CNAME. Then I trigger jQuery submit event on this hidden form, so after response user is on partner site (hidden form has no target attribute). It works fine in any browser except Safari 7 on mac. It just load for infinite time.
Any help is appreciated.
Well, there's not much code. Onsuccess of I run this:
if (response.result === true) {
this.targets.login.$email.val(response.data.data.email);
this.targets.login.$password.val(response.data.data.password);
this.targets.login.$form.submit();
}
My hidden form looks like this:
<form action="http://someurlunderCNAME" method="POST">
<input type="hidden" name="_method" value="POST">
<input type="text" name="data[User][email]">
<input type="password" name="data[User][password]">
</form>
Ok, I've got it myself. The reason was triggering submit on form. And the 'correct' behaiviour is to trigger click on submit input (which, btw, should be added too)

change the way the form is submitted without using javascript

I have a form that is used for search on a website.
<form method="get" action="example.com/search">
<input type="text" name="search"/>
<input type="submit"/>
</form>
Lets say that I searched for "stack" when submitting I want the user to get redirected to example.com/search:stack
right now when submitting user gets redirected to : example.com/search?search=stack
How can I achieve that and allow it on devices that does not support javascript!?
You could set up your search page to redirect your users from /search?search=stack to /search:stack.
PHP:
if(isset($_GET['search']))
{
$search = $_GET['search'];
header('Location: /search:'.$search);
}
else
// no query handling
You'll need Url rewriting to do that.
URL Rewriting for Beginners
You cannot. Submitting a form in the way you describe, i.e. with the GET method, encodes the content of the form as a query string, which has this form:
?search=stack
See section 4.10.22 of the HTML5 Living Standard or section 17.13.3 of the HTML 4.01 Specification.
Correction: I'm sorry, I did not understand your question correctly. You indeed cannot change how the form is submitted, but you can redirect afterwards as you suggest.
Álvaro Martínez suggests a good way to accomplish that in his answer.

Categories

Resources