Google Auth OAuth 2.0 SvelteKit wierd behavior - javascript

I am using Google Auth OAuth 2.0 One Tap Sign and Sveltekit,
and I got some really weird behavior,
I followed this doc https://developers.google.com/identity/gsi/web/guides/overview with javascript
onMount(async () => {
const handleCredentialResponse = async (response) => {
console.log('Encoded JWT ID token: ' + response.credential);
};
google.accounts.id.initialize({
client_id: clientId,
callback: handleCredentialResponse,
});
google.accounts.id.renderButton(
document.getElementById('buttonDiv'),
{ theme: 'outline', size: 'large' } // customization attributes
);
google.accounts.id.prompt();
});
the code from the doc.
Sometimes it works everything goes well,
Sometimes I got
Uncaught (in promise) ReferenceError: google is not defined
And some mobile / mobile browsers I get
[GSI_LOGGER]: The given origin is not allowed for the given client ID.
but works on laptop
Hope someone can understand and help.
Do we have any way to check logs for investigation?

I got your code to successfully run without modification: https://google-signin-kit.vercel.app/ (This app is in "dev" mode so signin may only succeed with my Google account. If you clone my repo and set your Google client id, signin will work for you.)
I would check how my code is different from your code outside onMount(). For example, how did you include the Google javascript? I describe one major change below.
You also need to check your Google app settings. [GSI_LOGGER]: The given origin is not allowed... is fixed by adding the HTTPS app domain to your Google app "Authorized JavaScript origins." Non-HTTPS domains are not allowed. For example, these domains would not work:
https://google-signin-kit-leftium.vercel.app/ (Not added as Authorized JavaScript origin)
http://google-signin-kit.vercel.app/ (Not HTTPS, if Vercel did not automatically redirect to HTTPS)
Of course, raw IP addresses will not work, either.
localhost is a special exception, but not easy (impossible?) to access from mobile.
ReferenceError: google is not defined (sometimes) happens because onMount() runs before the Google script is loaded.
To get a consistent reproduction, USB debug/inspect Android Chrome and set "disable caching" and throttling to "Slow 3G." (I could not reproduce on desktop Chrome).
Fixed by removing defer async when including Google's script: <script src="https://accounts.google.com/gsi/client"></script>
It should also be possible to call a function after the script is loaded, but I got inconsistent results in SvelteKit. For some reason Kit doesn't always call the load function. Possibly a bug?
Ideally, the Google script should be imported, but I couldn't find a version of the Google script that was built for importing. You may be able to construct a library that you can import? Importing would compile the Google script code into your app, tree-shaking the unused portions. Thus saving a network request and bandwidth.
Another workaround is to have your onMount function check for the google variable. If google is still undefined, call your function again after a certain timeout.

Related

Retrieving console errors to html

My question is different from the other posts similar to this.
AutoCAD offers developers a means of displaying a URL page inside the application. I created an intranet site for my company with the hopes that users can explore via desktop browser or their AutoCAD application.
The problem is that the browser AutoCAD uses is Chrome version 33 (currently its at 84) - there is no way to update or change the browser either.
I have no way to "inspect" or debug the site inside AutoCAD - and I've come to find out there are many difference in v84 and v33. I'm trying to diagnose errors right now but again, I have no way of accessing the console logs inside the AutoCAD Browser.
Is there a way for me to "alert" any errors that the console is trying to give me? (ie: the page can't find a script reference, there is an unexpected '.', etc...)
NOTE - my site runs great on the most updated Chrome browser (v84 on desktop browser), but some little things are not working right in v33 (in AutoCAD Browser).
If you control the website you can attach a listener on the window to listen for any unhandled exceptions. Add this before all other scripts to make sure everything is captured.
window.on('error', (e) => {
// if error is intresting, do work.
alert(e.message);
});
The handler accepts an ErrorEvent object.
NOTE - This will not capture errors that are triggered in scripts across domain. For example if you are loading google maps, and an error is triggered within that script, you will typically get a 'Script error.' and no other info. This has to do with cross origin policies. You can read more here.
If you need to specifically to capture data sent to console.error you can simply proxy the function. This may not capture anything except for code that explicitly calls console.error and is not recommended.
const error = console.error;
console.error = (...args) => {
// alert(...);
error.apply(console, args);
}

Recaptcha v3 initialization interrupted

Recaptcha v3 initialization is not completing when using the production site.
The logo is no longer appearing and if I try to submit the form I'm getting this error : "Uncaught Error: Invalid site key or not loaded in api.js"
It's working when I'm using it on localhost from my PC
The only difference between the dev and the prod are the keys.
Any idea to why it's not loading properly ?
Changed the keys.
Tried on other web browsers.
There's 2 main ways I believe this is caused:
Your domain name should just be the domain. apple.com, not https://apple.com
Make sure you are including the sitekey in the render param when you add the script tag:
<script src="https://www.google.com/recaptcha/api.js?render=<v3_site_key>"></script>
I've gotten the error when I forgot to provide the site key here (originally thought I only had to pass it in as the first argument to grecaptcha.execute)

Google Sign-In API Hang with uncaught error Failed to get parent origin from URL hash

I'm using Google Sign-In JavaScript client for months without problem.
But recently when user tapping on sign in button from webapp that added to homescreen, the signin pop-up just hang without showing any content.
When debugged via remote debugging, an error is displayed in console pane:
Uncaught Failed to get parent origin from URL hash!
originated from 4188232449-v2-idpiframe.js:136 (javascript loaded internally by google library).
I'm sure it's not programming/config error since the same webapp was previously working for months without problem, and I haven't modified any code.
I've tried google search for this particular problem and browse Google documentation for any recent changes in Google Sign-In API without any luck.
Is it bug from Google API Javascript client library, glitch from recent Chrome browser update on Android, or there is some changes in API usage that I doesn't yet aware?
Library used is https://apis.google.com/js/platform.js
This is init param for gapi.auth2.init():
{
client_id: GAPI_CID, // defined as constant
cookiepolicy: 'single_host_origin',
prompt: 'select_account',
ux_mode: 'popup',
fetch_basic_profile: true
}
Any insight will be much appreciated. Thank you.
P.S.: This problem is different with Uncaught Failed to get parent origin from URL hash since on that case the problem is caused by misconfiguration of required credential in Google API console.
If you never had succedded in integrating sign-in flow with your app, perhaps answer from that post can help you.
Otherwise, if you have had successfully integrated sign-in flow for some time but recently problem suddenly/erratically appears with symptom of blank screen on popped-up window, than you have same problem with me.
I can confirm we are experiencing the same problems at my company since recently. It seems a bit erratic, not 100% of the time. But for some users, some time, they are met with an empty sign-in popup with the url pointing to "https://accounts.google.com/o/oauth2/iframe" but nothing happens.
Not a complete answer yet, but this may be a reasonable workaround for some. I updated the ux_mode to use redirect and it is partially working now.
auth2 = gapi.auth2.init({
client_id: '1234.apps.googleusercontent.com',
scope: 'profile email',
ux_mode: 'redirect',
redirect_uri: 'https://blahblah.io/oauth2callback'
})
NOTE: it seems redirect_uri is required, contrary to Google's docs. This isn't a perfect drop-in replacement, but it solves the "URL hash!" error
This blog post and the Git Repo in it could also be helpful for anyone attempting to use redirect
My electron app started to fail today for the same reason. Been debugging quite a lot and I think found the reason, but don't know how to solve it, why it happened, or if it is electron or google's fault.
In my electron app, I have 2 webviews, one for the main content and another one for google popup dialogs.
So when google needs to open the authentication, it generates this IFRAME:
<iframe id="ssIFrame_google"
sandbox="allow-scripts allow-same-origin" aria-hidden="true"
src="https://accounts.google.com/o/oauth2/iframe#origin=https%3A%2F%2Fxxxx.com&rpcToken=dxxd318480305.4777704"
style="... display: none;"></iframe>
Mind that the URL has HASH parameters: your origin and the token.
However, when on the electron side I capture the new-window event in order to open the URL myself in another webview, the event I receive LACKS the hash parameters:
event {
type : "new-window",
url:"https://accounts.google.com/o/oauth2/iframe",
.
.
}
So what google's iframe is complaining about (I debugged it) is exactly that it can't find the origin and rpctoken parameters that should be in the hash parameters.
For a reason I don't understand (I haven't updated electron) the new-window event does not receive the full url anymore.
Using #howMuchCheeseIsTooMuchCheese answer below I have changed the flow to use the redirect callback, then capture that callback myself and restart the application. It is not ideal, but at least I can login into my applications.

Geolocation API doesn't work on mobile

I'm writing my web application on React/Redux. And I need to get user location with a help of Geolocation API. On desktop browsers everything works fine, but on mobile phones (checked out on Xiaomi Redmi Note 3 and iPhone 5s) it throws error code 1 - permission denied. And it doesn't requests any permissions to get the location.
Here's a test sample which I ran on my site:
componentDidMount() {
if (window.navigator.geolocation) {
window.navigator.geolocation.getCurrentPosition(position => {
alert(position.coords.latitude + ' ' + position.coords.longitude);
}, err => {
alert('ERROR: ' + err.code);
});
} else {
alert('Geolocation API is not supported!');
}
}
What's the solution of this problem?
Got the same Problem... Solved:
Check your phone permissions for sharing your location.
On iPhone:
Settings -> Location Services -> [your Browser]
https://support.apple.com/en-ca/HT203033
Added:
Chrome requires https for geolocation usage:
https://developers.google.com/web/updates/2016/04/geolocation-on-secure-contexts-only
I've got the solution. I'm using the Web Application Manifest and it needed to set the permission to use Geolocation API.
We just need to set an "required_features" option at manifest.webapp file:
{
"required_features": ["geolocation"]
}
Hope it will be useful for somebody ;)
As of the Year 2021, this still does not work.
This is the link in that error message.In case you're wondering, it talks about "prefer secure origins for powerful new features" and location is consider one of those powerful features.
To generate the above, update the error section as follows:
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(position => {
// other
},
err => {
// include the "code" part
alert(`ERROR(${err.code}): ${err.message}`)
});
};
On desktop during development...It works because if you read from the above link you will note that localhost is considered a secure origin.
In fact, even the chrome link shared in #chrisheyn's answer above, there is a section "Does this affect local development?" and explains why this should work on locahost.
So how about Mobile during development?Notice that react serves the app over your network e.g. http://192.168.0.134:3000 and that is definitely not considered a "secure origin" at all.
This question "Can I detect at runtime if the geolocation was blocked because of not being on a secure context
" mentions that... Errors due to this secure-context issue will return a code of 1 which is a "Permission Denied Error".
What's the solution?
Until the react team updates how your mobile picks the app during development, there is absolutely nothing you can to solve this issue.
To use the HTML5 Geolocation API, you will need to run the app over HTTPS. This means push your app to the cloud/host (in order to test this feature) or if you can some manage to get this network url http://192.168.0.134:3000 to do https The latter option, i believe, is much harder but I'd be interested to know if someone pulls it off.

Chrome extensions for silent print?

I have made a silent print web application that prints a PDF file. The key was to add JavaScript to the PDF file that silently print itself.
To do this I open the PDF with acrobat reader in chrome, that allow me to execute the script (with the proper permissions).
But as it was announced this solution won't work after chrome 45 because the npapi issue.
I guess a possible solution could be to use the recently release printProvider of chrome extensions.
Nevertheless I can't imagine how to fire any of the printProvider events.
So the question is: Is ok to think in chrome extensions to make a silent print web application, and how can I fire and handle a print job for an embedded PDF of a HTML Page.
Finally I reached an acceptable solution for this problem, as I couldn't find it out there, but read to many post with the same issue I will leave my solution here.
So first you need to add your printer to the Google Cloud Print and then you will need to add a proyect to the Google Developers Console
Then add this script and any time you need to print something execute the print() function. This method will print the document indicated in the content
The application will ask for your permission once to manage your printers.
function auth() {
gapi.auth.authorize({
'client_id': 'YOUR_GOOGLE_API_CLIENT_ID',
'scope': 'https://www.googleapis.com/auth/cloudprint',
'immediate': true
});
}
function print() {
var xhr = new XMLHttpRequest();
var q = new FormData()
q.append('xsrf', gapi.auth.getToken().access_token);
q.append('printerid', 'YOUR_GOOGLE_CLOUD_PRINTER_ID');
q.append('jobid', '');
q.append('title', 'silentPrintTest');
q.append('contentType', 'url');
q.append('content',"http://www.pdf995.com/samples/pdf.pdf");
q.append('ticket', '{ "version": "1.0", "print": {}}');
xhr.open('POST', 'https://www.google.com/cloudprint/submit');
xhr.setRequestHeader('Authorization', 'Bearer ' + gapi.auth.getToken().access_token);
xhr.onload = function () {
try {
var r = JSON.parse(xhr.responseText);
console.log(r.message)
} catch (e) {
console.log(xhr.responseText)
}
}
xhr.send(q)
}
window.addEventListener('load', auth);
<script src="https://apis.google.com/js/client.js"></script>
Anyway this script throw a 'Access-Control-Allow-Origin' error, even though this appears in the documentation... I couldn't make it work :(
Google APIs support requests and responses using Cross-origin Resource Sharing (CORS). You do not need to load the complete JavaScript client library to use CORS. If you want your application to access a user's personal information, however, it must still work with Google's OAuth 2.0 mechanism. To make this possible, Google provides the standalone auth client — a subset of the JavaScript client.
So to go throw this I had to install this chrome extension CORS. I'm sure that some one will improve this script to avoid this chrome extension.
You can register an Application to a URI Scheme to trigger the local application to print silently. The setting is pretty easy and straightforward. It's a seamless experience. I have posted the solution here with full example:
https://stackoverflow.com/a/37601807/409319
After the removal of npapi, I don't believe this is possible solely programmatically. The only current way I know to get chrome to print silently is using chrome kiosk mode, which is a flag (mode) you have to set when starting chrome.
Take a look at these SO posts:
Silent printing (direct) using KIOSK mode in Google Chrome
Running Chrome with extension in kiosk mode
This used to be possible using browser plugins (e.g. Java + NPAPI, ActiveX) but has been blacklisted by most browsers for several years.
If interested in modern solutions that use similar techniques, the architecture usually requires the following:
WebSocket, HTTP or Custom URI connection back to localhost
API that talks through web transport (JavaScript or custom URI scheme) to an app running locally.
A detail of projects (several of them are open source) that leverage these technologies are available here:
https://stackoverflow.com/a/28783269/3196753
Since the source code of these projects can vary (hundreds of lines to tens-of-thousands of lines), a code snippet would be too large unless a inquiring about a specific project's API.
Side note: Some technologies offer dedicated cloud resources, which add convenience at the expense of potential latency and privacy. At the time of writing this, the most popular "free" cloud solution -- Google Cloud Print -- is slated to be retired in December 2020.

Categories

Resources