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

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

Related

Facebook Javascript SDK new access token in the background

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.

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)

JSONP or window.postMessage & MessageChannel

OK, so in building an x domain sso bit of logic we have reach an unknown.
To use JSONP or window.postMessage & MessageChannel (MessageChannel) for windows bastard child IE10.
The logic is (apparently fairly std). One master domain, 2 other domains (site2 and site3).
Logging into site1
user posts a form to master domain.
master domain, logs user into master and redirects back to site1.com/sso?token=uhytchvgjb
site1/sso decrypts token and logs user into site1
This logic works fine and makes sense. Now enter "in-context login". ie, js lightbox popup, login, convert page to logged in state.
The above 3 steps can be done in an iframe but then i would need to deploy the use of postMessage to alert the parent window of a successful login. However upon researching, postMessage is not ie friendly (shocker). So I would have to use MessageChannel, but then then seems like extra work for one annoying browser.
Is it possible to use jquery ajax and jsonp? ie, loggin into site1
user posts via ajax data to master domain
master domain authenticates details and logs in current user and returns in the response a token to the client.
the client on receipt of response passes token back to site.com sso check and returns a success to client
client then converts page to logged state or redirects to rel logged in page.
The above seems sensible and feasible. The question is, if the JSONP method was used, would the client be logged into the master domain or not?
Yes.
When JSONP request will be sent to secondary website, response may contain setcookie headers.
Session cookie can be set for secondary website this way. So, session may be started for it too. And logged-in flag can be set.

ASP.NET windows authentication box when webservice called

Got a very strange issue, never seen it before. Basically in the admin section of our website, a user attempts to edit something by clicking a button.
This button attempts to call a webservice (via jquery, which the page will then use to show an edit form in shadowbox).
However the user informs me that instead of the form popping up as usual it is blank for a few seconds. Then this pops up:
Any ideas? The webservice is in the admin section, which requires the user to be in a role (which the user is, otherwise they would never get to the point of being able to click the edit button).
This is normal if your web service is located on a different machine as your web server.
If the two machines are on the same domain, then the browser will attempt to use the default network credentials that has been cached.
This dialog will also pop up if the default credentials used to access the web server (which could be anonymous) does not have access to the resource (folder) where the web service is running. The pop up gives the user an opportunity to enter another set of credentials.

Is there a common practice to track the user session across browser window?

I am writing a website that is essentially a client-side web app, i.e. everything on the page is populate by scripts with data from ajax APIs. Users would be also signing in and signing out using a set of APIs.
My question is about how do deal with the following (but not quite extreme) use case:
User opens browser tab A and go to the website and logged in as user #1.
User opens browser tab B and also go to the website. Since there is a get_session API, the script restores the session on tab B.
User logged out from tab B while leaves tab A open.
User forgets about tab A for sometime, and go back and interactive with tab A.
Scripts in tab A attempts to fetch new data as user #1 but encounter error.
Ideally, there should be some way in step 3 that the tab A would also log itself out when user clicked logged out in tab B.
It's possible to log out tab A in step 5 (GMail do that), but I think there should be a better way. Even checking in step 5 would be non-trivial, cause for such design every API must know exactly which user's data the script is requesting, or the below use case would generate incorrect output.
(1-3) same as above.
User opens browser tab A and go to the website and logged in as user #1.
User opens browser tab B and also go to the website. Since there is a get_session API, the script restores the session on tab B.
User logged out from tab B while leaves tab A open.
User log in again from tab B but this time as user #2.
User goes back to tab A and interactive. While thinking the user is user #1, the script in Tab A request data from API.
API returns data that belongs to user #2. Boom.
Is there a common practice to prevent these kind of problem? Thanks.
Tim
The ajax response should indicate as an error condition that the user has logged out; on the client side, detect this error and perform the appropriate action. Obviously this only works when there is an ajax response, so you might want to implement some kind of 'hearbeat' mechanism, that is, the client sends a ping-like ajax message to the server every few seconds. When you log out, the server will respond to the heartbeat with a 'user logged out' error, and the client can go into 'not logged in' mode.
I don't think there is, because such communication between pages (tabs) would be a significant security weakness.
However, you could achieve the same effect by having each page (tab) polling the server to see if the session is still valid. Or use one of the event-handling techniques such as long-polling or streaming in an iframe.

Categories

Resources