rewrite post message login

This commit is contained in:
Konstantin Haase 2012-12-05 14:02:42 +01:00
parent d3ed96f165
commit 811aa47098

View File

@ -263,95 +263,158 @@ __END__
console.log('refusing to send a token to <%= target_origin.inspect %>, not whitelisted!'); console.log('refusing to send a token to <%= target_origin.inspect %>, not whitelisted!');
</script> </script>
@@ common
function tellEveryone(msg, win) {
if(win == undefined) win = window;
win.postMessage(msg, '*');
if(win.parent != win) tellEveryone(msg, win.parent);
if(win.opener) tellEveryone(msg, win.opener);
}
@@ container @@ container
<!DOCTYPE html> <!DOCTYPE html>
<html> <html><body><script>
<body> // === THE FLOW ===
<script>
console.log('welcome to the wonderful world of authentication'); // every serious program has a main function
function main() {
doYouHave(thirdPartyCookies,
yesIndeed("third party cookies enabled, creating iframe",
doYouHave(iframe(after(5)),
yesIndeed("iframe succeeded", done),
nopeSorry("iframe taking too long, creating pop-up",
doYouHave(popup(after(5)),
yesIndeed("pop-up succeeded", done),
nopeSorry("pop-up failed, redirecting", redirect))))),
nopeSorry("third party cookies disabled, creating pop-up",
doYouHave(popup(after(8)),
yesIndeed("popup succeeded", done),
nopeSorry("popup failed", redirect))))();
}
// === THE LOGIC ===
var url = window.location.pathname + '/iframe' + window.location.search; var url = window.location.pathname + '/iframe' + window.location.search;
function thirdPartyCookies(yes, no) {
window.cookiesCheckCallback = function(enabled) { enabled ? yes() : no() };
var img = document.createElement('img'); var img = document.createElement('img');
var popUpWindow, timeout;
var handshake = location.protocol + "//" + location.host + "/auth/handshake?redirect_uri=";
img.src = "https://third-party-cookies.herokuapp.com/set"; img.src = "https://third-party-cookies.herokuapp.com/set";
img.onload = function() { img.onload = function() {
var script = document.createElement('script'); var script = document.createElement('script');
script.src = "https://third-party-cookies.herokuapp.com/check"; script.src = "https://third-party-cookies.herokuapp.com/check";
window.document.body.appendChild(script); window.document.body.appendChild(script);
} }
}
window.document.body.appendChild(img); function iframe(time) {
return function(yes, no) {
function iframe() {
var iframe = document.createElement('iframe'); var iframe = document.createElement('iframe');
iframe.src = url; iframe.src = url;
timeout(time, yes, no);
window.document.body.appendChild(iframe); window.document.body.appendChild(iframe);
} }
function popUp() {
popUpWindow = window.open(url, 'Signing in...', 'height=400,width=800');
return (!popUpWindow || popUpWindow.closed || typeof popUpWindow.closed == 'undefined');
} }
function uberParent(win) { function popup(time) {
return win.parent === win ? win : uberParent(win.parent); return function(yes, no) {
if(popupWindow) {
timeout(time, yes, function() {
if(popupWindow.closed || popupHidden) {
no()
} else {
try {
popupWindow.focus();
popupWindow.resizeTo(900, 500);
} catch(err) {
no()
}
}
});
} else {
no()
}
}
}
function done() {
if(popupWindow && !popupWindow.closed) popupWindow.close();
} }
function redirect() { function redirect() {
win = uberParent(window); tellEveryone('redirect');
win.location = handshake + win.location;
} }
function createPopup() {
if(!popupWindow) {
popupWindow = window.open(url, 'Signing in...', 'height=50,width=50');
popupWindow.onload = function() {
try {
popupHidden = popupWindow.innerHeight > 0;
maybe(function() { popupWindow.focus() });
} catch(err) {
popupHidden = false;
}
}
}
}
// === THE PLUMBING ===
<%= erb :common %>
function timeout(time, yes, no) {
var timeout = setTimeout(time, no);
onSuccess(function() {
clearTimeout(timeout);
yes()
});
}
function onSuccess(callback) {
succeeded ? callback() : callbacks.push(callback)
}
function doYouHave(feature, yes, no) {
return function() { feature(yes, no) };
}
function yesIndeed(msg, callback) {
if(console && console.log) console.log(msg);
return callback;
}
function after(value) {
return value*1000;
}
var nopeSorry = yesIndeed;
var timeoutes = [];
var callbacks = [];
var seconds = 1000;
var succeeded = false;
var popupWindow, popupHidden;
window.addEventListener("message", function(event) { window.addEventListener("message", function(event) {
console.log('handshake succeeded, cleaning up');
if(event.data === "done") { if(event.data === "done") {
if(timeout) clearTimeout(timeout); succeeded = true
if(popUpWindow && !popUpWindow.closed) popUpWindow.close(); for(var i = 0; i < callbacks.length; i++) {
(callbacks[i])();
}
} }
}); });
function cookiesCheckCallback(thirdPartyCookiesEnabled) { // === READY? GO! ===
if(thirdPartyCookiesEnabled) { main();
console.log("third party cookies enabled, creating iframe");
iframe();
timeout = setTimeout(function() {
console.log('handshake taking too long, creating pop-up');
if(!popUp()) {
console.log("pop-up failed, redirecting");
redirect();
}
}, 5000);
} else {
console.log("third party cookies disabled, creating pop-up");
if(!popUp()) {
console.log("pop-up failed, trying iframe anyhow");
iframe();
timeout = setTimeout(function() {
console.log('handshake taking too long, redirecting');
if(!popUp()) { redirect(); }
}, 5000);
}
}
}
</script> </script>
</body> </body>
</html> </html>
@@ post_message @@ post_message
<script> <script>
<%= erb :common %>
function uberParent(win) { function uberParent(win) {
return win.parent === win ? win : uberParent(win.parent); return win.parent === win ? win : uberParent(win.parent);
} }
function tellEveryone(msg, win) {
if(win == undefined) win = window;
win.postMessage(msg, '*');
if(win.parent != win) tellEveryone(msg, win.parent);
if(win.opener) tellEveryone(msg, win.opener);
}
function sendPayload(win) { function sendPayload(win) {
var payload = <%= user.to_json %>; var payload = <%= user.to_json %>;
payload.token = <%= token.inspect %>; payload.token = <%= token.inspect %>;