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

Commit 5304424

Browse files
authored
[google_sign_in_web] Migrate to the GIS SDK. (#6921)
* [google_sign_in_web] Migrate to GIS SDK. * include_granted_scopes in requestScopes call. * Remove the old JS-interop layer. * Introduce a mockable GisSdkClient for tests. * Split the people utils. * Delete tests for the old code. * Add some tests for the new code. * More utils_test.dart * Make jsifyAs reusable. * Ignore the tester in utils_test.dart * Make Clients overridable, and some renaming. * Test people.dart * Make autoDetectedClientId more testable. * Add mockito. * Comment about where to better split the code so GisSdkClient is testable too. * Add google_sign_in_web_test.dart (and its mocks) * dart format * Log only in debug. * Sync min sdk with package gis_web * Add migration notes to the README. * When the user is known upon signIn, remove friction. * Do not ask for user selection again in the authorization popup * Pass the email of the known user as a hint to the signIn method * Address PR comments / checks. * Update migration guide after comments from testers. * Update README.md * Remove package:jose from tests. * Rename to Vincent Adultman * _isJsSdkLoaded -> _jsSdkLoadedFuture * Remove idToken comment. * Link issue to split mocking better. * Remove dependency in package:jwt_decoder * Remove unneeded cast call.
1 parent ea048a2 commit 5304424

33 files changed

+1588
-1614
lines changed

packages/google_sign_in/google_sign_in_web/CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
## NEXT
1+
## 0.11.0
22

3+
* **Breaking Change:** Migrates JS-interop to `package:google_identity_services_web`
4+
* Uses the new Google Identity Authentication and Authorization JS SDKs. [Docs](https://developers.google.com/identity).
5+
* Added "Migrating to v0.11" section to the `README.md`.
36
* Updates minimum Flutter version to 3.0.
47

58
## 0.10.2+1

packages/google_sign_in/google_sign_in_web/README.md

Lines changed: 124 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,122 @@
22

33
The web implementation of [google_sign_in](https://pub.dev/packages/google_sign_in)
44

5+
## Migrating to v0.11 (Google Identity Services)
6+
7+
The `google_sign_in_web` plugin is backed by the new Google Identity Services
8+
(GIS) JS SDK since version 0.11.0.
9+
10+
The GIS SDK is used both for [Authentication](https://developers.google.com/identity/gsi/web/guides/overview)
11+
and [Authorization](https://developers.google.com/identity/oauth2/web/guides/overview) flows.
12+
13+
The GIS SDK, however, doesn't behave exactly like the one being deprecated.
14+
Some concepts have experienced pretty drastic changes, and that's why this
15+
plugin required a major version update.
16+
17+
### Differences between Google Identity Services SDK and Google Sign-In for Web SDK.
18+
19+
The **Google Sign-In JavaScript for Web JS SDK** is set to be deprecated after
20+
March 31, 2023. **Google Identity Services (GIS) SDK** is the new solution to
21+
quickly and easily sign users into your app suing their Google accounts.
22+
23+
* In the GIS SDK, Authentication and Authorization are now two separate concerns.
24+
* Authentication (information about the current user) flows will not
25+
authorize `scopes` anymore.
26+
* Authorization (permissions for the app to access certain user information)
27+
flows will not return authentication information.
28+
* The GIS SDK no longer has direct access to previously-seen users upon initialization.
29+
* `signInSilently` now displays the One Tap UX for web.
30+
* The GIS SDK only provides an `idToken` (JWT-encoded info) when the user
31+
successfully completes an authentication flow. In the plugin: `signInSilently`.
32+
* The plugin `signIn` method uses the Oauth "Implicit Flow" to Authorize the requested `scopes`.
33+
* If the user hasn't `signInSilently`, they'll have to sign in as a first step
34+
of the Authorization popup flow.
35+
* If `signInSilently` was unsuccessful, the plugin will add extra `scopes` to
36+
`signIn` and retrieve basic Profile information from the People API via a
37+
REST call immediately after a successful authorization. In this case, the
38+
`idToken` field of the `GoogleSignInUserData` will always be null.
39+
* The GIS SDK no longer handles sign-in state and user sessions, it only provides
40+
Authentication credentials for the moment the user did authenticate.
41+
* The GIS SDK no longer is able to renew Authorization sessions on the web.
42+
Once the token expires, API requests will begin to fail with unauthorized,
43+
and user Authorization is required again.
44+
45+
See more differences in the following migration guides:
46+
47+
* Authentication > [Migrating from Google Sign-In](https://developers.google.com/identity/gsi/web/guides/migration)
48+
* Authorization > [Migrate to Google Identity Services](https://developers.google.com/identity/oauth2/web/guides/migration-to-gis)
49+
50+
### New use cases to take into account in your app
51+
52+
#### Enable access to the People API for your GCP project
53+
54+
Since the GIS SDK is separating Authentication from Authorization, the
55+
[Oauth Implicit pop-up flow](https://developers.google.com/identity/oauth2/web/guides/use-token-model)
56+
used to Authorize scopes does **not** return any Authentication information
57+
anymore (user credential / `idToken`).
58+
59+
If the plugin is not able to Authenticate an user from `signInSilently` (the
60+
OneTap UX flow), it'll add extra `scopes` to those requested by the programmer
61+
so it can perform a [People API request](https://developers.google.com/people/api/rest/v1/people/get)
62+
to retrieve basic profile information about the user that is signed-in.
63+
64+
The information retrieved from the People API is used to complete data for the
65+
[`GoogleSignInAccount`](https://pub.dev/documentation/google_sign_in/latest/google_sign_in/GoogleSignInAccount-class.html)
66+
object that is returned after `signIn` completes successfully.
67+
68+
#### `signInSilently` always returns `null`
69+
70+
Previous versions of this plugin were able to return a `GoogleSignInAccount`
71+
object that was fully populated (signed-in and authorized) from `signInSilently`
72+
because the former SDK equated "is authenticated" and "is authorized".
73+
74+
With the GIS SDK, `signInSilently` only deals with user Authentication, so users
75+
retrieved "silently" will only contain an `idToken`, but not an `accessToken`.
76+
77+
Only after `signIn` or `requestScopes`, a user will be fully formed.
78+
79+
The GIS-backed plugin always returns `null` from `signInSilently`, to force apps
80+
that expect the former logic to perform a full `signIn`, which will result in a
81+
fully Authenticated and Authorized user, and making this migration easier.
82+
83+
#### `idToken` is `null` in the `GoogleSignInAccount` object after `signIn`
84+
85+
Since the GIS SDK is separating Authentication and Authorization, when a user
86+
fails to Authenticate through `signInSilently` and the plugin performs the
87+
fallback request to the People API described above,
88+
the returned `GoogleSignInUserData` object will contain basic profile information
89+
(name, email, photo, ID), but its `idToken` will be `null`.
90+
91+
This is because JWT are cryptographically signed by Google Identity Services, and
92+
this plugin won't spoof that signature when it retrieves the information from a
93+
simple REST request.
94+
95+
#### User Sessions
96+
97+
Since the GIS SDK does _not_ manage user sessions anymore, apps that relied on
98+
this feature might break.
99+
100+
If long-lived sessions are required, consider using some user authentication
101+
system that supports Google Sign In as a federated Authentication provider,
102+
like [Firebase Auth](https://firebase.google.com/docs/auth/flutter/federated-auth#google),
103+
or similar.
104+
105+
#### Expired / Invalid Authorization Tokens
106+
107+
Since the GIS SDK does _not_ auto-renew authorization tokens anymore, it's now
108+
the responsibility of your app to do so.
109+
110+
Apps now need to monitor the status code of their REST API requests for response
111+
codes different to `200`. For example:
112+
113+
* `401`: Missing or invalid access token.
114+
* `403`: Expired access token.
115+
116+
In either case, your app needs to prompt the end user to `signIn` or
117+
`requestScopes`, to interactively renew the token.
118+
119+
The GIS SDK limits authorization token duration to one hour (3600 seconds).
120+
5121
## Usage
6122

7123
### Import the package
@@ -12,7 +128,7 @@ normally. This package will be automatically included in your app when you do.
12128

13129
### Web integration
14130

15-
First, go through the instructions [here](https://developers.google.com/identity/sign-in/web/sign-in#before_you_begin) to create your Google Sign-In OAuth client ID.
131+
First, go through the instructions [here](https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid) to create your Google Sign-In OAuth client ID.
16132

17133
On your `web/index.html` file, add the following `meta` tag, somewhere in the
18134
`head` of the document:
@@ -29,7 +145,10 @@ You can do this by:
29145
2. Clicking "Edit" in the OAuth 2.0 Web application client that you created above.
30146
3. Adding the URIs you want to the **Authorized JavaScript origins**.
31147

32-
For local development, may add a `localhost` entry, for example: `http://localhost:7357`
148+
For local development, you must add two `localhost` entries:
149+
150+
* `http://localhost` and
151+
* `http://localhost:7357` (or any port that is free in your machine)
33152

34153
#### Starting flutter in http://localhost:7357
35154

@@ -45,48 +164,19 @@ flutter run -d chrome --web-hostname localhost --web-port 7357
45164

46165
Read the rest of the instructions if you need to add extra APIs (like Google People API).
47166

48-
49167
### Using the plugin
50-
Add the following import to your Dart code:
51-
52-
```dart
53-
import 'package:google_sign_in/google_sign_in.dart';
54-
```
55-
56-
Initialize GoogleSignIn with the scopes you want:
57168

58-
```dart
59-
GoogleSignIn _googleSignIn = GoogleSignIn(
60-
scopes: [
61-
'email',
62-
'https://www.googleapis.com/auth/contacts.readonly',
63-
],
64-
);
65-
```
66-
67-
[Full list of available scopes](https://developers.google.com/identity/protocols/googlescopes).
68-
69-
Note that the `serverClientId` parameter of the `GoogleSignIn` constructor is not supported on Web.
169+
See the [**Usage** instructions of `package:google_sign_in`](https://pub.dev/packages/google_sign_in#usage)
70170

71-
You can now use the `GoogleSignIn` class to authenticate in your Dart code, e.g.
72-
73-
```dart
74-
Future<void> _handleSignIn() async {
75-
try {
76-
await _googleSignIn.signIn();
77-
} catch (error) {
78-
print(error);
79-
}
80-
}
81-
```
171+
Note that the **`serverClientId` parameter of the `GoogleSignIn` constructor is not supported on Web.**
82172

83173
## Example
84174

85175
Find the example wiring in the [Google sign-in example application](https://github.com/flutter/plugins/blob/main/packages/google_sign_in/google_sign_in/example/lib/main.dart).
86176

87177
## API details
88178

89-
See the [google_sign_in.dart](https://github.com/flutter/plugins/blob/main/packages/google_sign_in/google_sign_in/lib/google_sign_in.dart) for more API details.
179+
See [google_sign_in.dart](https://github.com/flutter/plugins/blob/main/packages/google_sign_in/google_sign_in/lib/google_sign_in.dart) for more API details.
90180

91181
## Contributions and Testing
92182

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
targets:
2+
$default:
3+
sources:
4+
- integration_test/*.dart
5+
- lib/$lib$
6+
- $package$

0 commit comments

Comments
 (0)