I need only one tab accessible for my website. When he tries to open in new tab or even tries to copy and paste the url in new tab should clear the user's session and logout from the application.
There are several reasons,
When a user opens a new tab connecting to the same application - the session id is the same.
Imagine that this user has reached a page X in the application flow from the first tab.
When he opens the second tab he might be in one of the following scenarios - depending how the second tab was opened - new tab, duplicate tab (this copies the URL to the newly opened tab), or new session.
All of the above will "confuse" the server as to what the next valid state of the application is, and could override data entered in different tab, without his/her knowledge
What I want is to prevent a single user to have several tabs in the same session, i.e. only one tab/window per user, per session.
Including the below script in dashboard.php after login
<script>
$(document).ready(function()
{
if(typeof(Storage) !== "undefined")
{
if (sessionStorage.pagecount)
{
sessionStorage.removeItem('pagecount');
window.location='logout.php';
}
else
{
sessionStorage.pagecount = 1;
}
}
else
{
sessionStorage.removeItem('pagecount');
window.location='logout.php';
}
});
Below code in other sub pages in the application
<script>
$(document).ready(function()
{
if(typeof(Storage) !== "undefined")
{
if (sessionStorage.pagecount)
{
sessionStorage.pagecount = Number(sessionStorage.pagecount) + 1;
}
else
{
sessionStorage.removeItem('pagecount');
window.location='logout.php';
}
}
else
{
sessionStorage.removeItem('pagecount');
window.location='logout.php';
}
});
</script>
Added the below script after I login(say dashboard.php)
<script>
$(document).ready(function()
{
$("a").attr("target", "");
if(typeof(Storage) !== "undefined")
{
sessionStorage.pagecount = 1;
var randomVal = Math.floor((Math.random() * 10000000) + 1);
window.name = randomVal;
var url = "url to update the value in db(say random_value)";
$.post(url, function (data, url)
{
});
}
else
{
var url = "url to remove random_value";
$.post(url, function (data, url)
{
sessionStorage.removeItem('pagecount');
sessionStorage.clear();
window.location = 'logout.php';
});
}
});
</script>
Added the below script in Header in rest of my pages - 'random_value' is from db for that user
<script>
$(document).ready(function()
{
$("a").attr("target", "_self");
if(typeof(Storage) !== "undefined")
{
if (sessionStorage.pagecount)
{
if('<?=$random_value?>' == window.name)
{
sessionStorage.pagecount = Number(sessionStorage.pagecount) + 1;
}
else
{
var url = "url to remove random_value";
$.post(url, function (data, url)
{
sessionStorage.removeItem('pagecount');
sessionStorage.clear();
window.location = 'logout.php';
});
}
}
else
{
var url = "url to remove random_value";
$.post(url, function (data, url)
{
sessionStorage.removeItem('pagecount');
sessionStorage.clear();
window.location = 'logout.php';
});
}
}
else
{
var url = "url to remove random_value";
$.post(url, function (data, url)
{
sessionStorage.removeItem('pagecount');
sessionStorage.clear();
window.location = 'logout.php';
});
}
});
</script>
<script>
$(document).ready(function()
{
$("a").attr("target", "");
if(typeof(Storage) !== "undefined")
{
sessionStorage.pagecount = 1;
var randomVal = Math.floor((Math.random() * 10000000) + 1);
window.name = randomVal;
var url = "url to update the value in db(say random_value)";
$.post(url, function (data, url)
{
});
}
else
{
var url = "url to remove random_value";
$.post(url, function (data, url)
{
sessionStorage.removeItem('pagecount');
sessionStorage.clear();
window.location = 'logout.php';
});
}
});
</script>
Related
Goal of this poc:
a way to keep the user logged in across webapps
on different domains
do it once, import it everywhere
The poc:
So I thought of this possible solution. I call it the user widget.
Let's say we have service AUTH that provides the endpoint to login and logout, it also sets the httpOnly cookie.
This should be the header, distributed across webapps. The header downloads the iframe and with postMessage send calls to it, to understand if the user is already logged in, otherwise shows login:
<script>
/**
****************************************
* Code that should be inside the header
****************************************
*/
window.onload = function() {
(function(){
if (window.addEventListener) {
window.addEventListener("message", handleMessage, false);
} else {
window.attachEvent("onmessage", handleMessage);
}
//- This could be * meaning no preferences, or a URI,
//- but SHOULD not be * but the correct origin
var iframeOrigin = "*";
var iframeId = 'IFRAME-PROXY';
createIframe(checkStatusOfLogin);
var doLoginButton = document.getElementById('do-login');
doLoginButton.onclick = doLogin;
function createIframe(onLoadCallback) {
var iframe = document.createElement('iframe');
iframe.id = iframeId;
iframe.style.display = 'none';
iframe.src = 'https://mysecureiframe.securedomain.com/file.html';
document.body.appendChild(iframe);
iframe.onload = function () {
onLoadCallback(iframe);
};
}
function checkStatusOfLogin(iframe) {
var iframeWin = iframe.contentWindow;
var payload = {
action: 'status'
};
iframeWin.postMessage(JSON.stringify(payload), iframeOrigin);
}
function doLogin() {
var iframeWin = document.getElementById(iframeId).contentWindow;
var payload = {
action: 'login',
username: document.getElementById('username').value,
password: document.getElementById('password').value
};
iframeWin.postMessage(JSON.stringify(payload), iframeOrigin);
}
function handleMessage(evt) {
console.log('Inside client tab, received: ', evt);
var userContainer = document.getElementById('user-container');
try {
var parsedResponse = JSON.parse(evt.data);
if (parsedResponse.isCIA) { // checking it's a postmessage from us and not an extension
if (parsedResponse.status == "LOGGED_IN") {
userContainer.classList.remove('not-logged-in');
} else if (parsedResponse.status == 'NEED_LOGIN') {
userContainer.classList.add('not-logged-in');
}
} else {
throw new Error('not CIA message');
}
} catch (e) {
console.log('not CIA message');
}
}
}());
};
/**
*******************
* End of header code
* *****************
*/
</script>
The iframe contains a really simple body:
<!DOCTYPE html>
<html>
<head>
<script src="https://mysecureiframe.securedomain.com/loginProvider.js" type="text/javascript" ></script>
</head>
<body>
<p>IFRAME NON VISIBILE</p>
</body>
</html>
And here's the content of loginProvider.js:
(function() {
if (window.addEventListener) {
window.addEventListener("message", handleMessage, false);
} else {
window.attachEvent("onmessage", handleMessage);
}
// to read: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
// Guardare HEADER Content-Security-Policy instead of X FRame Options
function checkStatus(success, failure) {
var http = new XMLHttpRequest();
var url = "https://mysecureiframe.securedomain.com/status"; // AUTH endpoint
http.open("GET", url, true);
http.onreadystatechange = function() { //Call a function when the state changes.
if (http.readyState == 4 && http.status == 200) {
if (http.responseText == "true") {
success();
} else {
failure();
}
}
};
http.send();
}
function doLoginIframe(user, pass) {
var http = new XMLHttpRequest();
var url = "https://mysecureiframe.securedomain.com/login"; // AUTH endpoint
http.open("POST", url, true);
http.onreadystatechange = function() { //Call a function when the state changes.
if (http.readyState == 4 && http.status == 200) {
if (user == 'username' && pass == 'password') {
var payload = getPayload();
payload.status = 'LOGGED_IN';
parent.postMessage(JSON.stringify(payload), "http://targetOrigin");
alert(http.responseText);
}
}
};
http.send();
}
function getPayload() {
return {
isCIA: true
};
}
function handleMessage(evt) {
console.log('Inside iframe, got: ', evt); // TODO Check targetOrigin is from trusted sites
var parsedRequest = JSON.parse(evt.data);
if (parsedRequest.action == "status") {
checkStatus(function() {
var payload = getPayload();
payload.status = 'LOGGED_IN';
parent.postMessage(JSON.stringify(payload), "http://targetOrigin");
},
function () {
var payload = getPayload();
payload.status = 'NEED_LOGIN';
parent.postMessage(JSON.stringify(payload), "http://targetOrigin");
});
} else if (parsedRequest.action == "login") {
doLoginIframe(parsedRequest.username, parsedRequest.password);
}
}
}());
Besides adding the check to see if origin is a trusted site, do you see particular security flows with this strategy?
Edit (rephrasing): the website is loaded within an iframe, but there is 1 link inside the iframe which I would like to take the user out of the iframe when they click it, back into the main window that underlays the iframe.
I've found
top.location.href = 'page.htm';
, but I wouldn't know how to enter it into this 'complex' code.
This is the file I believe it should be in:
{literal}
$(document).ready( function() {
$('#payment_paypal_express_checkout').click(function() {
$('#paypal_payment_form').submit();
return false;
});
$('#paypal_payment_form').live('submit', function() {
var nb = $('#quantity_wanted').val();
var id = $('#idCombination').val();
$('#paypal_payment_form input[name=quantity]').val(nb);
$('#paypal_payment_form input[name=id_p_attr]').val(id);
});
function displayExpressCheckoutShortcut() {
var id_product = $('input[name="id_product"]').val();
var id_product_attribute = $('input[name="id_product_attribute"]').val();
$.ajax({
type: "GET",
url: baseDir+'/modules/paypal/express_checkout/ajax.php',
data: { get_qty: "1", id_product: id_product, id_product_attribute: id_product_attribute },
cache: false,
success: function(result) {
if (result == '1') {
$('#container_express_checkout').slideDown();
} else {
$('#container_express_checkout').slideUp();
}
return true;
}
});
}
$('select[name^="group_"]').change(function () {
displayExpressCheckoutShortcut();
});
$('.color_pick').click(function () {
displayExpressCheckoutShortcut();
});
{/literal}
{if isset($paypal_authorization)}
{literal}
/* 1.5 One page checkout*/
var qty = $('.qty-field.cart_quantity_input').val();
$('.qty-field.cart_quantity_input').after(qty);
$('.qty-field.cart_quantity_input, .cart_total_bar, .cart_quantity_delete, #cart_voucher *').remove();
var br = $('.cart > a').prev();
br.prev().remove();
br.remove();
$('.cart.ui-content > a').remove();
var gift_fieldset = $('#gift_div').prev();
var gift_title = gift_fieldset.prev();
$('#gift_div, #gift_mobile_div').remove();
gift_fieldset.remove();
gift_title.remove();
{/literal}
{/if}
{if isset($paypal_confirmation)}
{literal}
$('#container_express_checkout').hide();
$('#cgv').live('click', function() {
if ($('#cgv:checked').length != 0)
$(location).attr('href', '{/literal}{$paypal_confirmation}{literal}');
});
// old jQuery compatibility
$('#cgv').click(function() {
if ($('#cgv:checked').length != 0)
$(location).attr('href', '{/literal}{$paypal_confirmation}{literal}');
});
{/literal}
{else if isset($paypal_order_opc)}
{literal}
$('#cgv').live('click', function() {
if ($('#cgv:checked').length != 0)
checkOrder();
});
// old jQuery compatibility
$('#cgv').click(function() {
if ($('#cgv:checked').length != 0)
checkOrder();
});
{/literal}
{/if}
{literal}
var modulePath = 'modules/paypal';
var subFolder = '/integral_evolution';
var fullPath = baseDir + modulePath + subFolder;
var confirmTimer = false;
if ($('form[target="hss_iframe"]').length == 0) {
if ($('select[name^="group_"]').length > 0)
displayExpressCheckoutShortcut();
return false;
} else {
checkOrder();
}
function checkOrder() {
confirmTimer = setInterval(getOrdersCount, 1000);
}
{/literal}{if isset($id_cart)}{literal}
function getOrdersCount() {
$.get(
fullPath + '/confirm.php',
{ id_cart: '{/literal}{$id_cart}{literal}' },
function (data) {
if ((typeof(data) != 'undefined') && (data > 0)) {
clearInterval(confirmTimer);
window.location.replace(fullPath + '/submit.php?id_cart={/literal}{$id_cart}{literal}');
$('p.payment_module, p.cart_navigation').hide();
}
}
);
}
{/literal}{/if}{literal}
});
{/literal}
Edit: found some part of the HTML as well, figured it'd be easy to do there, but it doesnt actually seem to work. Perhaps because of the void(0)?
<a href="javascript:void(0)" target="_top" onclick="$('#paypal_payment_form').submit();" id="paypal_process_payment" mod='paypal'}">
Perhaps someone here can help me out. Thanks in advance!
Best,
Dave
This is some JavaScript that will redirect the user out of the iframe to the website if the website is being 'iframed':
<script>if (top !== self) top.location.href = self.location.href;</script>
I do not see a portion of the code for your form, but since you are using submit() you can set the target of the form to _top:
<form target="_top" action="yoururl.php" id="paypal_payment_form">
Then once you use submit, it will break the frames and continue to the new page.
<a href="#" onclick="$('#paypal_payment_form').submit();" id="paypal_process_payment" mod='paypal'>
I add the external script in head
http://www.google.com/jsapi
Body Part:
google.load("gdata", "1.s");
google.setOnLoadCallback(function (){
if(window.location.hash=="") {
if(!checkLogin()){
logMeIn();
} else {
var feedUrl = "https://www.google.com/m8/feeds/contacts/default/full";
query = new google.gdata.contacts.ContactQuery(feedUrl);
query.setMaxResults(5000);
myService = new google.gdata.contacts.ContactsService('exampleCo-exampleApp-1.0');
myService.getContactFeed(query, function(result) {
document.cookie="g314-scope-0=";
window.opener.parseGmailContacts(result.feed.entry);
close();
}, function(e){
alert(e.cause ? e.cause.statusText : e.message);
});
}
}
});
function logMeIn() {
scope = "https://www.google.com/m8/feeds";
var token = google.accounts.user.login(scope);
}
function logMeOut() {
google.accounts.user.logout();
}
function checkLogin(){
scope = "https://www.google.com/m8/feeds/";
var token = google.accounts.user.checkLogin(scope);
return token;
}
after page open it goes to https://accounts.google.com/AuthSubRequestJS?session=1&scope=https%3A%2F%2Fwww.google.com%2Fm8%2Ffeeds&next=http%3A%2F%2Fmaharashtratimes.indiatimes.com%2Fsocial_gmail.cms
and it;shown The page you requested is invalid. Please help.................
In my extension's content script, I request data from background.js like so:
fireOnNewTopic (); // Initial run on cold start or full reload.
window.addEventListener ("hashchange", fireOnNewTopic, false);
function fireOnNewTopic () {
/*-- For the pages we want, location.hash will contain values
like: "#!newtopic/{group title}"
*/
if (location.hash) {
var locHashParts = location.hash.split ('/');
if (locHashParts.length > 1 && locHashParts[0] == '#!newtopic') {
var subjectStr = '';
var bodyStr = '';
switch (locHashParts[1]) {
case 'opencomments-site-discussions':
chrome.extension.sendMessage({name:"domain"},
function(response)
{
subjectStr = response.domain;
});
chrome.extension.sendMessage({name:"url"},
function(response)
{
bodyStr = "URL of last page visited: " + response.url;
});
break;
default:
break;
}
if (subjectStr && bodyStr) {
runPayloadCode (subjectStr, bodyStr);
}
}
}
}
Unfortunately, since sendMessage() runs asynchronously with the callback, at the time the code reaches runPayloadCode(), subjectStr and bodyStr are still null, since the code in background.js hasn't completed. What's the best way to synchronize the code so that subjectStr and bodyStr are filled in by the time runPayloadCode() is called?
To elaborate on what Sudarshan said about combining the two requests into one (sorry, need code so couldn't just comment) here's what you could do...
send
chrome.extension.sendMessage({url: true, domain:true}, function(response) {
console.debug('The url is "'+response.url+'" and the domain is"'+response.domain+'"');
if (repsone.url && response.domain) {
runPayloadCode (subjectStr, "URL of last page visited: " + response.domain);
}
});
or, if you wanted it more like your case way for some reason, maybe this is the sorta thing you'd like...
if(location.hash) {
var locHashParts = location.hash.split('/');
if(locHashParts.length > 1 && locHashParts[0] == '#!newtopic') {
var subjectStr = '';
var bodyStr = '';
var request = {};
switch(locHashParts[1]) {
case 'opencomments-site-discussions':
request = {
url: true,
domain: true
}
break;
default:
break;
}
chrome.extension.sendMessage(request, function(response) {
console.debug('The url is "' + response.url + '" and the domain is"' + response.domain + '"');
if(repsone.url && response.domain) {
runPayloadCode(subjectStr, "URL of last page visited: " + response.domain);
}
});
}
}
}
listen
chrome.extension.onMessage.addListener(
function(request, sender, sendResponse) {
var response = {};
if(request.url) {
response.url = "someURL";
}
if(request.domain) {
response.domain = "someDomain";
}
sendResponse(response);
});
You can try the following code:
case 'opencomments-site-discussions':
chrome.extension.sendMessage({
name: "domain"
},
function (response) {
subjectStr = response.domain;
if(subjectStr){
chrome.extension.sendMessage({
name: "url"
},
function (response) {
bodyStr = "URL of last page visited: " + response.url;
if (bodyStr) {
runPayloadCode(subjectStr, bodyStr);
}
});
}
});
However, can't you merge both message's chrome.extension.sendMessage({name: "url"}) and chrome.extension.sendMessage({name: "domain"}) into single message(Because i see them independent) and eliminate multiple nesting?
public JsonResult UnassToOrder(string location, string article_number)
{
//....
return Json(new {
success = true,
redirect = "ImportXML/Index"
});
}
<script type="text/javascript">
$(document).ready(function() {
$('input:radio').click(function() {
var location = $("input:checked").val();
var article_number = $("input[id=MArticleNumber]").val();
$.post("/SomeController/SomeAction", { location: location, article_number: article_number }, function(data) {
window.location.href = data.redirect;
},"json");
});
});
</script>
I have 3 radio buttons. When click on first one I have redirect to "ImportXML/Index" with this line of code: window.location.href = data.redirect;. When I click on second radio button my URL on browser is "ImportXML/ImportXML/Index" and this is error because correct URL is "ImportXML/Index"
You can absolutize your path like this:
window.location.href = "/" + data.redirect;
I would highly recommend using the UrlHelper class to build your URLs.
return Json(new {
success = true,
redirect = Url.Action( "Index", "ImportXML ")
});