blob: f0092cdedd3e9ea8c16fef17f00630ba09a70d3f [file] [log] [blame]
// Copyright 2019 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:google_sign_in/google_sign_in.dart';
/// Service class for interacting with Google Sign In authentication for Cocoon backend.
///
/// Almost all operations with the plugin can throw an exception and should be caught
/// to prevent this service from crashing.
class GoogleSignInService extends ChangeNotifier {
/// Creates a new [GoogleSignIn].
GoogleSignInService({GoogleSignIn? googleSignIn})
: _googleSignIn = googleSignIn ??
GoogleSignIn(
scopes: _googleScopes,
) {
_googleSignIn.onCurrentUserChanged.listen((GoogleSignInAccount? accountValue) {
// We could decode the idToken here and look at its TTL, but it can be
// revoked (from another website) at any time, so the only reliable way of
// knowing that we're still authenticated is... to monitor the statuses of
// the requests to the server (if they return an error, clear user/log out!)
user = accountValue;
notifyListeners();
});
try {
_googleSignIn.signInSilently();
} on PlatformException catch (error) {
debugPrint('GoogleSignIn error code: ${error.code}');
debugPrint(error.message);
}
}
/// A list of Google API OAuth Scopes this project needs access to.
///
/// Currently, the project shows just basic user profile information
/// when logged in.
///
/// See https://developers.google.com/identity/protocols/googlescopes
static const List<String> _googleScopes = <String>[];
/// The instance of the GoogleSignIn plugin to use.
final GoogleSignIn _googleSignIn;
/// Whether or not the application has been signed in to.
///
/// If the plugin fails, default to unauthenticated.
bool get isAuthenticated {
return user != null;
}
/// The Google Account for the signed in user, null if no user is signed in.
///
/// Read only object with only access to clear client auth tokens.
GoogleSignInAccount? user;
/// Authentication token to be sent to Cocoon Backend to verify API calls.
Future<String> get idToken async {
assert(isAuthenticated, 'Ensure user isAuthenticated before requesting an idToken.');
final GoogleSignInAuthentication? key = await user?.authentication;
final String? idToken = key?.idToken;
assert(idToken != null && idToken.isNotEmpty);
return idToken!;
}
/// Initiate the Google Sign In process.
Future<void> signIn() async {
try {
user = await _googleSignIn.signIn();
notifyListeners();
} on PlatformException catch (error) {
debugPrint('GoogleSignIn error code: ${error.code}');
debugPrint(error.message);
}
}
Future<void> signOut() async {
try {
user = await _googleSignIn.signOut();
notifyListeners();
} on PlatformException catch (error) {
debugPrint('GoogleSignIn error code: ${error.code}');
debugPrint(error.message);
}
}
/// Clears the active user from the service, without calling signOut on the plugin.
///
/// This refreshes the UI of the app, while making it easy for users to re-login.
Future<void> clearUser() async {
user = null;
notifyListeners();
}
}