Facebook Javascript SDK new access token in the background - javascript

How can I refresh a long lived facebook access token in the background? From the facebook documentation
Even the long-lived access token will eventually expire. At any point,
you can generate a new long-lived token by sending the person back to
the login flow used by your web app - note that the person will not
actually need to login again, they have already authorized your app,
so they will immediately redirect back to your app from the login flow
with a refreshed token - how this appears to the person will vary
based on the type of login flow that you are using, for example if you
are using the JavaScript SDK, this will take place in the background,
if you are using a server-side flow, the browser will quickly redirect
to the Login Dialog and then automatically and immediately back to
your app again.
What I'm trying to reconcile is that in order to get a new access token you need to have the user login. In order to login, you must call FB.login(). According to the documentation, a user should click a button in order to login.
As noted in the reference docs for this function, it results in a
pop-up window showing the Login dialog, and therefore should only be
invoked as a result of someone clicking an HTML button (so that the
pop-up isn't blocked by browsers).
How can you refresh a long lived access token in the background with the facebook javascript SDK?

You can only refresh a User Token if the user visits your website: Use FB.getLoginStatus for that. You do not need to use FB.login - it would only work on user interaction (click event) anyway, because browsers usually block the popup if you try to call it automatically.

Related

Is there a way for a new window to communicate with the window that spawned it?

I have an application that asks a user to login with Reddit. When they accept, it opens a new window (call it SpawnedWindow), Reddit asks them if they want to connect, and when they do, SpawnedWindow redirects to a GET endpoint on my server with the success/failure information. My server will do some computation to figure out if the auth was really successful, and if it is, it will send an "ok" (as a response to the GET request) to SpawnedWindow.
I want the original page to detect this "okay" and continue with user onboarding. How might I communicate this between the new window and the original window?
If you're familiar with "login with Google" buttons: as we know, there's a popup, and depending on the result of authentication, the main page will have dynamic behavior (based on the login being successful or not). This is essentially what I'm trying to achieve.
The API (and many APIs which have a similar authorization process) provides a redirect_uri that the user will be redirected to after authorization succeeds. You can pass a redirect_url query parameter that goes to a page on your site. This way, once authorization succeeds, the newly opened page (on your site, that Google has redirected the popup to) can communicate to the original page (on your site).
One way to do this is with a BroadcastChannel - open a channel on your original page, and wait for a message. On the new page, open the same channel and send a message, and the old page can listen for the message.
Another option would be to use Local Storage. On the original page, listen for storage change events. On the new page, change storage so as to fire the event.

How can I prevent early popup closing when using chrome.identity.launchWebAuthFlow?

I'm calling chrome.identity.launchWebAuthFlow from a background script of my Chrome extension.
This is used to get implicit user authentication with https://login.microsoftonline.com
The sign in popup appears fine allowing for user credential input. However after credentials are submitted the window is not redirected to my callback redirect uri. Instead it redirects to another page (which is some kind of corporate signin page within Microsoft Azure AD) which does not require user's action.
At this very moment the window gets closed and I get undefined response in launchWebAuthFlow callback function. At the same time I get console error: Unchecked runtime.lastError: Authorization page could not be loaded.
The same flow works fine from the browser window: after credentials provision and redirect to the corporate signin page, it's finally redirected to my redirect url (with auth token ready).
From this I conclude that launchWebAuthFlow is not waiting till redirect is done to my redirect page but closes popup prematurely.
Is there a way to prevent this?
I spent too much time at this but found a workaround.
Still not sure why launchWebAuthFlow behaves like this. But I decided to resolve otherwise.
This double redirection happens because Microsoft auth page first requires plain e-mail address input. This allows it to decide which corporate auth page to redirect to. This happens even if it reuses the current session (cookies).
So I looked for a way to shortcut the route and give the first auth page a hint about what corporate page should go next. For this you have to add one more parameter to the url used by launchWebAuthFlow:
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize
?client_id={client-id}
&response_type=token
&login_hint=user#domain.com
&prompt=login
&redirect_uri={redirect-uri}
&scope={some-scope}
Please note, that I had to add prompt=login as well. It works without it from the browser (actually even faster with alive session). However, this is needed if called from chrome.identity.launchWebAuthFlow
Hope this will help somebody in similar situation.
More details here: Microsoft identity platform and Implicit grant flow

Is it possible to refresh an OAuth2 token asynchronously without triggering a popup blocker?

I'm using hello.js to implement OAuth 2 based (google sign in) authentication for a single page web application. If the user has not allowed the site in their popup blocker then calls to refresh the token will be stopped if they were triggered by an asynchronous or non-user-initiated action.
So a user clicking a delete button that checks & refreshes the token before making a delete request will work fine. However, a background polling request to check for updated data will trigger the popup blocker if it needs to refresh the token.
To check and refresh tokens when necessary I'm wrapping all authenticated request in this hello.js login method as described in the refresh section of the docs.
google.login({force: false}).then(function() {
google.api('me').then(fireRequest);
});
Is this issue a limitation of the library, my implementation or OAuth2 flows in general? How do other sites refresh OAuth tokens during actions that aren't synchronous user initiated events?

Detecting if app loaded from a page

So my app is (mostly) running. This is a corporate app, that our clients will 'install' on their own Facebook page(s), and make available for THEIR clients to run. During the connection process, I use the FB UID to determine their account on our system, connect that UID to the local account ID. I save that connection in our database, so that when the app is triggered from a Facebook account, I use that mapping to access the correct data.
First issue: I want to be able to detect that the app is being triggered from a Facebook page. I went into the App Settings page, and set up the "Page Tab" platform, with a secure URL. But when my app is added to a page tab, that URL is not invoked, but the Secure Canvas URL is invoked. Why? I assumed that was the point of having a Secure Page Tab URL for my app.
But if that doesn't work, is there a way to identify that my app was invoked from the Page Tab instead of some other way? Not as clean, but that would word as well.
I have used the Javascript API to login, and connect the App to a page. This is all working well.
This is answered in the Page Tab App documentation:
When a user selects your Page Tab, their browser will send a HTTP POST
request to your app's Secure Page Tab URL. This request will contain a
Signed Request in the signed_request parameter with fields you can use
to customise the content returned to the user.
If you're seeing the 'wrong' url triggered, make sure you're not accidentally redirecting, either upon receiving the initial POST request from the user's browser, or after using Facebook Login (e.g. if your redirect_uri when opening the dialog is accidentally sending all users to the same URL after login instead of back to where they triggered the flow from)

Facebook Javascript Canvas Login Redirect

I am building a facebook canvas application and want users, when they visit "apps.facebook.com/myApp", to be presented with the appropriate login dialogue immediately instead of showing my canvas page without having been logged in. With all the different login flows, I am confused!
Using javascript, how do I do this? Do I set the default canvas page to be a page with a script with a redirect url in it?
You should not immediately present them with the login dialog, it is best practice to show some intro screen with information about your app first. Else there is only a small authorization information and no use will really know what the app is about. Then let the user click on a "Login/Use/Start/..." button to present the authorization popup with the FB.login function of the JavaScript SDK:
https://developers.facebook.com/docs/reference/javascript/FB.login/
If you really want to require user authorization right at the beginning, user the PHP SDK:
https://github.com/facebook/facebook-php-sdk
See "$facebook->getLoginUrl()" - just redirect to the resulting URL if the user is not logged in.

Categories

Resources