Google OAuth conditional scope, requestPermissions - meteor

I am using the Meteor Account package for OAuth login with google.
My use case is to allow users to login with google. And later, provide them options to opt for linking to Google calendar.
i.e by default I need only email/profile scope during login. And, when the user clicks the button inside the app ( like Update events to my Google calendar ), I want to get the permissions for accessing https://www.googleapis.com/auth/calendar.events.
One option I figured out is to call LoginWithGoogle the second time with the requestPermissions.
My questions are,
Is this the correct way?
If so, how do I prompt the user to provide permission ( without further button click) if the user is denied or revoked this access later point? i.e when getting 403 - insufficientPermissions error.
What are the exceptions that I need to take care of?
Your help is highly appreciated.

Related

'Token has been expired or revoked' - Google OAuth2 Refresh token gets expired in a few days

I am using Google Analytics API to fetch analytics data. I tried to authenticate it using following steps:
Created OAuth client ID in https://console.developers.google.com/ credentials section.
In consent screen I had set publishing status as testing
In OAuth 2.0 Playground I got the refresh token using above generated client id and client secret
Then I am using it to generate access token through it.
But after a few days, the refresh token expires although it is mentioned that the refresh token's validity is life long.
If your app is in testing mode then user tokens will expire in 7 days. Please find this explanations here: https://support.google.com/cloud/answer/10311615#zippy=%2Ctesting
I needed to send mails from a gmail account that I have access to, using nodemailer. It works for a couple of days before my refresh token is mysteriously revoked, even though the account belongs to me. A google search brought me here and I had been watching for a while hoping someone would help with a solution.
As you mentioned, this seems to happen with only test/unverified apps and I'm guessing google revokes tokens for such applications in your account after a few days. After much trials and errors, here is what I did.
NOTE: This is solution is only applicable to accounts you own, otherwise you must verify your app to access other people's accounts
Generate a new refresh token (existing one is most likely revoked) as described in this SO post
Go to the security tab of your google account dashboard
Under the Recent security activity section, you should see a security alert for your app.
Click on the context menu next to the notification and click DISMISS
At this point you'll be presented with a dialog of options where you indicate the level of trust you have for the app. I just went ahead and said I trusted the developer/app, obviously. And that's it! The refresh token should persist after this.
I could not find anything related anywhere else.
The other answer pointed me in the right direction but for me the option was located somewhere else: security > security checkup/security issues found > context menu next to your app > dismiss
This issue seems to be for unverified apps, Simply delete the token file from your project and rerun the project, it will create a new token.
My problem was when I've added access_token instead of refresh_token.
What I did:
Go to https://console.cloud.google.com/apis/credentials/consent and change from the testing status to published.
Delete the current token file.
Authorize the API again by signing into your gmail account. You will be sent to a warning screen. From there, you can choose to proceed.
When done you'll get a new token file
The solution is to delete your token.json file to force Google to find a new token.
I was able to get it to work WITHOUT a verified app. Perhaps the refresh() method will work once my app is verified. Not sure on that one.

Google calendar API grantOfflineAccess() without a pop up

We have been working on an app that requires access to a users google calendar. We have been using the grantOfflineAccess() method described in google api's documentation - https://developers.google.com/identity/sign-in/web/reference#googleusergrantofflineaccessoptions
However, the problem we are facing is that this opens a pop up and we need to do this via a redirect. Does anyone have any ideas todo this without a pop up showing up?
Safari and Firefox block pop ups and this does not really work well on safari on mobile.
I was able to find a GitHub issue for this https://github.com/google/google-api-javascript-client/issues/288 but I have seen other websites do this without a pop up. You can check zendesk & frontapp.com - both of whom take offline grant for the users signing in.
Any ideas or help would be appreciated.
The only way to access a users data is to have a user grant you permission to access that data. This is done though Oauth2 a user is promoted to login to their google account then they are given a screen with the scopes of permissions that you are requesting.
There is no way around this. YOu will always have to ask a user at lease once to grant you permission to access their data if you are requesting offline access you will be given a refresh token that you can use to request a new access token and access the users data when they are not online.
As for popups they shouldn't be displaying as popups they should be opening in a new browser window.

How to get Google Sign-In for Websites to work with Identity Aware Proxy

I have a web site in google cloud. I use Identity-Aware Proxy (IAP) to protect it.
When a request comes in IAP checks if I'm authorized and then responds with either
if I'm authorized: the response from the resource I requested
if not: a 302 or 401 response depending on if it thinks it is an ajax call or not
Now I want to use Google Sign-In for Websites on top of this.
This might seem redundant since I am already logged in by the time I would see the buttons but I want to use it as a way to log out or change user account.
Now what I have tried to do is:
var auth2 = gapi.auth2.init({
client_id: 'mykey.apps.googleusercontent.com',
})
auth2.isSignedIn.get()
// false, I was hoping that I could somehow piggyback on my existing session
auth2.signIn()
// shows a pop up, allowing me to select an account
auth2.isSignedIn.get()
// true
currentUser.getBasicProfile()
// works
This seems to work except it shows me a login box even when I'm already logged in which is suspicious.
Add to this that when I do
auth2.disconnect()
auth2.isSignedIn.get()
// false
and then do a full refresh then I still get my resources from IAP proving that I'm still logged in there.
Questions:
How can I get this to work?
Is this even the correct way to do it?
I don't know much about Sign-In for Websites, but there's another option that might work for you. Have you considered adding a link to /_gcp_iap/clear_login_cookie to provide a "change user account" option? (It's documented here: https://cloud.google.com/iap/docs/special-urls-howto )
If the user is logged in with multiple Google accounts, that will bounce them back to the account picker. Today, if they're only logged in with one account, it will just send them right back into the application -- but there's an enhancement rolling out next week which will display the account picker even for the single-account case, giving the user a chance to sign in with an additional account.
Hope that helps!
--Matthew, IAP engineering lead

Google Analytics refresh token invalidates

We allow our users to connect their Google Analytics account to our CMS. However, many of them choose to have us manage their GA, so we have a lot of properties.
Each property has its own View ID, and when we connect the View ID, we do so by entering the View ID. Then, the account select prompt shows up. We select the account that owns the property (which is usually the same account, say admin#company.com), and then retrieve access and refresh token.
This all works well. Except, sometimes it seems the refresh token invalidates.
Is this because of the refresh token limit (we definitely manage more than 25 clients)?
If so, what would be a better way to connect the property to the site, while still allowing users to use their own GA account if they wish to do so?
I was thinking of trying to retrieve which google account is being use for the connect, but I am not sure how I would do that.
Any ideas?
I figured it out. The refresh token limit is per actual google account, took me a while to figure that out. I now store a default value in the main DB and if that one can access the ID that is to be connected, the default is used. Otherwise it will redirect to the Google auth window and authenticate normally.

What type of facebook auth/token do I need for this?

I want to build a custom asp.net control to put on a webpage that will allow people to see a piece of information from my facebook account that requires auth. For the sake of simplicity let's just say I'd like it to display the last thing that I liked. I don't want the visitor to my site to have to be logged into facebook (nor would they have to be my friend on fb). I want my site to somehow store a token that I have authorized and then it will use this token for the access. I know this can be done initially, but I'm confused what happens when the token expires. Or for that matter if I log out from facebook. Is there some type of token or secret or something that I can request that can be auto-renewed again and again by my website independent of any login state that I have as an fb user? Does this require me creating an fb app and associating the token to it?
I don't have any code at this point, I'm looking for a higher level of guidance on the protocol that should be used here, from there I can hopefully figure out the code from existing samples, docs, etc. This is my first code interaction with facebook so don't assume that I know very much at this point :-)
EDIT: I've been reading everything I can about this topic and I can't seem to find a solution. In the past there was an RSS feed but that appears to be gone now. Then there was also the offline_access permission which is no longer available. This seems like such a simple task but I'm just not able to connect the dots. I have been able to get the initial user token with perms for reading "likes", that's easy. Now I can store that in my website's db and use it to make requests for that data anytime someone loads my page. But eventually the token will expire and I'm not seeing any automatic way to renew it that wouldn't potentially involve user "Larry", who happens to be browsing my website, being asked to supply MY facebook credentials. Basically it seems as though I could never log out from facebook or I'd be risking a broken feed on my website. Is the fb auth model just not set up to allow for thist? To summarize again - a user Bob wants to give his permission to acme.com to always be able to display Bob's most recent like regardless of whether Bob is logged in to fb or not. He would only want to have this stop working if he revoked authorization to the WhatDoesBobLike app which runs on acme.com. Possible?
-JT
You would need an extended access token. It will only last up to 60 days and from then you would need to re-extend.
If it were a page you could extend the user access token then grab the page access token which would never expire.
Read more at
http://developers.facebook.com/roadmap/offline-access-removal/

Resources