Protecting iFrame - Only allow it to work on one domain - html

I have a Widget that I created and I am embedding it on other websites using an iFrame. What I want to do is make sure no one can view the source and copy the iFrame code and put it on their own website.
I can store the URL that it should be allowed on in the database. I've seen it done before, one site had a long encrypted code and if it didn't match with the domain then it said Access Denied..
Does anyone know how I can do this?
Thanks!

No you can't do this. The best thing you can do is the following:
if (window.top.location.host != "hostname") {
document.body.innerHTML = "Access Denied";
}
Add the above to your JavaScript and then use a JavaSript obfuscator

You cannot prevent people from looking at your HTML, but there are some headers can allow you to specify what sites can embed your iframe. Take a look at the X-Frame-Options header and the frame-ancestors directive of Content-Security-Policy. Browsers that respect it will refuse to load the iframe when embedded into someone else's site.

On the server in the code for the page displayed in the IFRAME, check the value of the Referer header. Unless this header has been blocked for privacy reasons, it contains the URL of the page which hosts the IFRAME.

What you are asking for is pretty much impossible. If you make the source available on the web someone can copy it one way or another. Any javascript tricks can be defeated by using low level tools like wget or curl.
So even if you protect it, you're still going to find that someone could in theory copy the code (as the browser would receive it) and could if so determined put it on their own website.

I faced the same problem, but I return the user on a home page. I spread the decision.
It has to be placed where there is iframe
<script>
$(window).load(function () {
var timetoEnd = '';
var dstHost = 'YOUR-ALLOW-HOST';
var backToUrl = 'BACK-TO-URL';
function checkHost(){
var win = window.frames.YOUR-IFRAME-NAME;
win.postMessage('checkHost', dstHost);
console.log('msg Sended');
clearInterval(timetoEnd);
timetoEnd = setInterval(function () {
window.location.href = backToUrl;
}, 5000);
}
function validHost(event) {
if (event.data == 'checkHostTrue') {
clearInterval(timetoEnd);
console.log('checkHostTrue');
} else {
return;
}
}
window.addEventListener("message", validHost, false);
checkHost();
setInterval(function () {
checkHost();
}, 10000
);
});
</script>
It has to be placed into your src iframe
<script>
function receiveMessage(event)
{
if(event.data=='checkHost'){
event.source.postMessage("checkHostTrue",
event.origin);
} else {
return;
}
}
window.addEventListener("message", receiveMessage, false);
</script>

I know it's kinda old topic but I have code that you just put in <script> tag and it should prevent most of curious people from looking at html files from iFrame:
if(window.top.location.pathname === window.location.pathname){
history.back()
}

Related

If my app is being loaded by iframe - can I detect it?

I didn't find the information about this topic in google. Can I detect if my (Rails) application is being loaded from iframe? If yes, can I obtain the url of the iframe? I'd like to do it by both javascript and on the server if it's not possible, if not - whatever way is easier.
through javascript its very easy.
function isInIframe () {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
}
server side , check http referer header.
$_SERVER['HTTP_REFERER'] but this is not foolproof.
more

How to embed MediaWiki page content into my site?

Our corporate wiki is Mediawiki. I have no problem to put iframe into my site to refer for some article on wiki.
But my own site have a lot of widgets and own style. I don't want to include Mediawiki navigation/search/login widgets, logo image.
Is it possible and how to get Mediawiki page contents without widgets (only article body)?
Yes, it is. You'll probably want to use the action=render url parameter, for example: http://en.wikipedia.org/w/index.php?action=render&title=Main_Page. Note that the stylesheets from the wiki aren't included, so you'll need to copy the relevant rules to your site's css files. See also this.
Thank waldir for answer!
After asking question I perform own research and end with code:
window.onload = function() {
httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState !== 4) {
console.log("Not ready, code: %o", httpRequest.readyState);
return;
}
if (httpRequest.status !== 200) {
console.log("Server error: %o", httpRequest.status);
return;
}
var json = JSON.parse(httpRequest.responseText);
console.log("json: %o", json);
var wiki = json.query.pages["1"].revisions[0]["*"];
console.log("wiki: %o", wiki);
var html = InstaView.convert(wiki);
console.log("html: %o", html);
document.getElementById('area').innerHTML = html;
};
var url = 'https://wiki.evil-company.com/api.php?action=query&prop=revisions&format=json&titles=Main_page&rvprop=timestamp|user|comment|content';
httpRequest.open('GET', url, true);
httpRequest.send(null);
}
Here I use https://github.com/cscott/instaview/blob/master/main.js project which is enhanced http://en.wikipedia.org/wiki/User:Pilaf to transform json output to HTML on browser side.
The reason for this code because our wiki is old or misconfigured and action=render is not available. But I trap into cross-domain scripting issue so I think that iframe with action=render is better solution.
See also How do you grab an article including the links in a usable format?
Another suggestion to use action=parse (http://en.wikipedia.org/w/api.php?action=parse&title=Linux) lead to warning:
You are looking at the HTML representation of the XML format.
HTML is good for debugging, but is unsuitable for application use.
Specify the format parameter to change the output format.
UPDATE
Perfect solution just append query action=render to any valid wiki URL like:
http://en.wikipedia.org/wiki/Linux?action=render

Chrome Extension: Insert a clickable image using a content script

I know hat it is possible, but I am not quite sure how to do it the 'right' way, as to ensure there are no conflicts.
I came across this question: Cannot call functions to content scripts by clicking on image . But it is so convoluted with random comments that it's hard to understand what the corrected way was.
Use case:
Html pages have a div on the page where they expect anyone using the Chrome extension to inject a picture. When users click on he picture, I want to somehow notify an event script. So I know I need to register a listener so the code inserted messages the event script.
Can I get some indication on what code to inject through the content script? I saw that sometimes injecting jquery directly is advised.
I am trying to avoid having the html page to post a message to itself so it can be intercepted. Thanks
With the help of Jquery something like this would capture the image onclick event and allow you to pass a message to a background page in the Chrome Extension:
$("img").click(function(){
var imageSrc = $(this).attr("src");
//Post to a background page in the Chrome Extension
chrome.extension.sendMessage({ cmd: "postImage", data: { imgSrc: imageSrc } }, function (response) {
return response;
});
});
Then in your background.js create a listener for the message:
chrome.extension.onMessage.addListener(
function (request, sender, sendResponse) {
if (request.cmd == "postImage") {
var imageSrc = request.data.imgSrc;
}
});

how to communicate between a options page and background page of chrome extension

I face a problem. Through message passing I transferred DOM data from content script to background page. What i would like to know is how you can establish a communication channel between Options page and background page. The API chrome.extension.getBackgroundPage() is not useful. Nor is traditional message passing through sendRequest and addlistener working . How do i transfer this data from background page to the options page? Could someone provide a tested snippet to explain?
this is what i have been trying .
In my contentscript.js
<script>
var selected_Text ="";
window.addEventListener("dblclick",function(event){
selected_Text = String(window.getSelection());
chrome.extension.sendRequest({greeting: "maprender",name:selected_Text}, function(response) {
alert("reached here")
console.log(response.farewell);
});
//i am to then load options.html on DOM like this
var Div = document.createElement("iframe");
Div.setAttribute('src', chrome.extension.getURL('options.html'));
Div.setAttribute("style","width:130px;height:80px;position:absolute;left:10px;");
Div.setAttribute("id","xyz");
document.body.appendChild(Div);
</script>
I retreive the selected_Text at background.html like this
<script>
var Addr_details={
place:null
};
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
if (request.greeting == "maprender")
{
alert("reached here sendin resp"+request.name);
Addr_details.place = request.name;
sendResponse({farewell: "goodbye"});
}
else
sendResponse({}); // snub them.
});
</script>
Now to access the value of this text at the options page options.html i tried 2 methods
One was to use chrome.extension.getBackgroundPage() like this:
<script>
function init(){
var bkg = chrome.extension.getBackgroundPage();
alert("the selected text is "+bkg.Addr_details.place);
}
</script>
init is onload of options.html .This does not give me the value . infact it just terminates at initialization of chrome.extension.backgroundPage.
Another approach i tried was to create a similar request(like the one already present at contentscript.js) from contentscript.js with a different greeting and add a listener to it at options.html .That doesnt seem to work either at the receiver side(options page) because i get the callback at the contentscript after the request.I am surely doing something wrong , amnt I ?Please help.
It makes sense for the second approach not work. Options.html is not "alive" all of the time, only when the options page is up. Hence, it cannot listen to requests from the content script.
That's exactly what "background" is for.
As for the first approach (using getBackgroundPage()), I never used this method myself, but it seems to bring back only the DOM of the background page, and therefore you cannot access the variables in the background js.
Your best shot should be to send a request from the options page to the background page, asking for this value, e.g.:
Content script:
chrome.extension.sendRequest({greeting: "retrieveAddr"}, function(response) {
// do something with response.addr...
});
Background page:
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
switch (request.greeting) {
case "maprender"):
alert("reached here sendin resp"+request.name);
Addr_details.place = request.name;
sendResponse({farewell: "goodbye"});
break;
case "retrieveAddr":
sendResponse({addr: Addr_details});
default:
sendResponse({}); // snub them.
});
});
Another, easier but hackier solution is to use localStorage to pass info between the options and background pages, as they both share the same one.

Background page to communicate with Content Script

I'm having a bit of trouble getting some final bit of code working to complete my extension.
The short version is that I need my background.html page to notify my content script whenever a different tab is selected. At the moment I have the following:
background.html
chrome.tabs.onSelectionChanged.addListener(function( tab_id , info ) {
// some way to call App.resize();
});
content script js file
var App = {
resize: function() {
// logic
}
}
The longer version is that I'm building a fullscreen extension for chrome that works the same as Firefox and Safari on PC. At the moment, when you enter fullscreen mode you can't really navigate to different other tabs unless you use a shortcut and cycle through all your open tabs. My extension shows all the currently opened tabs and you can switch to them, as well as an address bar so you can go to other websites, etc.
I have everything working as I need it, and it's all working nicely except with pages that redirect to others. E.g. with Google Reader, when you open an article in the background, it goes through google's proxy and then redirects to the actual article. This is the only place where it doesn't work. But if I can call the App.resize() function whenever I switch to a new tab, that will fix my problem. (I hope).
It depends on whether you need to inform content scripts on all pages or just the selected tab. I'll give you solutions for both.
background.html (if you need to inform all tabs)
chrome.tabs.onSelectionChanged.addListener(function() {
chrome.windows.getAll({populate: true}, function(windows) {
var w,t;
for (w=0; w<windows.length; w++) {
for (t=0; t<windows[w].tabs.length; t++) {
chrome.tabs.sendRequest(windows[w].tabs[t].id, "resize");
}
}
});
});
background.html (if you only need to inform the newly-selected tab)
chrome.tabs.onSelectionChanged.addListener(function(tabId) {
chrome.tabs.sendRequest(tabId, "resize");
});
content script
var App = {
resize: function() {
// logic
}
};
chrome.extension.onRequest.addListener(function(request) {
if (request === "resize") {
App.resize();
}
});