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

Commit 8c55b95

Browse files
committed
Add google_sign_in_web plugin.
1 parent 1b5eae5 commit 8c55b95

13 files changed

Lines changed: 1346 additions & 0 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## 1.0.0
2+
3+
* Flutter for web initial release
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
Copyright 2016, the Flutter project authors. All rights reserved.
2+
Redistribution and use in source and binary forms, with or without
3+
modification, are permitted provided that the following conditions are
4+
met:
5+
6+
* Redistributions of source code must retain the above copyright
7+
notice, this list of conditions and the following disclaimer.
8+
* Redistributions in binary form must reproduce the above
9+
copyright notice, this list of conditions and the following
10+
disclaimer in the documentation and/or other materials provided
11+
with the distribution.
12+
* Neither the name of Google Inc. nor the names of its
13+
contributors may be used to endorse or promote products derived
14+
from this software without specific prior written permission.
15+
16+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# google_sign_in_web
2+
3+
The web implementation of [google_sign_in](https://pub.dev/google_sign_in/google_sign_in)
4+
5+
## Web integration
6+
7+
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.
8+
9+
On your `web/index.html` file, add the following `meta` tag, somewhere in the
10+
`head` of the document:
11+
12+
```
13+
<meta name="google-signin-client_id" content="YOUR_GOOGLE_SIGN_IN_OAUTH_CLIENT_ID.apps.googleusercontent.com">
14+
```
15+
16+
Read the rest of the instructions if you need to add extra APIs (like Google People API).
17+
18+
19+
## Usage
20+
21+
### Import the package
22+
To use this plugin, follow the [plugin installation instructions](https://pub.dartlang.org/packages/google_sign_in#pub-pkg-tab-installing).
23+
24+
### Use the plugin
25+
Add the following import to your Dart code:
26+
27+
```dart
28+
import 'package:google_sign_in/google_sign_in.dart';
29+
```
30+
31+
Initialize GoogleSignIn with the scopes you want:
32+
33+
```dart
34+
GoogleSignIn _googleSignIn = GoogleSignIn(
35+
scopes: [
36+
'email',
37+
'https://www.googleapis.com/auth/contacts.readonly',
38+
],
39+
);
40+
```
41+
[Full list of available scopes](https://developers.google.com/identity/protocols/googlescopes).
42+
43+
You can now use the `GoogleSignIn` class to authenticate in your Dart code, e.g.
44+
45+
```dart
46+
Future<void> _handleSignIn() async {
47+
try {
48+
await _googleSignIn.signIn();
49+
} catch (error) {
50+
print(error);
51+
}
52+
}
53+
```
54+
55+
## Example
56+
57+
Find the example wiring in the [Google sign-in example application](https://github.com/flutter/plugins/blob/master/packages/google_sign_in/google_sign_in/example/lib/main.dart).
58+
59+
## API details
60+
61+
See the [google_sign_in.dart](https://github.com/flutter/plugins/blob/master/packages/google_sign_in/google_sign_in/lib/google_sign_in.dart) for more API details.
62+
63+
## Issues and feedback
64+
65+
Please file [issues](https://github.com/flutter/flutter/issues/new)
66+
to send feedback or report a bug. Thank you!
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
// Copyright 2017 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'dart:async';
6+
import 'dart:html' as html;
7+
8+
import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';
9+
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
10+
import 'package:js/js.dart';
11+
import 'package:meta/meta.dart';
12+
13+
import 'src/generated/gapiauth2.dart' as auth2;
14+
// TODO: Remove once this lands https://github.com/dart-lang/language/issues/671
15+
import 'src/generated/gapiauth2.dart' show GoogleAuthExtensions;
16+
import 'src/load_gapi.dart' as gapi;
17+
import 'src/utils.dart' show gapiUserToPluginUserData;
18+
19+
const String _kClientIdMetaSelector = 'meta[name=google-signin-client_id]';
20+
const String _kClientIdAttributeName = 'content';
21+
22+
@visibleForTesting
23+
String gapiUrl = 'https://apis.google.com/js/platform.js';
24+
25+
/// Implementation of the google_sign_in plugin for Web
26+
class GoogleSignInPlugin extends GoogleSignInPlatform {
27+
GoogleSignInPlugin() {
28+
_autoDetectedClientId = html
29+
.querySelector(_kClientIdMetaSelector)
30+
?.getAttribute(_kClientIdAttributeName);
31+
32+
_isGapiInitialized = gapi.inject(gapiUrl).then((_) => gapi.init()).then((_) {
33+
isInitialized = true;
34+
});
35+
}
36+
37+
Future<void> _isGapiInitialized;
38+
39+
@visibleForTesting
40+
Future<void> get isInitializing => _isGapiInitialized;
41+
@visibleForTesting
42+
bool isInitialized;
43+
44+
String _autoDetectedClientId;
45+
FutureOr<auth2.GoogleUser> _lastSeenUser;
46+
47+
static void registerWith(Registrar registrar) {
48+
GoogleSignInPlatform.instance = GoogleSignInPlugin();
49+
}
50+
51+
@override
52+
Future<void> init(
53+
{@required String hostedDomain,
54+
List<String> scopes = const <String>[],
55+
SignInOption signInOption = SignInOption.standard,
56+
String clientId}) async {
57+
final String appClientId = clientId ?? _autoDetectedClientId;
58+
assert(
59+
appClientId != null,
60+
'ClientID not set. Either set it on a '
61+
'<meta name="google-signin-client_id" content="CLIENT_ID" /> tag,'
62+
' or pass clientId when calling init()');
63+
64+
await _isGapiInitialized;
65+
66+
// This init returns an user, so let's wait for its future
67+
final auth2.GoogleAuth auth = auth2.init(auth2.ClientConfig(
68+
hosted_domain: hostedDomain,
69+
// The js lib wants a space-separated list of values
70+
scope: scopes.join(' '),
71+
client_id: appClientId,
72+
));
73+
74+
// Subscribe to changes in the auth user, and cache the latest seen for signInSilently
75+
final Completer<auth2.GoogleUser> initUserCompleter =
76+
Completer<auth2.GoogleUser>();
77+
78+
auth.currentUser.listen(allowInterop((auth2.GoogleUser nextUser) {
79+
if (!initUserCompleter.isCompleted) {
80+
initUserCompleter.complete(nextUser);
81+
} else {
82+
_lastSeenUser = nextUser;
83+
}
84+
}));
85+
_lastSeenUser = initUserCompleter.future;
86+
87+
return null;
88+
}
89+
90+
@override
91+
Future<GoogleSignInUserData> signInSilently() async {
92+
await _isGapiInitialized;
93+
94+
return gapiUserToPluginUserData(await _lastSeenUser);
95+
}
96+
97+
@override
98+
Future<GoogleSignInUserData> signIn() async {
99+
await _isGapiInitialized;
100+
101+
return gapiUserToPluginUserData(await auth2.getAuthInstance().signIn());
102+
}
103+
104+
@override
105+
Future<GoogleSignInTokenData> getTokens(
106+
{@required String email, bool shouldRecoverAuth}) async {
107+
await _isGapiInitialized;
108+
109+
final auth2.GoogleUser currentUser =
110+
auth2.getAuthInstance()?.currentUser?.get();
111+
final auth2.AuthResponse response = currentUser.getAuthResponse();
112+
113+
return GoogleSignInTokenData(
114+
idToken: response.id_token, accessToken: response.access_token);
115+
}
116+
117+
@override
118+
Future<void> signOut() async {
119+
await _isGapiInitialized;
120+
121+
return auth2.getAuthInstance().signOut();
122+
}
123+
124+
@override
125+
Future<void> disconnect() async {
126+
await _isGapiInitialized;
127+
128+
final auth2.GoogleUser currentUser =
129+
auth2.getAuthInstance()?.currentUser?.get();
130+
return currentUser.disconnect();
131+
}
132+
133+
@override
134+
Future<bool> isSignedIn() async {
135+
await _isGapiInitialized;
136+
137+
final auth2.GoogleUser currentUser =
138+
auth2.getAuthInstance()?.currentUser?.get();
139+
return currentUser.isSignedIn();
140+
}
141+
142+
@override
143+
Future<void> clearAuthCache({String token}) async {
144+
await _isGapiInitialized;
145+
146+
_lastSeenUser = null;
147+
return auth2.getAuthInstance().disconnect();
148+
}
149+
}

0 commit comments

Comments
 (0)