IonAuth - seems to be randomly logging me out - codeigniter

I'm using ionAuth & it seems to be logging me out almost randomly? I'm using Codeigniter v2.1.4 - it logs in perfect fine however ionAuth seems to log out at random intevals, is there a way to force the session to stay active until I call the ionAuth->logout function?
My CI config looks like as follows:
$config['sess_cookie_name'] = 'cisession';
$config['sess_expiration'] = 7200;
$config['sess_expire_on_close'] = FALSE;
$config['sess_encrypt_cookie'] = FALSE;
$config['sess_use_database'] = TRUE;
$config['sess_table_name'] = 'ci_sessions';
$config['sess_match_ip'] = FALSE;
$config['sess_match_useragent'] = TRUE;
$config['sess_time_to_update'] = 600;
My ion_auth config file looks as follows:
$config['user_expire'] = 0;
$config['user_extend_on_login'] = FALSE;
Can anyone give me any pointers on what might be causing the issue(s)?

The cause of the problem is a session cookie rotation when an AJAX Call is performed, the proper fix was included in CodeIgniter 3
You have four options:
Cope:
I faced this problem myself before without knowing exactly the cause of it. In short, I saved the promise of each XMLHttpRequest, if the HTTP status code 401 was encountered, the client side application would request the credentials in the form of a popup, and then retry the AJAX promise.
Client side with jQuery, just add this ajaxError handler:
$(document).ajaxError(function (e, xhr, settings, exception) {
if (xhr.status == 401)
{
// open your popup
$('#login-popup').modal('open');
// attach the xhr object to the listener
$(document).bind( "retry-xhr", {
xhro: xhr
},
function( event ) {
// retry the xhr when fired
$.ajax( event.data.xhro );
});
}
});
and when you are logged back in, just call this to retry your request:
$(document).trigger('retry-xhr');
Server side, you only need to add an if in your constructor
if (!$this->session->userdata('logged_in') && $this->input->is_ajax_request())
{
$this->output->set_status_header('401');
exit;
}
This was useful because some users would leave their web app window open overnight and the session timeout would kick in. Then the users would call me about not being able to do any AJAX function, and I would have to tell them to press F5
ps. if on Angular, I have used the HTTP Auth Interceptor Module successfully
Hack:
See this post, his solution is to create another field in the ci_session table and check for both cookies, so your session will still be valid after rotation.
It also explains in detail what is causing this glitch
http://www.hiretheworld.com/blog/tech-blog/codeigniter-session-race-conditions
Upgrade:
Start using the next version where it's already fixed:
https://github.com/EllisLab/CodeIgniter/tree/release/3.0
Patch
Replace line 346 in system/libraries/Session.php (function sess_update())
if (($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now)
With:
if (($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now || $this->CI->input->is_ajax_request())

Related

webRequest API redirect uses http method of parent request

I'm using the webRequest-API in a WebExtension to monitor requests made by the client. This works quite well, however the API doesn't behave as expected in case of a redirect:
In this case a POST is issued which is answered with a 302 FOUND and a new location. My browser (Firefox 57, other versions and other browsers - e.g. Chrome - act the same way) follows this redirect and now issues a GET to the new location.
Unfortunately the webRequest-API behaves differently: It traces the first POST (which is correct) but than handles the second request as a POST, too, whereas it should be a GET. This is a severe problem since the API traces something my browser supposedly did, which it actually did in another way...
This scenario (the browser-part) can be reproduced by following this link to surfnet.nl and choosing an IDP form the list (e.g. Academisch Medisch Centrum).
So, long story short: Why does the webRequest-API behave different form the way browsers behave? And is there a way to let it exactly trace the browser's actions?
Interestingly the webRequest-API might do it correctly, regarding the documentation:
Even if the specification requires the method, and the body, not to be altered when the redirection is performed, not all user-agents conform here [browsers obviously change the method!], and you can still find buggy software out there. It is therefore recommended to set the 302 code only as a response for GET or HEAD methods and to use 307 Temporary Redirect instead, as the method change is explicitly prohibited in that case.
In the cases where you want the method used to be changed to GET, use 303 See Other instead.
EDIT:
It seems as if browser change the method on a 302 due to historical reasons, even tho it contradicts RFC 2616...
https://stackoverflow.com/a/8139246/594832
https://trac.ietf.org/trac/httpbis/ticket/160
https://stackoverflow.com/a/8138447/594832
Anyways... the question remains: how can I induce the webRequest-API to act the same way?
For anyone interested, I ended up with the following:
The docs let me to this (redirectUrl):
[...] Redirects initiated by a redirect action use the original request method for the redirect, with one exception: If the redirect is initiated at the onHeadersReceived stage, then the redirect will be issued using the GET method. [...]
Although the statement above gave me some hope, the method of that redirected request was still labeled as a POST...
So I updated the code to something roughly like this:
// Keep track of all requests issued so far and their responses
var httpRequests = [];
// Redirected requests come in with their originating parents' ID
browser.webRequest.onBeforeRequest.addListener(request => {
// Check if the request is a redirect
var isRedirected = function(requestId) {
var parentRequest = httpRequests.find(r => r.req.requestId === requestId);
if (parentRequest != null && parentRequest.res != null && parentRequest.res.statusCode === 302) {
return true;
}
return false;
};
// The webRequest-API seems to keep the HTTP verbs which is correct in resepct to RFC 2616 but
// differs from a typical browser behaviour which will usually change the POST to a GET. So do we here...
if (request.method === 'POST' && isRedirected(request.requestId)) {
console.log(`Redirected 302-request '${request.requestId}' is a POST but is here changed to a GET to conform to browser behaviour...`);
request.method = 'GET';
}
// Store the request
var entry = {
id: id,
req: request
};
httpRequests.push(entry);
});
browser.webRequest.onHeadersReceived.addListener(response => {
// Store the response alongside the request
var entry = httpRequests.find(req => req.id === response.requestId);
entry.res = response;
// If it turns out that a request should be redirected...
if (response.statusCode === 302) {
var location = response.responseHeaders.find(header => header.name.toLowerCase() === "location");
console.log(`Redirecting request '${id}' to new location '${location.value}'...`);
// The new location is set as redirectUrl, which results in a new invocation of onBeforeRequest with
// the current requestId
return {
redirectUrl: location.value
};
}
});
What happens?
Say onBeforeRequest receives a new request 2640 which is a POST.
onHeadersReceived gets the response which says that this request should be redirected to a new location (302).
The code above does so by setting the redirectUrl to that new location.
Then onBeforeRequest is triggered again. The webRequest-API passes the same requestId to it (2640).
The code checks if there's a parent for this request, and in this case it's true.
The method (which is still POST) is then modified to GET.
For the request lifecycle have a look at the illustration in the docs.

AJAX Newbie , POSTing data on server

I started learning AJAX recently and am trying a very simple project which involves capturing some form data and sending it to two servers.
The first server is the one which hosts the website and server side php handling. This worls fine
The second server is a python basic http server which handles only the POST operation request send from AJAX. This functionality works but is a bit weird.
Let me explain
Here is my AJAX code which is absolutely straight forward.
function xml_http_post(url, data) {
var req = false;
try {
// Firefox, Opera 8.0+, Safari
req = new XMLHttpRequest();
}
catch (e) {
// Internet Explorer
try {
req = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
req = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {
alert("Your browser does not support AJAX!");
return false;
}
}
}
req.onreadystatechange = function() {
if (req.readyState == 4) {
// callback(req);
}
}
req.open("POST", url, true);
req.setRequestHeader("Content-type","text/plain");
req.send(data);
}
Since I do not intend to send back any response , my callback function on ready state change is empty.
But when I execute this code ( triggered by onclick on a button) , the POST doesnt work and server doesnt seem to receive anything.
But the most surprising thing is that if I keep a breakpoint at req.open( ) and then do a manual step execution then it works always. Which means , I guess that there is some timing issue which needs to be resolved.
It works fine without breakpoints if the third parameter "async" is set to false but that is anyway undesirable so I want to make it work with async = true.
Any help would be greatly appreciated.
Thanks
Shyam
As I figured out, the form page was getting unloaded by a php script which was invoked as a action of the form b the first server. This resulted in the javascript code being partially or not executed.
So I figured out that sync XHR is the only way for my.

can't seem to get progress events from node-formidable to send to the correct client over socket.io

So I'm building a multipart form uploader over ajax on node.js, and sending progress events back to the client over socket.io to show the status of their upload. Everything works just fine until I have multiple clients trying to upload at the same time. Originally what would happen is while one upload is going, when a second one starts up it begins receiving progress events from both of the forms being parsed. The original form does not get affected and it only receives progress updates for itself. I tried creating a new formidable form object and storing it in an array along with the socket's session id to try to fix this, but now the first form stops receiving events while the second form gets processed. Here is my server code:
var http = require('http'),
formidable = require('formidable'),
fs = require('fs'),
io = require('socket.io'),
mime = require('mime'),
forms = {};
var server = http.createServer(function (req, res) {
if (req.url.split("?")[0] == "/upload") {
console.log("hit upload");
if (req.method.toLowerCase() === 'post') {
socket_id = req.url.split("sid=")[1];
forms[socket_id] = new formidable.IncomingForm();
form = forms[socket_id];
form.addListener('progress', function (bytesReceived, bytesExpected) {
progress = (bytesReceived / bytesExpected * 100).toFixed(0);
socket.sockets.socket(socket_id).send(progress);
});
form.parse(req, function (err, fields, files) {
file_name = escape(files.upload.name);
fs.writeFile(file_name, files.upload, 'utf8', function (err) {
if (err) throw err;
console.log(file_name);
})
});
}
}
});
var socket = io.listen(server);
server.listen(8000);
If anyone could be any help on this I would greatly appreciate it. I've been banging my head against my desk for a few days trying to figure this one out, and would really just like to get this solved so that I can move on. Thank you so much in advance!
Can you try putting console.log(socket_id);
after form = forms[socket_id]; and
after progress = (bytesReceived / bytesExpected * 100).toFixed(0);, please?
I get the feeling that you might have to wrap that socket_id in a closure, like this:
form.addListener(
'progress',
(function(socket_id) {
return function (bytesReceived, bytesExpected) {
progress = (bytesReceived / bytesExpected * 100).toFixed(0);
socket.sockets.socket(socket_id).send(progress);
};
})(socket_id)
);
The problem is that you aren't declaring socket_id and form with var, so they're actually global.socket_id and global.form rather than local variables of your request handler. Consequently, separate requests step over each other since the callbacks are referring to the globals rather than being proper closures.
rdrey's solution works because it bypasses that problem (though only for socket_id; if you were to change the code in such a way that one of the callbacks referenced form you'd get in trouble). Normally you only need to use his technique if the variable in question is something that changes in the course of executing the outer function (e.g. if you're creating closures within a loop).

With JavaScript Ajax polling for widget

I have the follow problem. I need to create a JS widget and set it on one blog, for example any blog from blogger.com. YOu can select there a box for javascript and I will post the JS in this box.
The problem what I have and don't know how to do this is, that the script should do an ajax polling for exmaple for 60 seconds. But how to execute an ajax call, when the host is not the same linke the host, where the JS is includet?
For example the easiest way to explai is: There is a search box and when enayone searches for anythign, then the JS script should streaming the results for 60 seconds from the server what I have set in the script and is different as the host, where the JS is includet, without to become a problem with the JS restriction for hosts.
Or for example a chat client, where the client is hosted on one other host and the server on another.
Can anyone tell me an idea, or send me an example how to do this?
Thanks
Nik
Well with this example is it possible but without JSONP?
function asyncreq(url) {
var xmlhttp = false;
try {
xmlhttp = new XMLHttpRequest();
} catch (trymicrosoft) {
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
xmlhttp = false;
}
}
}
if (xmlhttp){
try {
xmlhttp.open("GET", url);
xmlhttp.onreadystatechange=function() {
document.getElementById('mydiv').innerHTML = xmlhttp.responseText;
}
xmlhttp.send(null);
}
catch (failed) {
xmlhttp = false;
}
}
}
If you send the response in chunks, then everything is fine. But here is the call in ajax again. And when I use it in a different host, then I can't call the url because of the same-origin policy.
Is there another way?
I found a very interesting example here.
Take a look at the bottom, there is a job search box. If you investigate a litte bit, then you will see there is a usage of a class RSL() which is doing the request. How this class is doing the request without ajax? I can't understand wow this class works. Can anyone show me a better example?
There are two main options:
Put an iframe where you want the widget to go. Its src URL would be on the same server that will receive the AJAX call.
Use JSONP, which consists of inserting a script tag into the page to bypass the same-origin policy. This requires that the AJAX server wrap its JSON output in ?(...), where the URL includes callback=?. Then, as soon as a response has been received, start another request.

Jaxer and HTTP proxy requests

Thanks to everyone in advance.
I'm using Jaxer.sandbox and making requests just fine. I'd like these requests to go through my http proxy (like squid for example). Here is the code I that is currently working for me.
window.onload = function() {
//the url to scrape
var url = "http://www.cnn.com/";
//our sandboxed browser
var sandbox = new Jaxer.Sandbox();
//open optons
var openOptions = new Jaxer.Sandbox.OpenOptions();
openOptions.allowJavaScript = false;
openOptions.allowMetaRedirects = false;
openOptions.allowSubFrames = false;
openOptions.allowSubFrames = false;
openOptions.onload = function() {
//do something onload
};
//make the call
sandbox.open(url, null, openOptions);
//write the response
Jaxer.response.setContents(sandbox.toHTML());
};
How can I send this request through a proxy server?
Thanks,
Reza.
I didn't get any replies to this. :|
We ended up hacking around this by creating our own custom sandbox.openProxy() method in the jaxer framework. :)
Reza.

Resources