Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

[google_sign_in] Fix issue obtaining serverAuthCode on Android and add forceCodeForRefreshToken parameter #3356

Merged
merged 25 commits into from
Sep 23, 2022

Conversation

fbcouch
Copy link
Contributor

@fbcouch fbcouch commented Dec 20, 2020

Description

This is a follow up to #2116 to fix the following issues:

  • serverAuthCode is always null on Android because it is not passed to the GoogleSignInAuthentication object as that is created by the getTokens call rather than from the data obtained during the initial signIn call (which does contain a serverAuthCode, it's just not accessible anywhere that I can tell)
  • A refresh token is only given to the server on the first sign in without the ability to set the forceCodeForRefreshToken parameter

Related Issues

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • My PR includes unit or integration tests for all changed/updated/fixed behaviors (See Contributor Guide).
  • All existing and new tests are passing.
  • I updated/added relevant documentation (doc comments with ///).
  • The analyzer (flutter analyze) does not report any problems on my PR.
  • I read and followed the Flutter Style Guide.
  • The title of the PR starts with the name of the plugin surrounded by square brackets, e.g. [shared_preferences]
  • I updated pubspec.yaml with an appropriate new version according to the pub versioning philosophy.
  • I updated CHANGELOG.md to add a description of the change.
  • I signed the CLA.
  • I am willing to follow-up on review comments in a timely manner.

A note on flutter analyze: this plugin updates google_sign_in and google_sign_in_platform_interface, so flutter analyze won't pass until the google_sign_in_platform_interface update is published or an additional commit is applied that sets up local path dependencies (see fbcouch@3bbdfec ). I can split that into two pull requests if needed.

Breaking Change

Does your PR require plugin users to manually update their apps to accommodate your change?

  • Yes, this is a breaking change (please indicate a breaking change in CHANGELOG.md and increment major revision).
  • No, this is not a breaking change.

Festivus Note

As the season of Festivus is upon us, I do have a grievance to air from the last time I submitted a PR related to this plugin. I was told on #879 that my pull request to add the serverAuthCode (which worked on android, as a side note) would not be accepted without E2E tests using a test harness that wasn't even ready yet. You can imagine my surprise when #2116 was merged a few months later without them (no disrespect to the author of that PR, they did what was asked of them).

@stuartmorgan-g
Copy link
Contributor

Thanks for the submission! We’re currently working through a large backlog of PRs, and this will require non-trivial review, so it will take some time before we’re able to review it. As explained in CONTRIBUTING.md, votes for the corresponding issue are the primary way we’re prioritizing non-trivial reviews, so we encourage anyone interested in this PR to vote for the corresponding issue.

We apologize for the long delay in triaging this PR. We’re in the process of overhauling our PR triage system to respond much more quickly, as well as working through the backlog.

(Note that #2792 is making a similar change, so when they are reviewed we should ensure we converge on a single PR that addresses everything.)

@stuartmorgan-g
Copy link
Contributor

As the season of Festivus is upon us, I do have a grievance to air from the last time I submitted a PR related to this plugin. I was told on #879 that my pull request to add the serverAuthCode (which worked on android, as a side note) would not be accepted without E2E tests using a test harness that wasn't even ready yet. You can imagine my surprise when #2116 was merged a few months later without them (no disrespect to the author of that PR, they did what was asked of them).

Unfortunately our push toward better testing coverage occasionally misses things, leading to inconsistencies like that. As evidenced by the need for this PR, that one really shouldn't have landed either without e2e testing!

@dreenot
Copy link

dreenot commented Apr 26, 2021

This problem is very relevant, and it is around for a long time. A huge part of Google's Api depends on server side authentication.

I am currently trying some workaround to implement his changes on my installation, but I'm getting an error "google_sign_in_platform_interface ^1.2.0 which doesn't match any versions, google_sign_in from git is forbidden." If I can, I'll use it before it's merged into master

@dreenot
Copy link

dreenot commented Apr 27, 2021

I updated the code to work with the current master. It's working fine for me. But it would be better if this PR was updated instead. I'm not very experienced making PR to large projects. But I made it available since it might be useful to someone who needs this specific task or in case this is not being updated. If necessary, I'll fix the issues.

@fbcouch fbcouch force-pushed the force-code-for-refresh-token branch from a09c3f5 to e3aea13 Compare April 27, 2021 21:55
@fbcouch
Copy link
Contributor Author

fbcouch commented Apr 27, 2021

@dreenot It looks like basically what was needed was updating the version numbers and adding some nullable types, right? I updated this PR accordingly...I think your PR was missing the updated implementations of hashCode and == on the GoogleSignInUserData interface. And I think the CHANGELOG entry for the platform interface didn't make it over. Let me know if the updated PR works for you, though!

@stuartmorgan No problem! I was just a bit frustrated at the time and about to embark on a saga of a PR to add scribble support (which is still in progress, actually)

@fbcouch
Copy link
Contributor Author

fbcouch commented Apr 27, 2021

BTW here is a patch that makes the analyze work properly:

diff --git a/packages/google_sign_in/google_sign_in/pubspec.yaml b/packages/google_sign_in/google_sign_in/pubspec.yaml
index d1443664..69daa456 100644
--- a/packages/google_sign_in/google_sign_in/pubspec.yaml
+++ b/packages/google_sign_in/google_sign_in/pubspec.yaml
@@ -16,8 +16,10 @@ flutter:
         default_package: google_sign_in_web
 
 dependencies:
-  google_sign_in_platform_interface: ^2.1.0
-  google_sign_in_web: ^0.10.0
+  google_sign_in_platform_interface:
+    path: ../google_sign_in_platform_interface
+  google_sign_in_web:
+    path: ../google_sign_in_web
   flutter:
     sdk: flutter
   meta: ^1.3.0
diff --git a/packages/google_sign_in/google_sign_in_web/pubspec.yaml b/packages/google_sign_in/google_sign_in_web/pubspec.yaml
index 52eedf8f..74cac167 100644
--- a/packages/google_sign_in/google_sign_in_web/pubspec.yaml
+++ b/packages/google_sign_in/google_sign_in_web/pubspec.yaml
@@ -12,7 +12,8 @@ flutter:
         fileName: google_sign_in_web.dart
 
 dependencies:
-  google_sign_in_platform_interface: ^2.0.0
+  google_sign_in_platform_interface:
+    path: ../google_sign_in_platform_interface
   flutter:
     sdk: flutter
   flutter_web_plugins:

@dreenot
Copy link

dreenot commented May 1, 2021

@fbcouch I noticed another problem that I'm afraid we can't fix here. Yes, we are able to get the serverAuthCode using your code.
But the code is invalid. You cannot use the code because your Access Type is not Offline. The problem is not in your code.

I consulted the documentation all the way down to Google Play Services, it SHOULD be setting it to offline when you use requestServerAuthCode either you setting forceCodeForRefreshToken or not. It is well stated in the documentation. Therefore, it does not happen. The code is sent, but your authorization remains Online. And the attempt to use the code returns "error": "invalid_grant"

image
image
image
image

requestServerAuthCode is being successfully sent, otherwise I'd not be able to get the serverAuthCode . Since the documentation says it supposedly set it to offline, it's a bug. I didn't find another way to set it. I reported it to Android Issue Tracker https://issuetracker.google.com/issues/186806274

https://developers.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInOptions.Builder

@fbcouch
Copy link
Contributor Author

fbcouch commented May 1, 2021

@dreenot Oh that is very interesting...what version of google play services are you using?

I am able to get valid serverAuthCodes on com.google.gms:google-services:4.3.0 (I think that would be the relevant library, not 100% sure of that though)

@dreenot
Copy link

dreenot commented May 2, 2021

@fbcouch It happens I had an invalid_redirect_uri before, and I didn't notice it, what "used" the code even though it was not successful. The token is still access_type Online for some reason, but it is working for Offline access. So, I guess you can disregard my last comment since it's going to work. But part of the info in https://www.googleapis.com/oauth2/v1/tokeninfo is not correct.

@stuartmorgan-g stuartmorgan-g removed the request for review from mehmetf January 6, 2022 16:14
@stuartmorgan-g
Copy link
Contributor

I believe the first of the two bullet points in the PR description was obsoleted by #4180

For the second part, can you explain why this is something configured for the entire app via an XML property, rather than being part of the API surface?

@godofredoc godofredoc changed the base branch from master to main January 6, 2022 22:56
@flutter-dashboard
Copy link

It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie on the #hackers channel in Chat.

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@fbcouch
Copy link
Contributor Author

fbcouch commented Jan 6, 2022

Yes, it looks like at least the serverAuthCode part is handled already now, so we just need the forceCodeForRefreshToken stuff. I think I had done it through the XML because that's the way most of the android options are defined. Adding it to the API surface sounds better to me. I'll see if I can make some time in the next couple of weeks to update this to target the latest main branch and reduce it down to just the forceCodeForRefreshToken stuff.

…low android to receive a refresh token on every sign in
@fbcouch fbcouch force-pushed the force-code-for-refresh-token branch from 0f984ea to b73d66e Compare January 11, 2022 23:12
@jmagman
Copy link
Member

jmagman commented May 11, 2022

Formatting issue:

To fix run "pub global activate flutter_plugin_tools && pub global run flutter_plugin_tools format" or copy-paste this command into your terminal:
patch -p1 <<DONE
diff --git a/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/GoogleSignInPlugin.java b/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/GoogleSignInPlugin.java
index e49a55b08..d9df30ac9 100644
--- a/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/GoogleSignInPlugin.java
+++ b/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/GoogleSignInPlugin.java
@@ -42,8 +42,6 @@ import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
-import android.content.res.Resources;
-import android.util.Log;
 /** Google sign-in plugin for Flutter. */
 public class GoogleSignInPlugin implements MethodCallHandler, FlutterPlugin, ActivityAware {
@@ -260,26 +258,25 @@ public class GoogleSignInPlugin implements MethodCallHandler, FlutterPlugin, Act
   }
   /**
-   * Factory class that generates the GoogleSignInOptions.Builder. This is exposed so that tests
-   * can inject a mock instance of the GoogleSignInOptions.Builder.
+   * Factory class that generates the GoogleSignInOptions.Builder. This is exposed so that tests can
+   * inject a mock instance of the GoogleSignInOptions.Builder.
    */
   public static class OptionsBuilderFactory {
     public static final String DEFAULT_SIGN_IN = "SignInOption.standard";
     public static final String DEFAULT_GAMES_SIGN_IN = "SignInOption.games";
-    /**
-     * Returns an instance of GoogleSignInOptions.Builder with the passed signInOption.
-     */
+    /** Returns an instance of GoogleSignInOptions.Builder with the passed signInOption. */
     public GoogleSignInOptions.Builder get(String signInOption) {
       switch (signInOption) {
-          case DEFAULT_GAMES_SIGN_IN:
-            return new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN);
+        case DEFAULT_GAMES_SIGN_IN:
+          return new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN);
-          case DEFAULT_SIGN_IN:
-            return new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).requestEmail();
-          default:
-            throw new IllegalStateException("Unknown signInOption");
-        }
+        case DEFAULT_SIGN_IN:
+          return new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
+              .requestEmail();
+        default:
+          throw new IllegalStateException("Unknown signInOption");
+      }
     }
   }
@@ -365,8 +362,8 @@ public class GoogleSignInPlugin implements MethodCallHandler, FlutterPlugin, Act
         return clientIdIdentifierOverride;
       }
       return context
-                .getResources()
-                .getIdentifier("default_web_client_id", "string", context.getPackageName());
+          .getResources()
+          .getIdentifier("default_web_client_id", "string", context.getPackageName());
     }
     /**
diff --git a/packages/google_sign_in/google_sign_in_android/android/src/test/java/io/flutter/plugins/googlesignin/GoogleSignInTest.java b/packages/google_sign_in/google_sign_in_android/android/src/test/java/io/flutter/plugins/googlesignin/GoogleSignInTest.java
index 563849949..3f15cb9af 100644
--- a/packages/google_sign_in/google_sign_in_android/android/src/test/java/io/flutter/plugins/googlesignin/GoogleSignInTest.java
+++ b/packages/google_sign_in/google_sign_in_android/android/src/test/java/io/flutter/plugins/googlesignin/GoogleSignInTest.java
@@ -47,8 +47,10 @@ public class GoogleSignInTest {
     when(mockRegistrar.messenger()).thenReturn(mockMessenger);
     when(mockRegistrar.context()).thenReturn(mockContext);
     when(mockRegistrar.activity()).thenReturn(mockActivity);
-    when(optionsBuilderFactory.get(GoogleSignInPlugin.OptionsBuilderFactory.DEFAULT_SIGN_IN)).thenReturn(optionsBuilder);
-    when(optionsBuilderFactory.get(GoogleSignInPlugin.OptionsBuilderFactory.DEFAULT_GAMES_SIGN_IN)).thenReturn(optionsBuilder);
+    when(optionsBuilderFactory.get(GoogleSignInPlugin.OptionsBuilderFactory.DEFAULT_SIGN_IN))
+        .thenReturn(optionsBuilder);
+    when(optionsBuilderFactory.get(GoogleSignInPlugin.OptionsBuilderFactory.DEFAULT_GAMES_SIGN_IN))
+        .thenReturn(optionsBuilder);
     plugin = new GoogleSignInPlugin();
     plugin.initInstance(mockRegistrar.messenger(), mockRegistrar.context(), mockGoogleSignIn);
     plugin.setUpRegistrar(mockRegistrar);
DONE

@stuartmorgan-g stuartmorgan-g self-requested a review May 12, 2022 20:24
@stuartmorgan-g
Copy link
Contributor

stuartmorgan-g commented Jun 7, 2022

Sorry, I lost track of the state of this PR. The next step here would be to split the implementation package parts into a new PR. While from a compilation standpoint this would be landable as-is, we don't want to add a new app-facing parameter that doesn't actually work (if someone updates only the app-facing package, which happens more than you might think). So generally we land the implementations, and then the final PR for the app-facing package updates the minimum version of the implementation packages (in this case we only need to rev Android) so that when someone gets the new API they will definitely also get a working implementation of it.

@fbcouch
Copy link
Contributor Author

fbcouch commented Jul 21, 2022

Sorry, I lost track of the state of this PR. The next step here would be to split the implementation package parts into a new PR. While from a compilation standpoint this would be landable as-is, we don't want to add a new app-facing parameter that doesn't actually work (if someone updates only the app-facing package, which happens more than you might think). So generally we land the implementations, and then the final PR for the app-facing package updates the minimum version of the implementation packages (in this case we only need to rev Android) so that when someone gets the new API they will definitely also get a working implementation of it.

Sorry, I haven't had a chance to come back to this in awhile – so you are saying I should separate the google_sign_in_x parts into another separate PR, get that landed, then finally land the changes to google_sign_in itself?

@fbcouch
Copy link
Contributor Author

fbcouch commented Jul 21, 2022

All right assuming that is correct, the platform implementations are here: #6130

@stuartmorgan-g
Copy link
Contributor

so you are saying I should separate the google_sign_in_x parts into another separate PR, get that landed, then finally land the changes to google_sign_in itself?

Yes, that's correct; once the implementation lands, then there will be published versions you can use as the new minimum constraints in the app-facing package.

@stuartmorgan-g
Copy link
Contributor

The platform interface changes have landed and been published, so the implementation parts can now be split out into a new PR.

…ished versions; update google_sign_in changes / changelog / pubspec depenencies
Copy link
Contributor

@stuartmorgan-g stuartmorgan-g left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I got confused about the state and thought this was still waiting on the implementation package PR, and didn't realized it had already been updated since they were landed and published.

LGTM, and sorry this was waiting unnecessarily!

@stuartmorgan-g stuartmorgan-g added autosubmit Merge PR when tree becomes green via auto submit App and removed needs tests labels Sep 22, 2022
@auto-submit auto-submit bot merged commit 88dc5e3 into flutter:main Sep 23, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Sep 23, 2022
adam-harwood pushed a commit to adam-harwood/flutter_plugins that referenced this pull request Nov 3, 2022
mauricioluz pushed a commit to mauricioluz/plugins that referenced this pull request Jan 26, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
autosubmit Merge PR when tree becomes green via auto submit App cla: yes p: google_sign_in
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants