Skip to content

Migrate to null safety #1

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

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
96 changes: 47 additions & 49 deletions google_sign_in_dart/lib/google_sign_in_dartio.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import 'package:google_sign_in/google_sign_in.dart';
import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart'
as platform;
import 'package:http/http.dart';
import 'package:meta/meta.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:url_launcher/url_launcher.dart';

Expand All @@ -30,16 +29,13 @@ typedef UrlPresenter = void Function(Uri uri);
/// Implementation of the google_sign_in plugin in pure dart.
class GoogleSignInDart extends platform.GoogleSignInPlatform {
GoogleSignInDart._({
@required DataStorage storage,
@required String clientId,
@required UrlPresenter presenter,
String exchangeEndpoint,
String successUrl,
String failUrl,
}) : assert(storage != null),
assert(clientId != null),
assert(presenter != null),
_storage = storage,
required DataStorage storage,
required String clientId,
required UrlPresenter presenter,
String? exchangeEndpoint,
String? successUrl,
String? failUrl,
}) : _storage = storage,
_clientId = clientId,
_presenter = presenter,
_exchangeEndpoint = exchangeEndpoint,
Expand All @@ -52,12 +48,12 @@ class GoogleSignInDart extends platform.GoogleSignInPlatform {
/// the tokens is a secure, long-lived location that is accessible between
/// different invocations of your application.
static Future<void> register({
@required String clientId,
String exchangeEndpoint,
DataStorage storage,
UrlPresenter presenter,
String successUrl,
String failUrl,
required String clientId,
String? exchangeEndpoint,
DataStorage? storage,
UrlPresenter? presenter,
String? successUrl,
String? failUrl,
}) async {
presenter ??= (Uri uri) => launch(uri.toString());

Expand Down Expand Up @@ -87,19 +83,19 @@ class GoogleSignInDart extends platform.GoogleSignInPlatform {
);
}

final String _exchangeEndpoint;
final String? _exchangeEndpoint;
final String _clientId;
final DataStorage _storage;
final String _successUrl;
final String _failUrl;
final String? _successUrl;
final String? _failUrl;

UrlPresenter _presenter;
List<String> _scopes;
String _hostedDomain;
List<String>? _scopes;
String? _hostedDomain;

platform.GoogleSignInTokenData _tokenData;
String _refreshToken;
DateTime _expiresAt;
platform.GoogleSignInTokenData? _tokenData;
String? _refreshToken;
DateTime? _expiresAt;

/// Used by the sign in flow to allow opening of a browser in a platform
/// specific way.
Expand All @@ -109,16 +105,15 @@ class GoogleSignInDart extends platform.GoogleSignInPlatform {
UrlPresenter get presenter => _presenter;

set presenter(UrlPresenter value) {
assert(value != null);
_presenter = value;
}

@override
Future<void> init({
@required String hostedDomain,
String? hostedDomain,
List<String> scopes = const <String>[],
platform.SignInOption signInOption = platform.SignInOption.standard,
String clientId,
String? clientId,
}) async {
assert(clientId == null || clientId == _clientId,
'ClientID ($clientId) does not match the one used to register the plugin $_clientId.');
Expand All @@ -128,7 +123,7 @@ class GoogleSignInDart extends platform.GoogleSignInPlatform {
'Check https://developers.google.com/identity/protocols/googlescopes '
'for a list of valid OAuth 2.0 scopes.');

if (scopes == null || scopes.isEmpty) {
if (scopes.isEmpty) {
_scopes = const <String>['openid', 'email', 'profile'];
} else {
_scopes = scopes;
Expand All @@ -138,7 +133,7 @@ class GoogleSignInDart extends platform.GoogleSignInPlatform {
}

@override
Future<platform.GoogleSignInUserData> signInSilently() async {
Future<platform.GoogleSignInUserData?> signInSilently() async {
if (_haveValidToken) {
return _storage.userData;
} else if (_refreshToken != null) {
Expand All @@ -155,9 +150,9 @@ class GoogleSignInDart extends platform.GoogleSignInPlatform {
}

@override
Future<platform.GoogleSignInUserData> signIn() async {
Future<platform.GoogleSignInUserData?> signIn() async {
if (_haveValidToken) {
final platform.GoogleSignInUserData userData = _storage.userData;
final platform.GoogleSignInUserData? userData = _storage.userData;
if (userData == null) {
await _fetchUserProfile();
}
Expand All @@ -170,21 +165,21 @@ class GoogleSignInDart extends platform.GoogleSignInPlatform {

@override
Future<platform.GoogleSignInTokenData> getTokens(
{String email, bool shouldRecoverAuth}) async {
{required String email, bool? shouldRecoverAuth}) async {
if (_haveValidToken) {
return _tokenData;
return _tokenData!;
} else if (_refreshToken != null) {
// if refreshing the token fails, and shouldRecoverAuth is true, then we
// will prompt the user to login again
try {
await _doTokenRefresh();
return _tokenData;
return _tokenData!;
} catch (_) {}
}

if (shouldRecoverAuth) {
if (shouldRecoverAuth!) {
await _performSignIn(_scopes);
return _tokenData;
return _tokenData!;
} else {
throw PlatformException(
code: GoogleSignInAccount.kUserRecoverableAuthError);
Expand Down Expand Up @@ -219,7 +214,7 @@ class GoogleSignInDart extends platform.GoogleSignInPlatform {
}

@override
Future<void> clearAuthCache({String token}) async {
Future<void> clearAuthCache({String? token}) async {
await _revokeToken();
_storage.clear();
_initFromStore();
Expand All @@ -244,7 +239,8 @@ class GoogleSignInDart extends platform.GoogleSignInPlatform {
Future<void> _revokeToken() async {
if (_haveValidToken) {
await get(
'https://oauth2.googleapis.com/revoke?token=${_tokenData.accessToken}',
Uri.parse(
'https://oauth2.googleapis.com/revoke?token=${_tokenData!.accessToken}'),
headers: <String, String>{
'content-type': 'application/x-www-form-urlencoded'
},
Expand All @@ -254,9 +250,9 @@ class GoogleSignInDart extends platform.GoogleSignInPlatform {

Future<void> _fetchUserProfile() async {
if (_haveValidToken) {
final String token = _tokenData.accessToken;
final String? token = _tokenData!.accessToken;
final Response response = await get(
'https://openidconnect.googleapis.com/v1/userinfo',
Uri.parse('https://openidconnect.googleapis.com/v1/userinfo'),
headers: <String, String>{
'Authorization': 'Bearer $token',
},
Expand All @@ -278,23 +274,23 @@ class GoogleSignInDart extends platform.GoogleSignInPlatform {
}

bool get _haveValidToken {
return _expiresAt != null && DateTime.now().isBefore(_expiresAt);
return _expiresAt != null && DateTime.now().isBefore(_expiresAt!);
}

Future<void> _performSignIn(List<String> scopes) async {
Future<void> _performSignIn(List<String>? scopes) async {
Future<Map<String, dynamic>> future;
if (_exchangeEndpoint != null) {
future = _codeExchangeSignIn(
scope: scopes.join(' '),
scope: scopes!.join(' '),
clientId: _clientId,
hostedDomains: _hostedDomain,
presenter: presenter,
exchangeEndpoint: _exchangeEndpoint,
exchangeEndpoint: _exchangeEndpoint!,
uid: _storage.id,
);
} else {
future = _tokenSignIn(
scope: scopes.join(' '),
scope: scopes!.join(' '),
clientId: _clientId,
hostedDomains: _hostedDomain,
presenter: presenter,
Expand All @@ -318,13 +314,13 @@ class GoogleSignInDart extends platform.GoogleSignInPlatform {
await _fetchUserProfile();
}

Future<void> _doTokenRefresh() async {
Future<Map<String, dynamic>> _doTokenRefresh() async {
assert(_exchangeEndpoint != null);
assert(_refreshToken != null);

final Response response = await post(
_exchangeEndpoint,
body: json.encode(<String, String>{
Uri.parse(_exchangeEndpoint!),
body: json.encode(<String, String?>{
'refreshToken': _refreshToken,
'clientId': _clientId,
}),
Expand All @@ -339,6 +335,8 @@ class GoogleSignInDart extends platform.GoogleSignInPlatform {
} else {
return Future<Map<String, dynamic>>.error(response.body);
}

throw Exception('Error refreshing token');
}

void _initFromStore() {
Expand Down
49 changes: 22 additions & 27 deletions google_sign_in_dart/lib/src/code_exchange_sing_in.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,13 @@ part of '../google_sign_in_dartio.dart';
/// Once the auth code comes back it make a post to [exchangeEndpoint] for
/// to obtain the access and refresh tokens.
Future<Map<String, dynamic>> _codeExchangeSignIn({
@required String clientId,
@required String exchangeEndpoint,
@required String scope,
@required UrlPresenter presenter,
String hostedDomains,
String uid,
required String clientId,
required String exchangeEndpoint,
required String scope,
required UrlPresenter presenter,
String? hostedDomains,
String? uid,
}) async {
assert(clientId != null);
assert(exchangeEndpoint != null);
assert(presenter != null);
assert(scope != null);

final Completer<Map<String, dynamic>> completer =
Completer<Map<String, dynamic>>();

Expand Down Expand Up @@ -84,18 +79,18 @@ Future<Map<String, dynamic>> _codeExchangeSignIn({
}

Future<Map<String, dynamic>> _validateAndExchangeCodeResponse({
@required HttpRequest request,
@required String state,
@required String exchangeEndpoint,
@required String redirectUrl,
@required String clientId,
@required String codeVerifier,
required HttpRequest request,
required String state,
required String exchangeEndpoint,
required String redirectUrl,
required String clientId,
required String codeVerifier,
}) {
final Map<String, String> authResponse = request.requestedUri.queryParameters;
final String returnedState = authResponse['state'];
final String code = authResponse['code'];
final String? returnedState = authResponse['state'];
final String? code = authResponse['code'];

String message;
String? message;
if (state != returnedState) {
message = 'Invalid response from server (state did not match).';
}
Expand Down Expand Up @@ -124,15 +119,15 @@ Future<Map<String, dynamic>> _validateAndExchangeCodeResponse({
}

Future<Map<String, dynamic>> _exchangeCode({
@required String exchangeEndpoint,
@required String redirectUrl,
@required String clientId,
@required String code,
@required String codeVerifier,
required String exchangeEndpoint,
required String redirectUrl,
required String clientId,
required String? code,
required String codeVerifier,
}) async {
final Response response = await post(
exchangeEndpoint,
body: json.encode(<String, String>{
Uri.parse(exchangeEndpoint),
body: json.encode(<String, String?>{
'code': code,
'codeVerifier': codeVerifier,
'clientId': clientId,
Expand Down
5 changes: 1 addition & 4 deletions google_sign_in_dart/lib/src/crypto.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,8 @@ const String _charset =
/// See "Proof Key for Code Exchange by OAuth Public Clients (RFC 7636)
/// <https://tools.ietf.org/html/rfc7636>"
String _generateSecureRandomString(
[Random entropySource, int entropyBytes = 64]) {
[Random? entropySource, int entropyBytes = 64]) {
entropySource ??= Random.secure();
assert(entropySource != null, 'entropySource cannot be null');
assert(entropyBytes != null, 'entropyBytes cannot be null');

final StringBuffer buffer = StringBuffer();
int remainingLength = entropyBytes;
while (remainingLength > 0) {
Expand Down
Loading