I have been trying to figure out how to proceed to call Google Calendar API from a Firebase Cloud function.
Currently the Flutter App is using the Google Sign In plugin to authenticate and authorize a user ( and it adds the Google Calendar scope ). A firebase user is then created/updated off of these credentials.
The issue is the Google Sign In is not returning a Refresh Token, only Access Token and an Id Token.
final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth =
await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
final FirebaseUser user = await _auth.signInWithCredential(credential);
The goal is to have a scheduled Cloud Function in Firebase that will run and access Google Calendar events for ALL users in the system using the Node.js Client for Google APIs.
Have hit sort of a dead end with out having that refresh token, since accessing the google apis, needs to check the refresh token. Since this is happening in the background in a cloud function we can not redirect to a confirmation screen for the user.
@nealdyrkacz
The issue at https://github.com/flutter/flutter/issues/42238 has been closed and moved here. Future collaboration on this issue will be done here.
@kroikie Any updates on this?
Hi @nealdyrkacz
can you please provide your updated flutter doctor -v
and your flutter run --verbose/flutter build --verbose ?
Also, to better address the issue, would be helpful
if you could post a self contained app on github
or the steps to reproduce it.
Thank you
flutter doctor -v
[✓] Flutter (Channel stable, v1.9.1+hotfix.6, on Mac OS X 10.14.4 18E226, locale en-US)
• Flutter version 1.9.1+hotfix.6 at /Users/nealdyrkacz/Documents/DEVELOPMENT/flutter
• Framework revision 68587a0916 (6 weeks ago), 2019-09-13 19:46:58 -0700
• Engine revision b863200c37
• Dart version 2.5.0
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
• Android SDK at /Users/nealdyrkacz/Library/Android/sdk
• Android NDK location not configured (optional; useful for native profiling support)
• Platform android-29, build-tools 29.0.2
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 11.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 11.1, Build version 11A1027
• CocoaPods version 1.8.0
[✓] Android Studio (version 3.5)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin version 39.0.3
• Dart plugin version 191.8423
• Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
[✓] VS Code (version 1.39.2)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.5.1
[✓] Connected device (1 available)
• iPhone 11 Pro Max • A0BC4CB8-2997-458B-93AD-D1530EABA232 • ios • com.apple.CoreSimulator.SimRuntime.iOS-13-1 (simulator)
The issue is stemming around being able to access the google apis in a cloud based function in firebase. A scheduled cloud function. The cloud functions will be written in node and use the google api nodejs client ( https://github.com/googleapis/google-api-nodejs-client ). In order to access the APIs it appears I need the access_token in addition to the refresh_token to set on an Oauth2Client.
Our initial sign in using the google_sign_in package will show the consent screen to a user and ask them to give access to the scopes we need. The user is signed in and access_token / idToken is returned, but no refresh_token.
`final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth =
await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
final FirebaseUser user = await _auth.signInWithCredential(credential);`
The node libraries have capabilities to do access_type: offline, but this does not appear to be the same for the google_sign_in package.
It seems others were searching for something of the same thing https://github.com/flutter/flutter/issues/15796
does this mean currently users using this will not be able to get a refreshed access token? if not used in nodejs libs?
im using google signin with flutter
I'm running into the exact same issue as you @nealdyrkacz. Trying to store access_token and refresh_token when users log in to later create an event on their calendars with a firebase cloud function.
Did you manage to solve this using google_sign_in? Thanks in advance!
@nealdyrkacz for flutter, what i did is store the last date when refresh token was retrieved, and if it's like 5minutes till the 1 hour expiry, i refresh it. this is through interceptors
however, there are cases where something might go wrong and the refresh token is already invalid so if an interceptor is capable to re-run the the request when the 401 is encountered then the user can refresh the token when the request is re-run.
As far as I know Firebase Auth does not support getting the refresh token for OAuth providers - this feature/bug/request would probably be better tracked on the issue @nealdyrkacz linked above (flutter/flutter#15796) as this is where the implementation needs to happen.
@Salakar why would firebase not allow for refresh tokens? This would seem like an extremely ignorant decision.
@Salakar why would firebase not allow for refresh tokens? This would seem like an extremely ignorant decision.
Firebase Auth focuses on AuthN and not AuthZ.
It does not manage OAuth refresh tokens for this reason. Once the users identity has been established (AuthN) the refresh tokens are discarded and only the initial OAuth access token is returned - as there is no further need for them.
This should come from the Google signin package instead if required, as above. I can see why it might be handy but in the end if the underlying Firebase SDKs that we wrap for FlutterFire don't have it then neither do we.
@Salakar I am quite sure that the refresh token is needed in order to refresh your access token and authorize your application to utilize Google's APIs in the backend. Without a refresh token every time you want to make an API call to Google, you will have to ask the user to resign in. This can become extremely annoying for the user since most access tokens expire within an hour.
Most helpful comment
The issue is stemming around being able to access the google apis in a cloud based function in firebase. A scheduled cloud function. The cloud functions will be written in node and use the google api nodejs client ( https://github.com/googleapis/google-api-nodejs-client ). In order to access the APIs it appears I need the access_token in addition to the refresh_token to set on an Oauth2Client.
Our initial sign in using the google_sign_in package will show the consent screen to a user and ask them to give access to the scopes we need. The user is signed in and access_token / idToken is returned, but no refresh_token.
`final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth =
await googleUser.authentication;
The node libraries have capabilities to do access_type: offline, but this does not appear to be the same for the google_sign_in package.
It seems others were searching for something of the same thing https://github.com/flutter/flutter/issues/15796