Logout through XMLHTTPRequest Object is not working in Opera - html

I am using the basic authentication mechanism for my website in IIS. To logout the user I am using something similar to this JavaScript function:
function logoutUser() {
setTimeout('location.reload(true)', 1000);
xmlhttp = GetXmlHttpObject();
if (xmlhttp==null) {
return;
}
//alert(xmlhttp);
var url = "index.php";
xmlhttp.open("GET", url, true, "dummy_user", "dummy_password");
xmlhttp.setRequestHeader( "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT" );
xmlhttp.setRequestHeader( 'Accept', 'message/x-formresult' );
xmlhttp.send(null);
}
function GetXmlHttpObject()
{
if (window.XMLHttpRequest)
{
// code for IE7+, Firefox, Chrome, Opera, Safari
return new XMLHttpRequest();
}
if (window.ActiveXObject)
{
// code for IE6, IE5
return new ActiveXObject("Microsoft.XMLHTTP");
}
return null;
}
The idea is to force a request with some invalid credentials, in order to invalidate the real credentials cached by the browser.
It is working fine in IE,Firefox, Safari, Google Chrome but not in Opera.
Please help me in this regard.

That setting invalid credentials in an XMLHttpRequest should cause valid credentials to be discarded is not something you can rely on. It happens to work in many browsers but it's not at all standardised. Opera is not doing anything wrong by ignoring the credentials.
There is no standard way to cause HTTP Basic Authentication credentials to be dropped. There's one more way which works more widely, which is to have a link to /logout, a script that responds 401 when the user has valid credentials instead of when they do not. That will pop open an auth dialog, in which the user can fill in nonsense values or just empty strings; then when /logout is re-requested, it accepts those credentials, replacing the old ‘real’ ones.
Pairing this method and XMLHttpRequest is about the best you can do to provide logout capability for HTTP Authentication today.

Use any good JavaScript library. eg.jQuery...
so you will have not any browser specific problem.

It will be better to do an ajax call to a page that destroys session data; a page like logout.asp that has a call to Session.Abandon() or session_destroy() in php language
logout.php:
<?php session_destroy();?>
logout.aspx or logout.asp:
//other functions can go here before ending the session
<% Session.Abandon() %>
then the javascript function :
function(){
$.ajax({
url:'logout.php',//or logout.aspx or logout.asp
success:function(){location.reload();},
});
}
you should load jquery.js on the page that is making this logout call

Related

Apps Script webhooks and Access-Control-Allow-Origin header missing

I have a Google Apps Script project acting as a webhook. When calling the endpoint using a library like htmx, the preflight check fails and the request subsequently fails. When calling directly with fetch or XMLHttpRequest, it works fine.
I have a sample endpoint with a simple doPost for testing:
const doPost = (request = {}) => {
const { postData: { contents, type } = {} } = request;
return ContentService.createTextOutput(contents);
};
This Codepen sample shows how requests with HTMX fail while fetch and XHRHttpRequest are successful.
Some things I've learned:
The OPTIONS header sent in a preflight results in a 405 error, aborting the request entirely. You can mimic this by sending an OPTIONS request via Postman (or similar) to the web app URL.
The error doesn't include Access-Control-Allow-Origin header, which is what shows as the failure reason in the console.
HTMX sends non-standard headers, which trigger preflight requests in modern browsers. However, you can strip all headers out, which should bypass the preflight, but doesn't. See this related discussion in the repo.
In this kind of situation, what is the best method for debugging? I'm not really sure what else to try to get this working.
This is an issue with HTMX, that requires modification of its source code. The source of the problem is that HTMX adds some event listeners to xhr.upload that makes the browsers mark the request as "not simple", triggering the CORS preflight request:
If the request is made using an XMLHttpRequest object, no event listeners are registered on the object returned by the XMLHttpRequest.upload property used in the request; that is, given an XMLHttpRequest instance xhr, no code has called xhr.upload.addEventListener() to add an event listener to monitor the upload
The specific part of HTMX source code:
forEach(['loadstart', 'loadend', 'progress', 'abort'], function(eventName) {
forEach([xhr, xhr.upload], function (target) {
target.addEventListener(eventName, function(event){
triggerEvent(elt, "htmx:xhr:" + eventName, {
lengthComputable:event.lengthComputable,
loaded:event.loaded,
total:event.total
});
})
});
});
Sadly, the addEventListener uses anonymous functions, so there's no way to remove them with removeEventListener AFAIK.
But if you are willing to use a custom HTMX script in your app until the authors fix this issue (e.g. add ability to prevent event listener creation on xhr.upload), just remove the xhr.upload from the list in the second row:
forEach(['loadstart', 'loadend', 'progress', 'abort'], function(eventName) {
forEach([xhr], function (target) {
target.addEventListener(eventName, function(event){
triggerEvent(elt, "htmx:xhr:" + eventName, {
lengthComputable:event.lengthComputable,
loaded:event.loaded,
total:event.total
});
})
});
});
With this modification your original suggestion of removing non-standard HTMX-specific headers via evt.detail.headers = [] will work, since now this request becomes "simple", so no more CORS preflight is made by the browsers.
Note: the modification may break the HTMX file upload, I did not test it.

webrtc: failed to send arraybuffer over data channel in chrome

I want to send streaming data (as sequences of ArrayBuffer) from a Chrome extension to a Chrome App, since Chrome message API (includes chrome.runtime.sendMessage, postMessage...) does not support ArrayBuffer and JS arrays have poor performance, I have to try other methods. Eventually, I found WebRTC over RTCDataChannel might a good solution in my case.
I have succeeded to send string over a RTCDataChannel, but when I tried to send ArrayBuffer I got:
code: 19
message: "Failed to execute 'send' on 'RTCDataChannel': Could not send data"
name: "NetworkError"
It seems that it's not a bandwidths limits problem since it failed even though I sent one byte of data. Here is my code:
pc = new RTCPeerConnection(configuration, { optional: [ { RtpDataChannels: true } ]});
//...
var dataChannel = m.pc.createDataChannel("mydata", {reliable: true});
//...
var ab = new ArrayBuffer(8);
dataChannel.send(ab);
Tested on OSX 10.10.1, Chrome M40 (Stnble), M42(Canary); and on Chromebook M40.
I have filed a bug for WebRTC here.
I modified my code, now everything worked amazing:
removed RtpDataChannels option when creating RTCPeerConnection.(YES, remove RtpDataChannels option if you want data channel, what a magic world!)
on receiver side: no need createDataChannel, instead, handle onmessage, onxxx by using event.channle from pc.ondatachannel callback:
pc.ondatachannel function(event)
var receiveChannel = event.channel;
receiveChannel.onmessage = function(event){
console.log("Got Data Channel Message:", event.data);
};
};

xmlHttpRequest to absolute url in WP8

I have stumbled across an odd issue when testing an app in Windows Phone 8. I am using xmlHttpRequest (cannot use ajax as I need to send as bufferarray) to make a call to a third party url. This works perfectly in Android and iOS, but throws an error in WP8
Example:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function (){
if(xhr.readyState == 4){
if(xhr.status==200){
alert(xhr.responseText);
}else{
console.log("Error: "+xhr.responseText);
}
}
}
console.log("1");
xhr.timeout = 30000;
console.log("2");
xhr.open("POST","http://google.com",true);
console.log("3");
xhr.setRequestHeader("Content-Type",contentType+"; boundary=" + boundary);
console.log("4");
//other headers / auth etc
console.log("about to post");
xhr.send(bodyBuf);
this will result in:
log:"before request"
log:"1"
log:"2"
log:"Error in error callback: Cameraxxxxx = InvalidStateError"
However if I chang the open to:
xhr.open("POST","google.com",true); //or www.google.com etc
This goes right through to send, but then get a 404 status as the url is not found. I am obviously not using google in my request, but the error is the same. With "http://" it errors, but without, it doesn't error but cannot find the url.
Any thoughts appreciated.
I have found one thing, but unsure if it is related. According to W3C html 5 documentation, InvalidStateError is thown on open() if document is not fully active (when it is the active document of its browsing context). And if this is the cause of the error; how can the document not be the active document and how to I define the base url of an app that does not reside on a url (document suggests setting base to the document base url of document (or setting source origin/referrer source))?
Have gotten one step closer. After lots of fiddling about, I eventually found that for some reason on WP8 is needs the xhr to be opened before anything else is applied. So moving xhr.timeout below xhr.open sort of works.
this raises another problem in my particular case.. but that is probably another topic.
Solution for this was to move the timout to below the open.. so:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function (){
if(xhr.readyState == 4){
if(xhr.status==200){
alert(xhr.responseText);
}else{
console.log("Error: "+xhr.responseText);
}
}
}
xhr.open("POST","http://google.com",true);
xhr.timeout = 30000;
xhr.setRequestHeader("Content-Type",contentType+"; boundary=" + boundary);
//other headers / auth etc
xhr.send(bodyBuf);

Chrome addon with my server interaction

its many days reading hundreds of ways to help me make what I really need. No success at all.
What I need is this:
1) Having a button which only works when the tab has a certain url.
2) After clicking it, must read page's source and then get some pieces of it to send them to my server page in order to check my database for recordcounts (I assume with AJAX & javascript). Then this page should send back to the extension its responses and populate the popup html.
Looks easy I know, but please I need the workflow if not the required codes for the extension.
Thank you so much!
ok so you can chceck selected tab and it's url with:
chrome.tabs.getSelected(null,function(tab) {
workWithUrl(tab.url);
});
...
function workWithUrl(url){
if (url == ...
...
}
To be able to chceck this you need to add permission for "tabs"
To process page source code, send it to web service and change popup.html:
var xhr = new XMLHttpRequest();
xhr.open("POST", "__server adress___", true);
//headers
xhr.setRequestHeader("Content-Type", "application/json");
//response
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
//response from service to popup.html
document.body.innerHTML = xhr.responseText;
}
}
//process page here
xhr.send(pageText);
You have to add permission for server adress to manifest as well and everything should be executed from popup.js (or html).

Using jQuery.getJSON in Chrome Extension

I need to do a cross-domain request in a chrome extension. I know I can it via message passing but I'd rather stick to just jQuery idioms (so my javascript can also work as a <script src="">).
I do the normal:
$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?", function(data) {
console.log(data);
});
but in the error console I see:
Uncaught ReferenceError: jsonp1271044791817 is not defined
Is jQuery not inserting the callback function correctly into the document? What can I do to make this work?
(If I paste the code into a chrome console, it works fine, but if I put it as the page.js in an extension is when the problem appears.)
Alas, none of these worked, so I ended up doing the communication via the background.html.
background.html
<script src="http://code.jquery.com/jquery-1.4.2.js"></script>
<script>
function onRequest(request, sender, callback) {
if (request.action == 'getJSON') {
$.getJSON(request.url, callback);
}
}
chrome.extension.onRequest.addListener(onRequest);
</script>
javascripts/page.js
chrome_getJSON = function(url, callback) {
console.log("sending RPC");
chrome.extension.sendRequest({action:'getJSON',url:url}, callback);
}
$(function(){
// use chrome_getJSON instead of $.getJSON
});
If you specify "api.flickr.com" in your manifest.json file you will not need to use the JSONP callback, script injection style of cross domain request.
For example:
"permissions": ["http://api.flickr.com"],
This should work beautifully in you code. I would remove the querystring parameter "&jsoncallback" as there is no JSONP work needed.
The reason why your current code is not working is your code is injecting into pages DOM, content scripts have access to the DOM but no access to javascript context, so there is no method to call on callback.
My impressions it that this fails because the jQuery callback function is being created within the 'isolated world' of the Chrome extension and is inaccessible when the response comes back:
http://code.google.com/chrome/extensions/content_scripts.html#execution-environment
I'm using Prototype and jQuery for various reasons, but my quick fix should be easy to parse:
// Add the callback function to the page
s = new Element('script').update("function boom(e){console.log(e);}");
$$('body')[0].insert(s);
// Tell jQuery which method to call in the response
function shrink_link(oldLink, callback){
jQuery.ajax({
type: "POST",
url: "http://api.awe.sm/url.json",
data: {
v: 3,
url: oldLink,
key: "5c8b1a212434c2153c2f2c2f2c765a36140add243bf6eae876345f8fd11045d9",
tool: "mKU7uN",
channel: "twitter"
},
dataType: "jsonp",
jsonpCallback: callback
});
}
// And make it so.
shrink_link('http://www.google.com', "boom");
Alternatively you can try using the extension XHR capability:
http://code.google.com/chrome/extensions/xhr.html
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://api.example.com/data.json", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// JSON.parse does not evaluate the attacker's scripts.
var resp = JSON.parse(xhr.responseText);
}
}
xhr.send();
The syntax is a little off. There's no need for the callback( bit. This works flawlessly. Tested in the javascript console of Chrome on this StackOverflow page (which includes jQuery):
$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?", function(data) {
console.log(data);
});
As many of you will know, Google Chrome doesn't support any of the handy GM_ functions at the moment.
As such, it is impossible to do cross site AJAX requests due to various sandbox restrictions (even using great tools like James Padolsey's Cross Domain Request Script)
I needed a way for users to know when my Greasemonkey script had been updated in Chrome (since Chrome doesn't do that either...). I came up with a solution which is documented here (and in use in my Lighthouse++ script) and worth a read for those of you wanting to version check your scripts:
http://blog.bandit.co.nz/post/1048347342/version-check-chrome-greasemonkey-script