Skip to content

[google_sign_in] Redesign API for current identity SDKs - Platform Interface #9454

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
432a627
Initial PoC using CredentialManager
stuartmorgan-g Feb 12, 2025
df1cf87
Pathify everything for local development
stuartmorgan-g Mar 20, 2025
6a1ec7c
Remove method channel implementation
stuartmorgan-g Mar 20, 2025
49342c5
First pass rework of interface, impls, and app-facing API
stuartmorgan-g Mar 20, 2025
eba7a8b
Add nonce support
stuartmorgan-g May 2, 2025
f3d472f
Initial README updates and migration guide
stuartmorgan-g May 2, 2025
728a4f9
Rework Android calls to match recommended practice
stuartmorgan-g May 5, 2025
c165834
Synthesize sign-out event for disconnect
stuartmorgan-g May 5, 2025
dba0f3e
platform interface tests
stuartmorgan-g May 5, 2025
83c7b1d
Simplify Android Pigeon API
stuartmorgan-g May 6, 2025
82c0530
Android Dart unit tests
stuartmorgan-g May 8, 2025
4123b18
iOS Dart unit tests
stuartmorgan-g May 9, 2025
165fb78
Web Dart 'unit' tests, and fix lightweight auth return
stuartmorgan-g May 9, 2025
eda66bb
Update example apps
stuartmorgan-g May 9, 2025
21635a0
Update native unit tests, fix an Obj-C selector name
stuartmorgan-g May 13, 2025
39b7505
Update to recent 1.5 release
stuartmorgan-g May 13, 2025
07fe543
Android native unit tests
stuartmorgan-g May 14, 2025
e6c9f62
README, CHANGELOG, and version updates
stuartmorgan-g May 16, 2025
90a63aa
App-facing Dart tests
stuartmorgan-g May 16, 2025
816f614
Revert unrelated Xcode project changes
stuartmorgan-g May 16, 2025
0d46beb
Analysis fix
stuartmorgan-g May 16, 2025
a0cf078
Revert extension package changes
stuartmorgan-g May 16, 2025
0a134ec
Fix Obj-C warnings
stuartmorgan-g May 16, 2025
1b0d4d1
Missing license
stuartmorgan-g May 16, 2025
8f57604
Analyze fix
stuartmorgan-g May 19, 2025
e786998
Update excerpting
stuartmorgan-g May 19, 2025
78602e8
Merge branch 'main' into google-sign-in-authn-authz-redesign
stuartmorgan-g May 23, 2025
8783b72
Merge branch 'main' into google-sign-in-authn-authz-redesign
stuartmorgan-g May 27, 2025
7140fd0
Remove email scope
stuartmorgan-g May 27, 2025
5a587b4
Web README additions
stuartmorgan-g May 27, 2025
5f78e10
Update stream error handling, update main example
stuartmorgan-g May 27, 2025
a6036b8
Fix lightweight auth null return, and add missing tests
stuartmorgan-g May 28, 2025
9c9923c
Re-add web asserts for scope spaces
stuartmorgan-g May 28, 2025
b44ff39
Remove unused People code
stuartmorgan-g May 28, 2025
8640443
Restructure options slightly
stuartmorgan-g May 28, 2025
86a7a1d
Add TODO issue link
stuartmorgan-g May 28, 2025
4fb7fea
Add activity lifecycle tests
stuartmorgan-g May 28, 2025
563680c
Add authorize param tests
stuartmorgan-g May 28, 2025
dab117f
Test safety check, better README
stuartmorgan-g May 29, 2025
81f59f7
Analyzer
stuartmorgan-g May 29, 2025
6b76be0
Java autoformat
stuartmorgan-g May 29, 2025
9817325
excerpt update
stuartmorgan-g May 29, 2025
20a8fc5
Add stack traces to stream errors
stuartmorgan-g May 29, 2025
d6bd8bc
Handle emulators without sign-in support
stuartmorgan-g May 29, 2025
6766860
Add another missing stack
stuartmorgan-g May 29, 2025
8ad0051
Rework the stream tests to make wasm happy
stuartmorgan-g May 29, 2025
98e55b2
Merge branch 'main' into google-sign-in-authn-authz-redesign
stuartmorgan-g Jun 3, 2025
f36a6c8
Minor iOS review fixes
stuartmorgan-g Jun 4, 2025
2823a54
Add authorizationRequiresUserInteraction
stuartmorgan-g Jun 4, 2025
012a6d7
final variable in example
stuartmorgan-g Jun 5, 2025
86e9d00
Review feedback
stuartmorgan-g Jun 11, 2025
beaa804
Merge branch 'main' into google-sign-in-authn-authz-redesign-p-i
stuartmorgan-g Jun 18, 2025
8f1bf83
Revert non-platform-interface changes
stuartmorgan-g Jun 18, 2025
edc8aed
Exclude platform interface from build-all
stuartmorgan-g Jun 20, 2025
7dbe874
Merge branch 'main' into google-sign-in-authn-authz-redesign-p-i
stuartmorgan-g Jun 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## NEXT
## 3.0.0

* **BREAKING CHANGE**: Overhauls the entire API surface to better abstract the
current set of underlying platform SDKs, and to use structured errors. See
API doc comments for details on the behaviors that platform implementations
must implement.
* Updates minimum supported SDK version to Flutter 3.27/Dart 3.6.

## 2.5.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@

import 'dart:async';

import 'package:flutter/foundation.dart' show visibleForTesting;
import 'package:plugin_platform_interface/plugin_platform_interface.dart';

import 'src/method_channel_google_sign_in.dart';
import 'src/types.dart';

export 'src/method_channel_google_sign_in.dart';
export 'src/types.dart';

/// The interface that implementations of google_sign_in must implement.
Expand All @@ -27,134 +24,151 @@ abstract class GoogleSignInPlatform extends PlatformInterface {

static final Object _token = Object();

/// Only mock implementations should set this to `true`.
/// The instance of [GoogleSignInPlatform] to use.
///
/// Mockito mocks implement this class with `implements` which is forbidden
/// (see class docs). This property provides a backdoor for mocks to skip the
/// verification that the class isn't implemented with `implements`.
@visibleForTesting
@Deprecated('Use MockPlatformInterfaceMixin instead')
bool get isMock => false;

/// The default instance of [GoogleSignInPlatform] to use.
///
/// Platform-specific plugins should override this with their own
/// Platform-implementations should override this with their own
/// platform-specific class that extends [GoogleSignInPlatform] when they
/// register themselves.
///
/// Defaults to [MethodChannelGoogleSignIn].
static GoogleSignInPlatform get instance => _instance;

static GoogleSignInPlatform _instance = MethodChannelGoogleSignIn();
static GoogleSignInPlatform _instance = _PlaceholderImplementation();

// TODO(amirh): Extract common platform interface logic.
// https://github.com/flutter/flutter/issues/43368
static set instance(GoogleSignInPlatform instance) {
if (!instance.isMock) {
PlatformInterface.verify(instance, _token);
}
PlatformInterface.verify(instance, _token);
_instance = instance;
}

/// Initializes the plugin. Deprecated: call [initWithParams] instead.
/// Initializes the plugin with specified [params]. You must call this method
/// before calling other methods.
///
/// The [hostedDomain] argument specifies a hosted domain restriction. By
/// setting this, sign in will be restricted to accounts of the user in the
/// specified domain. By default, the list of accounts will not be restricted.
/// See:
///
/// The list of [scopes] are OAuth scope codes to request when signing in.
/// These scope codes will determine the level of data access that is granted
/// to your application by the user. The full list of available scopes can be
/// found here: <https://developers.google.com/identity/protocols/googlescopes>
/// * [InitParameters]
Future<void> init(InitParameters params);

/// Attempts to sign in without an explicit user intent.
///
/// The [signInOption] determines the user experience. [SigninOption.games] is
/// only supported on Android.
/// This is intended to support the use case where the user might be expected
/// to be signed in, but hasn't explicitly requested sign in, such as when
/// launching an application that is intended to be used while signed in.
///
/// See:
/// https://developers.google.com/identity/sign-in/web/reference#gapiauth2initparams
Future<void> init({
List<String> scopes = const <String>[],
SignInOption signInOption = SignInOption.standard,
String? hostedDomain,
String? clientId,
}) async {
throw UnimplementedError('init() has not been implemented.');
}
/// This may be silent, or may show minimal UI, depending on the platform and
/// the context.
Future<AuthenticationResults?>? attemptLightweightAuthentication(
AttemptLightweightAuthenticationParameters params);

/// Initializes the plugin with specified [params]. You must call this method
/// before calling other methods.
/// Returns true if the platform implementation supports the [authenticate]
/// method.
///
/// See:
/// The default is true, but platforms that cannot support [authenticate] can
/// override this to return false, throw [UnsupportedError] from
/// [authenticate], and provide a different, platform-specific authentication
/// flow.
bool supportsAuthenticate();

/// Signs in with explicit user intent.
///
/// * [SignInInitParameters]
Future<void> initWithParams(SignInInitParameters params) async {
await init(
scopes: params.scopes,
signInOption: params.signInOption,
hostedDomain: params.hostedDomain,
clientId: params.clientId,
);
}
/// This is intended to support the use case where the user has expressed
/// an explicit intent to sign in.
Future<AuthenticationResults> authenticate(AuthenticateParameters params);

/// Attempts to reuse pre-existing credentials to sign in again, without user interaction.
Future<GoogleSignInUserData?> signInSilently() async {
throw UnimplementedError('signInSilently() has not been implemented.');
}
/// Whether or not authorization calls that could show UI must be called from
/// a user interaction, such as a button press, on the current platform.
///
/// Platforms that can fail to show UI without an active user interaction,
/// such as a web implementations that uses popups, should return false.
bool authorizationRequiresUserInteraction();

/// Signs in the user with the options specified to [init].
Future<GoogleSignInUserData?> signIn() async {
throw UnimplementedError('signIn() has not been implemented.');
/// Returns the tokens used to authenticate other API calls from a client.
///
/// This should only return null if prompting would be necessary but [params]
/// do not allow it, otherwise any failure should return an error.
Future<ClientAuthorizationTokenData?> clientAuthorizationTokensForScopes(
ClientAuthorizationTokensForScopesParameters params);

/// Returns the tokens used to authenticate other API calls from a server.
///
/// This should only return null if prompting would be necessary but [params]
/// do not allow it, otherwise any failure should return an error.
Future<ServerAuthorizationTokenData?> serverAuthorizationTokensForScopes(
ServerAuthorizationTokensForScopesParameters params);

/// Signs out previously signed in accounts.
Future<void> signOut(SignOutParams params);

/// Revokes all of the scopes that all signed in users granted, and then signs
/// them out.
Future<void> disconnect(DisconnectParams params);

/// Returns a stream of authentication events.
///
/// If this is not overridden, the app-facing package will assume that the
/// futures returned by [attemptLightweightAuthentication], [authenticate],
/// and [signOut] are the only sources of authentication-related events.
/// Implementations that have other sources should override this and provide
/// a stream with all authentication and sign-out events.
/// These will normally come from asynchronous flows, like the authenticate
/// and signOut methods, as well as potentially from platform-specific methods
/// (such as the Google Sign-In Button Widget from the Web implementation).
///
/// Implementations should never intentionally call `addError` for this
/// stream, and should instead use AuthenticationEventException. This is to
/// ensure via the type system that implementations are always sending
/// [GoogleSignInException] for know failure cases.
Stream<AuthenticationEvent>? get authenticationEvents => null;
}

/// An implementation of GoogleSignInPlatform that throws unimplemented errors,
/// to use as a default instance if no platform implementation has been
/// registered.
class _PlaceholderImplementation extends GoogleSignInPlatform {
@override
Future<void> init(InitParameters params) {
throw UnimplementedError();
}

/// Returns the Tokens used to authenticate other API calls.
Future<GoogleSignInTokenData> getTokens(
{required String email, bool? shouldRecoverAuth}) async {
throw UnimplementedError('getTokens() has not been implemented.');
@override
Future<AuthenticationResults?> attemptLightweightAuthentication(
AttemptLightweightAuthenticationParameters params) {
throw UnimplementedError();
}

/// Signs out the current account from the application.
Future<void> signOut() async {
throw UnimplementedError('signOut() has not been implemented.');
@override
bool supportsAuthenticate() {
throw UnimplementedError();
}

/// Revokes all of the scopes that the user granted.
Future<void> disconnect() async {
throw UnimplementedError('disconnect() has not been implemented.');
@override
Future<AuthenticationResults> authenticate(AuthenticateParameters params) {
throw UnimplementedError();
}

/// Returns whether the current user is currently signed in.
Future<bool> isSignedIn() async {
throw UnimplementedError('isSignedIn() has not been implemented.');
@override
bool authorizationRequiresUserInteraction() {
throw UnimplementedError();
}

/// Clears any cached information that the plugin may be holding on to.
Future<void> clearAuthCache({required String token}) async {
throw UnimplementedError('clearAuthCache() has not been implemented.');
@override
Future<ClientAuthorizationTokenData?> clientAuthorizationTokensForScopes(
ClientAuthorizationTokensForScopesParameters params) {
throw UnimplementedError();
}

/// Requests the user grants additional Oauth [scopes].
///
/// Scopes should come from the full list
/// [here](https://developers.google.com/identity/protocols/googlescopes).
Future<bool> requestScopes(List<String> scopes) async {
throw UnimplementedError('requestScopes() has not been implemented.');
@override
Future<ServerAuthorizationTokenData?> serverAuthorizationTokensForScopes(
ServerAuthorizationTokensForScopesParameters params) {
throw UnimplementedError();
}

/// Checks if the current user has granted access to all the specified [scopes].
///
/// Optionally, an [accessToken] can be passed for applications where a
/// long-lived token may be cached (like the web).
Future<bool> canAccessScopes(
List<String> scopes, {
String? accessToken,
}) async {
throw UnimplementedError('canAccessScopes() has not been implemented.');
@override
Future<void> signOut(SignOutParams params) {
throw UnimplementedError();
}

/// Returns a stream of [GoogleSignInUserData] authentication events.
///
/// These will normally come from asynchronous flows, like the Google Sign-In
/// Button Widget from the Web implementation, and will be funneled directly
/// to the `onCurrentUserChanged` Stream of the plugin.
Stream<GoogleSignInUserData?>? get userDataEvents => null;
@override
Future<void> disconnect(DisconnectParams params) {
throw UnimplementedError();
}
}

This file was deleted.

Loading