Redirect all referral links with Javascript - javascript

I am trying to make a secure download page. In an effort to deter that person from simply copying the URL and sharing it with the world, I'd like to use Javascript to redirect any referral that comes from outside of my domain.
Here's what I'm trying, but with no luck.
var referrer = /^(https?:\/\/[^\/]*)/.exec(document.referrer)
if (referrer && referrer[-1] == "http://mydomain.com") {
ducument.location = "http://mydomain.com/accessdenied"
}

You should do it from your server side, some one will disable javascript and get what he want :D

You can only do this on the server. Not sure what server side your using but no matter which one you can get access to the server properties $_SERVER['HTTP_REFERER'];

typo,and "http" may not be used to test
var referrer = /^https?:\/\/([^\/]*)/.exec(document.referrer)
if (referrer && referrer[1] == "mydomain.com") {
document.location = "http://mydomain.com/accessdenied"
}

Related

How to disable direct access to Iframe

Let's say normally my users access our web page via https://www.mycompany.com/go/mybusinessname
Inside this web page, we have a iframe which actually comes from https://www.mycompany.com/myapp
Everything is working fine, except that if for some reason, the users come to know about this url https://www.mycompany.com/myapp. They can start accessing it directly by typing into the address bar.
This is what I want to prevent them from doing. Is there any best practice to achieve this?
==== Update to provide more background ====
The parent page which is https://www.mycompany.com is the company's page and it's maintained by some other team. So they have all the generic header and footer, etc. so each application is rendered as an iframe inside it. (This also means we cannot change the parent page's code)
If users access https://www.mycompany.com/myapp directly, they won't be able to see the header and footer. Yes, it's not a big deal, but I just want to maintain the consistency.
Another of my concern is that, in our dev environment (aka when running the page locally) we don't have the parent-iframe thing. We access our page directly from http://localhost:port. Hence I want to find a solution that can allow us access it normally when running locally as well.
If such solution simple does not exist, please let me know as well :)
On your iframe's source, you can check the parent's window by using window.top.location and see if it's set to 'https://www.mycompany.com/go/mybusinessname'. If not, redirect the page.
var myUrl = 'https://www.mycompany.com/go/mybusinessname';
if(window.top.location.href !== myUrl) {
window.top.location.href = myUrl;
}
I realized we already had a function to determine whether the page in running under https://www.mycompany.com. So now I only need to do the below to perform the redirecting when our page is not iframe
var expectedPathname = "/go/mybusinessname";
var getLocation = function (href) {
var l = document.createElement("a");
l.href = href;
return l;
};
if (window == window.top) { // if not iframe
var link = getLocation(window.top.location.href);
if (link.pathname !== expectedPathname) {
link.pathname = expectedPathname;
window.top.location.replace(link.href);
}
}
You can use HTTP referer header on server-side. If the page is opened in IFRAME - the referer contains parent page address. Otherwise, it is empty or contains different page.

Forcing Javascript Redirection

I am trying to implement what seems to be very simple JavaScript redirection, via the following rudimentary command:
window.location.href = "http://www.somesite.com";
So far so good, it works. I also can do it via the following method:
location.replace("http://www.somesite.com");
No problem here, it works again! The problem comes when I loose the protocol out of the string:
window.location.href = "www.somesite.com";
OR:
location.replace("www.somesite.com");
It just appends the new location to the current url:
www.currentsite.com/www.somesite.com
Of cause, that's not what I want. Is there any way to force the redirect?
One way is to use protocol-relative url like this:
window.location = "//www.somesite.com";
Or
window.location = "//somesite.com";
This way, it would redirect and browser itself will take care of figuring out protocol part eg http or https
Working Example
The protocol is required.
How else would the browser know whether
location.replace("mysite.pl");
was going to a Polish website or a Perl script on the current website?
You could do something like this to add http:// to the URL if it's not already there... although I can't think of a reason for not just including it yourself. Why complicate things?
​function redirect(url) {
if(url.substr(4) != "http")
url = "http://" + url;
window.location.href = url;
}
redirect("www.google.com")
​

google tts with paid account

You now have to pay to use the google translate api. I'm happy to pay for the service but I can't find a way to use the tts. This is what I'm doing
var GoogleTranslate = function(){
var key = "myapikey"
this.speak = function(words) {
var url = "http://translate.google.com/translate_tts?tl=es&q=" + escape(words) + "&key=" + key
new Audio(url).play();
}
}
but when I do new GoogleTranslate().speak("hola")
The requests to http://translate.google.com/translate_tts never return a response. How do I get this working?
I haven't tried your code yet, so I'm not sure if you should be waiting for the sound to load before you can play it (most likely), but I've written an article about this service recently. The part that matters here is the following:
...if your browser forwards a Referer header with any value other than an empty string (meaning it tells the service which page you clicked the link on) then [Google] will return a 404 (Not Found) http error...
Read the entire article here: Embedding text-to-speech into HTML5 games
So in fact, the service is still there, you just need to hide your referer header. One way to do that is through creating a small gateway script. There's the source for one right in the article.

Re-Direct with document.url.match

My goal is to redirect my website to (/2012/index.php)
ONLY IF the user goes to ( http://www.neonblackmag.com )
ELSE IF
the user goes to ( http://neonblackmag.com.s73231.gridserver.com ) they will not be re-directed... ( this way i can still work on my website and view it from this url ( the temp url )
I have tried the following script and variations, i have been unsuccessful in getting this to work thus far....
<script language="javascript">
if (document.URL.match("http://www.neonblackmag.com/")); {
location.replace("http://www.neonblackmag.com/2012"); }
</script>
This should work:
<script type="text/javascript">
if(location.href.match(/www.neonblackmag.com/)){
location.replace("http://www.neonblackmag.com/2012");
}
</script>
You should use regular expression as an argument of match (if you're not using https you can drop match for http://...
In your solution the semicolon after if should be removed - and I think that's it, mine is using location.href instead of document.URL.
You can also match subfolders using location.href.match(/www.neonblackmag.com\/subfolder/) etc
Cheers
G.
document.url doesn't appear to be settable, afaict. You probably want window.location
<script type="text/javascript">
if (window.location.hostname === "www.neonblackmag.com") {
window.location.pathname = '/2012';
}
</script>
(Don't use language="javascript". It's deprecated.)
Anyone at any time can disable JavaScript and continue viewing your site. There are better ways to do this, mostly on the server side.
To directly answer your questions, this code will do what you want. Here's a fiddle for it.
var the_url = window.location.href;
document.write(the_url);
// This is our pretend URL
// Remove this next line in production
var the_url = 'http://www.neonblackmag.com/';
if (the_url.indexOf('http://www.neonblackmag.com/') !== -1)
window.location.href = 'http://www.neonblackmag.com/2012/index.php';
else
alert('Welcome');
As I said, this can be easily bypassed. It'd be enough to stop a person who can check email and do basic Google searches.
On the server side is where you really have power. In your PHP code you can limit requests to only coming from your IP, or only any other variable factor, and no one can get in. If you don't like the request, send them somewhere else instead of giving them the page.
header('Location: /2012/index.php'); // PHP code for a redirect
There are plenty of other ways to do it, but this is one of the simpler. Others include, redirecting the entire domain, or creating a test sub domain and only allow requests to that.

Setting cross-domain cookies in Safari

I have to call domain A.com (which sets the cookies with http) from domain B.com.
All I do on domain B.com is (javascript):
var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.src = "A.com/setCookie?cache=1231213123";
head.appendChild(script);
This sets the cookie on A.com on every browser I've tested, except Safari.
Amazingly this works in IE6, even without the P3P headers.
Is there any way to make this work in Safari?
From the Safari Developer FAQ:
Safari ships with a conservative cookie policy which limits cookie writes to only the pages chosen ("navigated to") by the user. This default conservative policy may confuse frame based sites that attempt to write cookies and fail.
I have found no way to get around this.
If it's worth anything, Chrome doesn't set the cookies either if you use the <script> appending method, but if you have a hidden <img> with the same source, Chrome works in addition to the rest of the browsers (except, again, Safari)
Here is a solution which works:
http://anantgarg.com/2010/02/18/cross-domain-cookies-in-safari/
This might not work for everyone, but I came across this issue because I was serving a React App from a different host than the API, and the solution that ultimately worked was to use DNS:
Our client was being served from www.company-name.com and our API was on company-name.herokuapp.com. By making a CNAME record api.company-name.com --> company-name.herokuapp.com, and having our client use that subdomain for API calls, Safari stopped considering it a "third-party" cookie.
The upside is that there's very little code involved, and it's all using well-established stuff... The downside is that you need some control/ownership over the API host if you're going to use https - they need a certificate that's valid for the client domain, or users will get a certificate warning - so this wouldn't work (at least not for something end-user-facing) if the API in question isn't yours or a partner's.
Working method 2014-2016:
You have to do window.open to the domain / assign a cookie / close the popup, the domain is now safelisted.
Original post # PHP multiple cookies not working on iPad / iPhone browser
There is a bit of an evil trick assuming they have flash installed.
I'm not sure if it still works or not, but Flash'es "Local Shared Objects" aka Flash Cookies could help you circumnavigate Safari's same-domain policies.
Local Shared Object Tutorial
However, it may be complicated to implement, to say the least.
Wiki Article on LSO's
Additonally, LSO's are comming into the light as being a security nightmare:
Electronic Privacy Information Centre on LSO's
Flash Cookies: The Silent Privacy Killer
So think carefully before using them.
A post to a hidden <iframe> can allow you to by-pass this restriction in Safari -- http://gist.github.com/586182:
<?php
header('P3P: CP=HONK');
setcookie('test_cookie', '1', 0, '/');
?>
<div id="test_cookie" style="position: absolute; top: -10000px"></div>
<script>
window.setTimeout(function() {
if (document.cookie.indexOf('test_cookie=1') < 0) {
var
name = 'test_cookie',
div = document.getElementById(name),
iframe = document.createElement('iframe'),
form = document.createElement('form');
iframe.name = name;
iframe.src = 'javascript:false';
div.appendChild(iframe);
form.action = location.toString();
form.method = 'POST';
form.target = name;
div.appendChild(form);
form.submit();
}
}, 10);
</script>
There is a proper workaround for this working in 2015. Let's say there is website y.com which includes iframe with site x.com. The x.com iframe wants to store a cookie. That is not permitted by Safari policy, however, y.com is able to store it. So y.com must listen to messages from x.com and then store the cookie itself.
var _cookieEvMth = window.addEventListener ? "addEventListener" : "attachEvent";
var _cookieEvAction = window[_cookieEvMth];
var _cookieEv = _cookieEvMth == "attachEvent" ? "onmessage" : "message";
_cookieEvAction(_cookieEv, function(evt){
if(evt.data.indexOf('cookieset')!=-1){
var datack = evt.data.split('|');
YOUR_CUSTOM_COOKIE_SAVE_METHOD(datack[1],datack[2],datack[3]);
}
},false);
When x.com needs to store the cookie, it must post a message to y.com:
window.parent.postMessage('cookieset|'+ckName+'|'+ckVal+'|'+days,'*');
Also you can work your way to post message to the iframe if you want to read the cookie. Or you can include it as parameter in x.com iframe url using javascript:
iframe.setAttribute('url','x.com/?cookieval='+YOUR_COOKIE_GET_METHOD('cookiename'));
A workaround we just came up with at my job was to set the cookie via a window.open() - it may not be optimal for you (as you'll have an ugly ass popup window open), but it worked well for us. We had to have a popup window open anyway for OAuth authentication.
So the jist of what we did was:
User clicks a link from B.com
Popup window opens to A.com/setCookie
A.com sets its cookie, and then redirects to B.com in the proper place
Again, not valid in all solutions, but it worked in ours. Hope this helps.
I know this question is rather old, but this helped me to solve cookies problem:
var cookieForm = document.createElement("form");
cookieForm.action = "A.com/setCookie?cache=1231213123";
cookieForm.method = "post";
document.body.appendChild(cookieForm);
cookieForm.submit();
The idea to make a form post on a page that sets your cookies.
*EDIT*
This workaround has been reported closed in WebKit.
Luca,
Ok, so this answer is two years old, but... you can set a cookie from an iframe if you post a form to a hidden iframe. You can do this by creating a form:
<form id="myiframe" action="http://yourdomain.com" method="POST" target="iframe_target">
Then in Javascript, get a reference to the form and call submit:
document.getElementsByTagName('form')[0].submit();
You can listen to the iframe's onload, or you can have your iframe action page issue some javascript that signals the load. I have tested this in Safari and Chrome, and it works.
Cheers.
Perhaps pragmatically create and click a link with an href="A.com/setCookie?cache=1231213123" and a target attribute pointing to a hidden iframe. That may bypass Safari's policy of user navigation for setting cookies (I don't have Safari handy to test.)
I did some extensive investigation around this when I was trying to deploy a site that used Windows Live ID, which depended on the ability to be able to set 3rd party cookies in order to log out. It just... didn't work. Nothing we could do would get it to work. The Live ID team also did extensive investigation and their answer was "can't make it work".
Note this line:
script.src = "A.com/setCookie?cache=1231213123";
I could not get this working until I added the http, i.e.
script.src = "http://A.com/setCookie?cache=1231213123";
I found a simple solution. You just need for first time setting cookie to check if request come from the same origin or not, if not as usual you need to return into iframe a script that will repeat this request, already having permission to assign cookie. After that you can do other request directly through iframe accessing this cookie. This helped me in my tracking system. Try, this works well.
Its worth noting that this restriction in Safari doesn't apply across subdomains. So if you directly visit sitea.com, then you can set cookies from subdomain.sitea.com without direct user interaction (iframe/JavaScript).
This was relevant for my case when developing an API. If you're visitors are arriving at mysite.com, and then you want some JavaScript to interact with your API, then if the API is hosted at api.mysite.com, then it will work on Safari.
Place this JavaScript on the page making cross-domain requests, http://example1.com/index.html:
<script>
var gup = function(name, url) {
if(!url) url = location.href;
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+name+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec( url );
return results == null ? null : results[1];
}
var isSafari = navigator.vendor && navigator.vendor.indexOf('Apple') > -1 && navigator.userAgent && !navigator.userAgent.match('CriOS');
var n = gup("activated");
if(isSafari && n == null) {
//browser is Safari and cookies have not yet been activated
var current_url = location.protocol + '//' + location.host + location.pathname;
var query_string = '?callback=' + encodeURIComponent(current_url + '?activated=1');
var new_url = 'http://example2.com/activate.php' + query_string;
window.location.href = new_url;
}
//the rest of your code goes here, and you can now set cross-domain cookies on Safari
</script>
Then create a file on the other server, which needs to set cookies, http://example2.com/activate.php:
<?php
if(isset($_GET['callback'])) {
header('Location: '.$_GET['callback']);
exit();
} else {
//in case callback param is not set, simply go back to previous page
echo "<script>";
echo "window.history.back();";
echo "</script>";
exit();
}
?>
Here's how this works:
When http://example1.com/index.html is first visited, a check is made to see whether the browser is Safari and whether a GET parameter of the name "activated" does not exist. If both conditions are met (which will happen on the first visit for a Safari browser), then the browser is redirected to http://example2.com/activate.php with a GET parameter, "callback", containing the calling URL appended with an "activated" parameter.
http://example2.com/activate.php simply redirects back to the URL contained in the GET parameter, "callback".
When http://example1.index.html is now hit this second time after being redirected-to, the GET parameter, "activated" will now be set, so the conditional from step 1 will not execute, thus allowing the script to continue execution.
This fulfills Safari's requirement of having the browser visit the 3rd party domain at least once in order to start setting cookies.
Try something like:
var w = window.open("A.com/setCookie?cache=1231213123");
w.close();
It may bypass safari's security policy.
It isn't the missing type-attribute thats annoying you ?-)
<script type="text/javascript">
var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.setAttribute("type","text/javascript");
script.src = "A.com/setCookie?cache=1231213123";
head.appendChild(script);
</script>

Categories