What I'm looking for:
I want to test for the 403 disallowed_useragent error (unless there is something else to test for) and when the error is present I can create a way for the user to continue.
Background/The Problem:
I have a Google Scripts signup sheets app with a Google OAuth button to login to the Admin functions.
Everything in the resulting webpage works the way I'd like, if it's accessed from a web browser.
However, this script was made for our church and placed both on a website and within an app builder (Subsplash), and when someone tries to login (from the script from within the app) it's returning a 403 disallowed_useragent error. I don't have much control over the app builder, or the resulting app: Subsplash (https://www.subsplash.com/).
I am reaching out to Subsplash to see if there is something they can do on their end, but in the meantime, or in the even that there isn't anything they can do, I'm looking for a solution that I can do on my end.
After researching the error, and potential fixes, it appears the problem is that Subspash is rendering my webpage in a WebView and, for security reasons, OAuth won't work in a WebView.
Researching the Problem:
I found references to using googlechrome://navigate?url=www.example.com but that didn't do anything from within the WebView on my Android phone.
This was the closest question to what I'm looking for: Google OAuth for websites in embedded browsers
In the answer:
I would like to avoid going down the road of detecting the user-agent web-side and force the user to open the link in Safari.
I don't know that sounds like a pretty decent solution to me. It may feel a like over kill a little but if it works go with it.
So I headed down the path of detecting the user-agent web-side and ran into this article: https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent which basically tells you to avoid it at all costs, and only if necessary, try to detect the missing feature instead.
This makes sense, because for some mobile/browser options, it'll work fine, but not all.
Also, maintaining all availiable browsers/mobile scenarios, does sound like a headache (and I'm programming this in my freetime, not as a job, so less maintenance would be best! Not to mention, at some point, it'll get turned over to someone without a background in programming!)
Not to mention, I don't have access to all different mobiles, etc. And may only find out that something doesn't work when someone with a different device tells me. (One I don't have to test with!)
Back to the solution:
I'm not sure what to look for, but the best case scenario would be to be able to test that clicking on a Google Login button will return the 403 error, and that I can somehow catch that and show something different.
If it is possible to search for a specific feature that is missing from a WebView (before even showing the Google Sign button) that would be acceptable also.
As a last resort, I'm not even sure what else to search for in my quest for an answer. So if you won't have a full answer, but can point me in a direction, that would be super helpful as well.
Some Code
Reminder!! This works for a website rendering!
page.html
<head>
...
<meta name="google-signin-client_id" content="....apps.googleusercontent.com">
...
</head>
<body>
...
<div id="google-signin-button" class="g-signin2" data-onsuccess="onSignIn"></div>
<div id="not-logged-in-message">
<br />Please login to access Admin Functions.
<!-- This anchor tag doesn't do anything -->
<br /><a href='googlechrome://navigate?url=script.google.com/...'>Open outside the app</a>
</div>
...
<?!= HtmlService.createHtmlOutputFromFile('javaScript').getContent(); ?>
<?!= HtmlService.createHtmlOutputFromFile('adminScript').getContent(); ?>
</body>
javaScript.html
...
<!-- Google Login https://developers.google.com/identity/sign-in/web/sign-in -->
<script src="https://apis.google.com/js/platform.js?onload=init" async defer></script>
...
adminScript.html
<script>
...
// https://developers.google.com/identity/sign-in/web/reference
function init ()
{
gapi.load ('auth2', function () {
/* Ready. Make a call to gapi.auth2.init or some other API */
$('#loading-message').val ("").empty ();
});
}
// Trouble Shooting: https://stackoverflow.com/questions/41448014/google-script-oauth2-error-redirect-uri-mismatch
// Make sure redirect faces production script
function onSignIn (googleUser)
{
console.log ("Calling onSignIn");
var google_profile = googleUser.getBasicProfile ();
console.log ('ID: ' + google_profile.getId ()); // Do not send to your backend! Use an ID token instead.
console.log ('Name: ' + google_profile.getName ());
console.log ('Image URL: ' + google_profile.getImageUrl ());
console.log ('Email: ' + google_profile.getEmail ()); // This is null if the 'email' scope is not present.
displayAdminInfoCall (google_profile);
fillAdminNavs (google_profile);
}
...
</script>
Related
To begin with: I'm a total newb. These functions are the first I have ever written. I use Wordpress (and the most important plugin used on the site is called BuddyPress). What I essentially want the script to make is delete something from my database and then reload the page one time when pressing a certain link. Nothing more.
I have an issue with Internet Explorer where my page gets stuck in an infinite loop. This problem doesn't occur on Chrome at all. I have a PHP containing the following:
<li><a id="edit" href="#" onclick="runUpdateForm();">Uppdatera profil</a></li>
When pressing the link the following script is run:
<!--Javascript runUpdateForm-->
<script type="text/javascript">
function runUpdateForm() {
$.post ( ajaxurl, {
action:'resetUser',
user_id:jQuery("#user_id").val()
});
window.location.reload();
}
</script>
<!--End Javascript runUpdateForm-->
In my functions-file the following is found:
function resetUser() {
$user_id=get_current_user_id();
global $wpdb;
$wpdb->query("DELETE FROM wp_profile_updates WHERE user_id='".$user_id."'");
die(); // close the connection
}
add_action('wp_ajax_resetUser', 'resetUser'); // add action for logged users
add_action( 'wp_ajax_nopriv_resetUser', 'resetUser' ); // add action for unlogged users
After Googling a bit I found the following piece of code which I put right above location.reload():
history.pushState("", document.title, window.location.pathname + window.location.search);
This made the infinite-loop go away but still it reloads one time to much in Internet Explorer, in comparision to Chrome and what I actually want to happen.
Sorry for my poor English. I'm a Swede :-)
I appreciate the help. I need someone with knowledge to tell me if they see anything right away which looks crazy and should be changed. My problem maybe is related to other stuff happening on my site.
Regards.
Your code does: start the ajax, then reload. as ajax is async, it will never post to the server, its interrupted by the reload. So you need to await the ajax:
<script type="text/javascript">
function runUpdateForm() {
$.post ( ajaxurl, {
action:'resetUser',
user_id:jQuery("#user_id").val()
},function(){
// executed on success
window.location.reload();
});
}
</script>
also, im wondering where ajaxurl is defined...
I am looking to remove a certain amount of a page URL without reloading.
I have looked on StackOverflow for the answer and there are a few close answers but not what I'm looking for really.
I do not want to use the hash function and if possible, avoid using the HTML5 version because HTML5 isn't the ratified standard yet and for the website this will be used on, I wouldn't be at all surprised is some of the clients used IE6.
I would prefer if it wasn't an extremely complicated solution with 400 lines of code (at that cost I'd rather just reload the page to be honest).
I forgot to mention this, critical, part of the question
The user is directed from a different page with this string via PHP. So for example:
user submits a form with errors. Let's say the form is on /myform.php
The user gets headed to /index.php?string
carry on as normal
What I have:
This is an example URL that I wish to edit without reloading:
http://www.mywebsite.com/index.php?string
Wait! ?string has a use on /index.php
index.php will use $_GET['string']; and display a message to the user
I have used JQuery to remove the message after 4 seconds like this:
<div id="pagemsg"><?php echo $string; ?></div>
<script language="javascript">
setTimeout( "$('#pagemsg').fadeOut();", 4000);
</script>
This works all well and the message disappears after 4 seconds. However I'm left with this URL:
http://www.mywebsite.com/index.php?string
I don't want this string anymore because ?string has done its job!
I would like to remove the ?string without reloading the while page.
Is there any solution that can help me?
Also,
I don't mind if I have to use the HTML5 push function but is there a fall-back solution for the browsers that don;t support HTML5?
Why did I put WITH A TWIST in the title? Well, my requirements are different to the questions I have seen so far. Correct me if I'm wrong and I will change it.
Thanks for your help in advance!
The simple answer is no. That's why they added pushState.
However, it looks like you are trying to accomplish a fairly common scenario known as flash messaging. This is often done using the user's session to store a message to show on the next request (and then delete it).
Example:
function doImportStuff() {
// ...
$_SESSION['message'] = 'important stuff was done';
// ...
}
function showBoringPage() {
// ...
if (isset($_SESSION['message']) {
echo '<b>' . $_SESSION['message'] . '</b>';
unset($_SESSION['message']);
}
// ...
}
The only method I know of is this:
if (history && history.pushState){
history.pushState(null, null, '/new/url');
}
But this is HTML5 and won't work in your case..
For old browsers - and you: History.js
I am currently trying to setup a Client Side Experiment without Redirects as opposed to the default Content Experiment A/B testing. All I want to do is for half my visitors disable one of two existing stylesheets on a page.
To me it doesn't make sense to do this the default A/B way because then I would have to setup a second page with the stylesheet disabled for every page on my site.
There is also Running a Server-side Experiment but to me that is too heavy handed for something I think should be somewhat simple.
I have the js all setup, I just need to be able to tell the page that when there is a given variation disable the stylesheet or don't render the stylesheet before the DOM loads.
One thing I considered is, given a certain variation, redirect to the same page but append a url query parameter like &stylesheet_disabled=true then I would simply not render the stylesheet on the server side but when I briefly looked at that I ran into a redirect loop but perhaps someone has a better way to write the js.
Any help greatly appreciated.
You could do something like this:
<head>
...
<script>
if (cxApi.chooseVariation() != 1) { // not in the experiment
document.write('<link href="... />'); // add the stylesheet
}
</script>
...
Only use document.write while the page is still being loaded.
This is all client-side, so no need for redirects and extra server work.
Here is how I did it:
<head>
<script src="//www.google-analytics.com/cx/api.js?experiment=EXPERIMENT_ID"></script>
<script>
// Ask Google Analytics which variation to show the visitor.
var chosenVariation = cxApi.chooseVariation();
function redirectVariation($variation) {
var url = window.location.href;
if ($variation === 1) {
var queryString = document.location.search;
if (queryString.indexOf("stylesheet_disabled=true") == -1) {
if (Boolean(queryString)) {
url += "&stylesheet_disabled=true";
} else {
url += "?stylesheet_disabled=true";
}
window.location.href = url;
}
}
}
redirectVariation(chosenVariation);
</script>
This is only setup for one different variation but could easily be modified for more. Then you just have your application on the server side detect the presence of the querystring parameter and execute whatever logic you like, in my case not displaying a stylesheet.
Theoretically this could be used to do any kind of server side logic with GA Content Experiment Client Side Redirects. Hopefully this helps someone else.
This is my code I came up with (w/ lots of outside help; I'm not fluent in JS):
setTimeout(function() {
var logout = document.querySelector('a.yucs-signout'),
link = "http://login.yahoo.com/config/login?logout=1&.src=cdgm&.intl=us&.direct=2&.done=http://ma
il.yahoo.com";
logout.setAttribute ('onclick', 'location.href =
\"' + link + '\"');
logout.setAttribute ('href', link);
}, 17000)
I'm trying to change the sign-out URL at Yahoo Mail, when clicking the "Sign Out" dropdown menu item, so that you are redirected back to the Yahoo Mail login page -- not the yahoo.com "main page". This is to make it easier to login with another account.
We couldn't get it to work. Even added a timeout to the code in case my js was running too soon. Still no go.
I was told "The class="yucs-submenu-toggle" on the <a id="yucs-menu_link_profile"> with no CSS on :hover means javascript is being used."
Logout control screenshot:
You have to hover over that section to get the menu to dropdown & see Sign Out.
I also made sure my "Included page" was https: https://*.mail.yahoo.*/*
I'm trying to use this with Greasemonkey, why isn't it working?
Edit: I was thinking this other answer might have something useful, like the jQuery stuff in it?
If the code in the question is copied verbatim, then it has syntax errors from improperly made, multi-line strings.
Don't set onclick from a userscript. Ever! In this case, no form of click event handling is necessary anyway, and may block the logout operation of the page.
Other than that, that code works for me -- at least on Yahoo, UK, mail.
Some more minor points:
You don't need a setTimeout in this case.
Don't brute-force the link like that; it may not always work. Use regex to surgically change just the done variable part.
Here's a complete working script:
// ==UserScript==
// #name _Fix Yahoo mail logout
// #include http://mail.yahoo.com/*
// #include http://*.mail.yahoo.com/*
// #include https://mail.yahoo.com/*
// #include https://*.mail.yahoo.com/*
// ==/UserScript==
//-- Only run in the top page, not the various iframes.
if (window.self === window.top) {
var logout = document.querySelector ('a.yucs-signout');
if (logout) {
var link = logout.href.replace (
/&\.done=[^&#]+(&?)/, "&.done=http://mail.yahoo.com$1"
);
logout.href = link;
}
else
console.error ("From GM script: Node 'a.yucs-signout' not found.");
}
i have this chatbox, and when users login i want it to send a message like this:
Admin: User is online
I really want to use a javascript code for this, because i can work with it quite good. I already have some example, but the problem here is that it does not do something until it is called to do it's function. THATS what i want to achieve, just that when the page is opened up, it does that function one time.
function onLine(message)
{
document.writeform.bericht.value+=message;
document.writeform.bericht.focus();
write1();
}
explanation: onLine is the function and (message) tells what it should say. For example:
...
onclick="onLine('User is online');"
...
the function write1() sends it.
HELP?!
Do you want to run that function once when the page is loaded? If so, you have many possible ways to do it. A couple of simple ones:
<body onload="onLine('User is online')">
This will call the function when all the page components are loaded. You could also add this to the end of the page:
<script type="text/javascript">
onLine('User is online');
</script>
There are also javascript libraries like jQuery and prototype, which you should have a look at if you haven't yet.