Refresh Google OAuth2 Token Automatically - javascript

I'm trying implement a photo uploading to Google Drive feature (using the Google Drive API and GIS) into a web app that I'm working on, but can't seem to figure out how to keep a user authenticated for longer than the designated expiry time of the access token (which is 1 hour) without prompting the user or opening a popup.
The sample code provided at https://github.com/googleworkspace/browser-samples/blob/master/drive/quickstart/index.html forces the user to click a "refresh" button to get a new token, but this means I would have to force users to sign in every hour, which isn't ideal (since users are likely going to be using the app for periods longer than an hour at a time).
According to https://developers.google.com/identity/oauth2/web/guides/use-token-model#token_expiration, this appears to be intentional. However, after looking around quite a bit, I found that one could supposedly use a refresh token to generate a new access token that expires after another hour. Assuming you generate a new token every 45 minutes or so (which another Google article actually suggested, but I can't seem to find it now), then you should never have to worry about this re-authentication.
However, I can't figure out how to get a refresh token.
Not receiving Google OAuth refresh token suggests sending access_type=offline as a query parameter, but I'm not using any redirects, and the aforementioned documentation for initTokenClient and requestAccessToken don't make any mention of an access_type parameter.
The closest I've gotten is calling the requestAccessToken method periodically, but this still brings up a popup for the user to sign in again, which is what I'm trying to avoid. Even using requestAccessToken({ prompt: "" }) still brings up this popup window, but it at least logs in without any user input. Is there any way to disable this popup window entirely?
Worst case scenario, I force the user to re-authenticate every hour, but this seems like it would make for a less-than-ideal UX. Any help is appreciated.

I have stepped through GIS library code and can confirm that prompt='' and prompt='none' are not implemented the way requestAccessToken documentation implies. GIS always opens a pop-up window. The prompt parameter only changes what happens in the pop-up. There is also no token storage or caching features in GIS, only in pop-up.
The current prompt parameter behavior looks by design based on OAuth 2.0 flow comparison table. The access token should be refreshed only when user invokes an action that requires it.
This leaves us with pretty awful UX experience where pop-up has to briefly open and close every hour or so. Alternative is to use the authorization code flow. But it requires to implement a mechanism to send access token back to the client side from backend.

The button flow and consent popup behavior is intentional for browsers to obtain an access token, when configuring setting prompt to an empty string will suppress the user popup on every request: prompt=''.
Adopting the code model with auth code and exchanging the refresh token for access token is what you are looking for if you'd like to perform actions on behalf of the user without their being present or having to trigger a token request with a gesture such as a button press.

Related

On iOS, is there a way to detect a web page runs in the embedded browser and open the "real" one?

My web site uses magic links for login, however, I have a problem on mobile (not sure about Android - haven't tried yet, but the problem exists at least on iOS): when a user receives the email say in the GMail app, the link opens in the embedded browser, meaning that cookies will not be passed to the "real" browser.
Is there a way to ensure the link in the email opens in the real system browser and therefore cookies are stored permanently?
(Essentially browser session isolation on iOS breaks a lot of things on the Internet, so surely there is a workaround?)
After some research: no, it is not possible to detect you are in an embedded browser, neither is it possible to enforce opening a link in the system one. Makes sense from security point of view.
However, I was asking the wrong question. The problem of a magic link login is solved differently: when starting a login process you can set a session cookie and create an associated DB record for it, marking it as blocked, i.e. not logged in.
At next step, when the magic link is opened in whatever browser you unblock the session in the DB. At this stage you can replace the login cookie with a real one, e.g. JWT, or continue using it as your main auth token.
If the user then returns to the real browser, you check the login cookie and act accordingly, keeping in mind that it may not be the browser where they validated the magic link. At this stage you can, again, replace the login cookie with your real auth cookie knowing that the session has been validated already.
I'm not entirely sure this is 100% safe, need to think about it more but at first glance it does look safe and seems to be pretty much the only way of handling magic links on mobile.

Fetch posts from Facebook page using FB API

Up until this summer, I had a website (not my website) which was fetching it's responding fb page posts and was displaying it on a page.
I was doing it using the app-token, which now doesn't work since it now requires Page Public Content Access to get those data, which in turn requires it to be registered as an app, which is beyond the scope of this.
I tried creating a non-expiring user-access token, but they seem to expire after 3 months, no matter the "trick" I tried using.
Is there any suggestion of how I can get over it?
Maybe an automated api call that would refresh the token with no user interaction?
You can either use a Page Token (NOT a User Token) for the Page if you manage it - but it will expire. There is no way around that. OR you apply for Page Public Content Access so you can use an App Token.
Auto-refreshing would make the whole point of expiring Tokens pointless, you need user interaction for that.
So, I did it!
Now the how: I did it with the manage_pages access, not with Page Public Content.
I went back and forth a total of 5 times to get this to pass and a bit over a week.
First of all Page Public Content is only allowed by Facebook when you want to analyze data from other pages as well, so you better not mess with it.
What I had to do to get the request approved is specify on your application for requesting the access that there is no login, provide a copy of your code on the description and I also included a url where it was working with a user generated token through javascript, so they could review the code through a web debugger.
After that you get a manage_pages token which you can use to fetch your pages posts
I really hope some of those things were an overkill, but, like I said, I had to submit a review a total of 5 times, so on the last try I went all in...

How to execute some javascript when the user log out of google from another tab?

I have an appengine application that works with google logging system.
The services i propose are based on the user account and linked to it (for instance, saving the user's work on his account).
I noticed that it breaks my app when the user logout from a google service on another tab (for instance, gmail). When coming back to the tab of my website, things don't work anymore, the user is logged out here too.
I'd like to know when the user is logged out and execute some javascript code without having to do some polling on my application that will increase the appengine costs.
What solutions do i have for that ?
You can use the Channel API and open a channel that waits for a message when you get logged out.
However, Channel API calls are pretty expensive, so this could end up being more expensive.
The cheapest way to go would be to return a particular error code if you're logged out, and handle that error code across all your AJAX calls.
You cant without polling unless you write a browser extension that alerts your tab (hard and varies on browser brand).
The behaviour you see is expected. They log out of their google account, not the website.
You could also poll only when the user selects your tab instead of always.

OAuth and Facebook page tabs

I'm in need of more of an explanation than an answer, per se - I'm building a page tab, which will pull certain images from a particular album belonging to the page. This does not require an access token, so there is no need to ask for permissions from visitors.
I can add like/share options which also work fine without an access token or authorisation.
How do I get basic user info (id, name etc) without requesting authorisation? It's a page tab, on Facebook, so therefore the visitor must be logged in already.
Just seems counter intuitive if I have to request permissions to perform what is essentially pretty standard actions.
I'm using the javascript SDK.
It's a page tab, on Facebook, so therefore the visitor must be logged in already.
The user may be logged in to Facebook – but he is not necessarily connected to your app (yet). And you need him to be, to get his user id.
Make a call to FB.login without asking for any permissions in the scope parameter – that’ll prompt the user to connect to your app, giving it only “basic” permissions to read his personal data. That’ll give you his user id in the response.authResponse (and also will lead to his user id being included in the signed_request next time he visits your page tab).
After that, you can get his basic user info be calling /me via the Graph API.

Getting Facebook Page Posts

I've written a bit of JavaScript that will fetch all of the posts on a Facebook Page. The URL with which I do that is this:
http://graph.facebook.com/cocacola/feed?limit=5&callback=facebookResponse
and this worked fine and dandy, right up until last week sometime, when I started seeing oauth errors.
I've searched for an hour or so on Stack, and seen plenty of other people are trying to do this, - but none have been asked after all of my requests to FB started returning these oauth errors.
It really doesn't make sense, - I'm trying to access publicly available data from company pages. I can still do so without oauth (albeit in a limited fashion) via RSS.
Anyhow, I'm hoping someone can clue me in as to how to get this PUBLICLY AVAILABLE information without having to go through the rigmarole of getting an application ID, an authorization token, etc.
This is a recent not-so-recent change, but you now need an access token to access /feed and /posts. Annoying, but at least it's navigable.
Edit: updated the link, which has broken in the many years since this post was relevant. Here's the relevant text from that post for future posterity:
Breaking change: Graph API PROFILE_ID/feed and PROFILE_ID/posts requires access_token
The Graph API PROFILE_ID/feed/ for a Page, Application, User or Group and PROFILE_ID/posts for a Page or User will now require a vaild [sic] access_token to access the wall or posts of the corresponding object (where previously no access_token was required). This will also affect direct FQL queries to the stream table, when querying for posts on a wall.
You will need to pass a valid app or user access_token to access this functionality. Please update your code if you are calling this API without an access token. This change will go live a week from today - Friday(June 3rd). We have updated the Roadmap to reflect this change.
Moving forward, you should always pass a valid app or user access_token with all API requests.

Categories