I'm using Soundclouds JS sample code for client side JS apps to connect with the Soundcloud API, as a start. The only difference between their code and mine is I've put in my own client_id and redirect_uri. (I also copied their callback.html, put it on my server, put its address in the soundcloud page for my app).
After ok-ing with my popup blocker, the auth popup comes up and asks permission to access my account, I give it permission, then the popup clears all previous content and simply informs: 'This popup should automatically close in a few seconds' - but it doesn't, and the rest of the code that shows its past authorization never displays.
Here is Soundclouds sample that I'm using. I've tried it while using a server on localhost and also deploying it and changing redirect_uri appropriately with the exact same results.
SC.initialize({
client_id: 'YOUR_CLIENT_ID', // changed it to mine
redirect_uri: 'http://example.com/callback'
});
SC.connect().then(function() {
return SC.get('/me');
}).then(function(me) {
alert('Hello, ' + me.username);
});
Looking in the dev console on both Chrome and Firefox, I dont see any errors. I've also made sure the protocol for my redirect_uri file matches between my account settings and the code.
Does the 'Website of your app' field on the Soundcloud page for my app make a difference? I tried setting it, it didnt fix it. What does client secret do?
The closest to an answer I've found so far is from this SO page where it seems he found out that you can't use an url that doesn't start with 'www.' ??? Its hard for me to believe that this is the problem and unfortunately for me neither localhost or my domain start with www.
Thanks in advance for any help.
In your callback.html, change the line:
<body onload="window.opener.setTimeout(window.opener.SC.connectCallback, 1)">
to:
<body onload="window.setTimeout(window.opener.SC.connectCallback, 1)">
In your application setup page at soundcloud.com, ensure your website setting and callback uri are on the same domain (whether that is localhost or the production domain) and all should work.
Note: for debugging, comment out this line to leave the popup there deliberately, then console can be used to interrogate other code in the callback.html page.
Related
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.
So I am trying to implement silent renewal in an ionic 3 application, I am still learning about the whole thing so I'll try to be as descriptive as possible please correct me if I am wrong.
Authentication
I am using Implicit flow for my authentication using the In App Browser.
The user is redirected to the authentication server page
After a success authentication I retrieve the id-token & access-token
As I understand the id-token is for authentication and access-token is for authorization with the API.
I have followed this article to help me set this up (Particularly the "Deploy to Mobile Device" section) for my Identity Server.
As done in the article I am using angular-oauth2-oidc to assist me with storing information about redirect links, issuer, etc...
I have attempted to achieve this in 3 different ways, 2 of them work but I don't understand how to retrieve the new access-token and id-token, and the last one returns an error. each of them left me with questions.
First: oauthService
The angular-oauth2-oidc library has a silentRefresh() method, and this github MD describes how to use it using a hidden iframe very vaguely so I barely understand how this works. I have created a silent-refresh.html page in the same directory, but using http://localhost:8000/silent-refresh.html return's a 404. Calling the silentRefresh() method successfully re-authenticates on the server side but the request times-out on the client side, as said in the MD file, something is wrong with the iframe.
Question 1: Does the library create a new iframe and then waits for a response to the http://localhost:8000/silent-refresh.html page but is never found so I never get my response? How to proceed to retrieve my tokens?
Second: iframe
So here I follow this article where I create an iframe and add it to the body. I create my own url (similar to the one made by the silentRefresh() method), and assign it to the src of the iframe. Again on the server side everything is fine and it tries to return the tokens to http://localhost:8000.
public startRenew(url: string) {
this._sessionIframe.src = url;
return new Promise((resolve) => {
this._sessionIframe.onload = () => {
resolve();
}
});
}
Question 2: How to proceed to retrieve the tokens? as it doesn't update my tokens automatically, and I don't see how the code above can do it.
Third: In App Browser
I thought this would work fine as I already know how to process the request using the In App Browser. So I tried to use the same url that worked for the iframe in the 2nd part. However this returns an error: prompt=none was requested. But user is not authenticated. on the server side, which tells that the server can't find the session so it doesn't know who is requesting the token renewal.
Question 3: Is there a specific reason this won't work other than I made a mistake?
NOTE: Took longer than expected to write this will edit this in a bit.
oAuthService
So I looked in to the implementation of the silent refresh, to see what it does. It creates an iframe with a default id, unless you override it. That cleared up a lot of confusion as to what was actually happening.
The next mistake I did was placing the silent-refresh.html file in the src/ folder, that makes it inaccessible to the iframe. Instead the file should have been placed in the www/ folder.
Then inside the iframe I kept getting the net::ERR_CONNECTION_REFUSED error. This was due to CORS and is solved by editing the Client int the Config.cs file on the Authentication Server:
AllowedCorsOrigins = { "http://localhost:8100", "http://<ip>:8100/", "http://<ip>:8100/silent-refresh.html" },
WARNING: This didn't work once I wanted to take this outside serving in the browser (ionic serve) or emulating on my device with ionic cordova run android -c-l-s, these made the root url return something like http://<ip>/. But once ran with ionic cordova run android (without the flags), window.location.href would return file:///<example>/<something>/index.html, using this sort of path (file:///<example>/<something>/silent-refresh.html) as a redirect url caused an ERR_UNSAFE_REDIRECT error to display in the iframe.
Perhaps silentRefresh() is an Angular only solution?
In App Browser
The mistake that caused the original error was having clearsessioncache and clearcache set to yes when creating the browser, caused the session to be wiped so the authentication server didn't know who it was duh, now reduced to this:
const browser = window.cordova.InAppBrowser.open(oauthUrl, '_blank',
'location=no, hidden=yes'
);
Regular redirect url of http://localhost:8100 could be used to catch the request with the new tokens. And the silent-refresh.html page is not needed.
Here is the code for creating the oauthUrl:
buildOAuthRefreshUrl(nonce): string {
return this.oauthService.issuer + '/connect/authorize?' +
'response_type=id_token%20token' +
'&client_id=' + this.oauthService.clientId +
'&state=' + nonce +
'&redirect_uri=' + encodeURIComponent(this.oauthService.redirectUri) +
'&scope=' + encodeURI(this.oauthService.scope) +
'&nonce=' + nonce +
'&prompt=none';
}
The rest of the code is pretty much identical to the originally mentioned article
I'm developing website with a lot of HTML5 and CSS3 features. I'm also using iframe to embed several content on my website. It works fine if I open it using Chrome/Firefox/Safari mobile browser. However, if I share on facebook (post/page) and I opened it up with Facebook application with Facebook Internal Browser, my website is messed up.
Is there any tools or way to debug on Facebook Browser? Thanks.
This is how you can do the debugging yourself. It's painful, but the only way I've come across so far.
tl;dr Get the Facebook App loading a page on your local server so you can iterate quickly. Then print debug statements directly to the page until you figure out what is going on.
Get a link to a page on your local server that you can access on your mobile device (test in mobile safari that it works). See this to find out your local IP address How do you access a website running on localhost from iPhone browser. It will look something like this
http://192.xxx.1.127:3000/facebook-test
Post that link on your Facebook page (you can make it private so your friends aren't all like WTF?)
Click the posted link in the Facebook mobile App and it will open up in Facebook's mobile browser
Since you don't have a console, you basically need to print debug statements directly to the page so it is visible. Put debug statements all over your code. If your problems are primarily related to CSS, then you can iteratively comment out stuff until you've found the issue(s) or print the relevant CSS attributes using JavaScript. Eg something like (using JQuery)
function debug(str){$('body').append("<br>"+str);}
Quite possibly the most painful part. The Facebook browser caches very aggressively. If you are making changes and nothing has happened, it's because the content is cached. You can sometimes resolve this by updating the URLs, eg /facebook-test-1, /facebook-test-2, or adding dummy parameters eg /facebook-test?dummy=1. But if the changes are in external css or js sheets it sometimes will still cache. To 100% clear the cache, delete the Facebook App from your mobile device and reinstall.
The internal browser the Facebook app uses is essentially a uiWebView. Paul Irish has made a simple iOS app that lets you load any URL into a uiWebView which you then can debug using Safari's Developer Tools.
https://github.com/paulirish/iOS-WebView-App
I found a way how to debug it easier. You will need to install the Ghostlab app (You have a 7-day free trial there, however it's totally worth paying for).
In Ghostlab, add the website address (or a localhost address) you want to debug and start the session.
Ghostlab will generate a link for access.
Copy that link and post it on Facebook (as a private post)
Open the link on mobile and that's it! Ghostlab will identify you once you open that link, and will allow you to debug the page.
For debugging, you will have all the same tools as in the Chrome devtools (how cool is that!). For example, you can tweak CSS and see the changes applied live.
If you want to debug a possible error, you can try to catch it and display it.
Put this at the very top of your code:
window.onerror = function (msg, url, lineNo, columnNo, error) {
var string = msg.toLowerCase();
var substring = "script error";
if (string.indexOf(substring) > -1){
alert('Script Error: See Browser Console for Detail');
} else {
var message = [
'Message: ' + msg,
'URL: ' + url,
'Line: ' + lineNo,
'Column: ' + columnNo,
'Error object: ' + JSON.stringify(error)
].join(' - ');
alert(message);
}
}
(Source: MDN)
This will catch and alert your errors.
Share a link on Facebook (privately), or send yourself a message on Facebook Messenger (easier). To break the cache, create a new URL every time, e.g. by appending a random string to the URL.
Follow the link and see if you can find any errors.
With help of ngrok create temporary http & https adress instead of your ordinary localhost:3000(or other port) and you could run your app on any devices. It is super easy to use.
and as it was written above all other useful information you should write somewhere inside div element (in case of React I recommend to put onClick on that div with force update or other function for getting info, sometimes it helps because JS in FB could be executed erlier than your information appears). Keep in mind that alerts are not reliable, sometimes they are blocked
bonus from ngrok that in console you will see which files was
requested and response code (it will replace lack of network tab)
and about iFrame.If you use it on other domain and you rely on cookies - you should know that facebook in-app browser blocks 3rd party cookies
test on Android and iOS separately because technicaly they use different browsers
I've got a problem with creating an App that could be then added to facebook pages as a tab. The problem is probably because I'm new to this facebook stuff and I'm doing something wrong here.
Currently I'm trying to use both URL and JS api call (as I'm using language other than english - the errors I put below could differ a bit from what they are in english). Of course APP_ID below is replaced with the proper app id.
URL:
https://www.facebook.com/dialog/pagetab?app_id=APP_ID&redirect_uri=facebook.com
which results in 'There was an error. Try again later.'
JS:
FB.ui({
method: 'pagetab',
app_id: APP_ID
}, function(response){});
which results in: 'This application could not be activated on your profile.'
The profile i"m trying to add this of course has some facebook Pages on it. The app I'm trying to add was created accordingly to https://developers.facebook.com/docs/appsonfacebook/pagetabs/ . I've created a simple Page Tab app, entered a test name and URL, and that's it. When I;m in the fb dev dashboard there's a green icon next to the app that says 'live and available to all users'.
Does anyone have idea what could be wrong here, and why can't I add this app to my FB page?
There cause of the error is likely to be two reasons:
The redirect_uri is incorrect. It must be part of your app domain (as setup in the App Settings). If you app is hosted at http://myapp.com, then the redirect_url needs to be on the same domain, e.g. http:/myapp.com/installed.php.
You have not setup the Application correctly on the App Settings page. Have you added the correct "Page Tab" settings? At the minimum, the Page Tab Name, Page Tab URL and Secure Page Tab URL are required.
So, I'm using the Facebook JS SDK, and I keep getting 191:
Now, I have checked my settings, and everything seems to be in order. App Domain is set to my base domain (alehunt.com), and "Website with Facebook Login" => "Site URL:" is set to "http://www.alehunt.com". I'm not doing any canvas-related stuff.
When looking at the URL for the login dialog window produced by FB.login I'm quite surprised to see that redirect_uri does not point directly to my app, but instead goes via http://static.ak.fbcdn.net/connect/xd_proxy.php. I'm wondering if this is the reason for the 191 error.
Now, if I change that part of the redirect_uri to be my own everything seems to work just fine. The dialog is presented as it should.
The complete URL is https://www.facebook.com/dialog/oauth?api_key=MYAPPID&app_id=MYAPPID&client_id=MYAPPID&display=popup&domain=www.alehunt.com&origin=1&redirect_uri=http%3A%2F%2Fstatic.ak.fbcdn.net%2Fconnect%2Fxd_proxy.php%23cb%3Df2f3026b8%26origin%3Dhttp%253A%252F%252Fwww.alehunt.com%252Ff298bcee3c%26relation%3Dopener%26transport%3Dpostmessage%26frame%3Df3d63e980c&response_type=token%2Csigned_request&scope=email&sdk=joey
Can anyone shed some light on this? Why is the JS SDK insisting on setting all this in the redirect URI?
The error I'm seeing is:
API Error Code: 191
API Error Description: The specified URL is not owned by the application
Error Message: Invalid redirect_uri: Given URL is not allowed by the Application configuration.
I'm testing in Chrome 21
Turns out this was due to using a Facebook JS client which had been modified by Cordova (PhoneGap). Still not sure exactly what the issue was, but everything worked just fine when I moved over to loading the JS directly from Facebook.