Skip to content

Commit

Permalink
Issue authpass#359 fix
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielAlbertSwan committed Apr 3, 2024
1 parent 713c58a commit d940b4d
Show file tree
Hide file tree
Showing 12 changed files with 306 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ import 'package:authpass/utils/platform.dart';
import 'package:extension_google_sign_in_as_googleapis_auth/extension_google_sign_in_as_googleapis_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';
import 'package:googleapis/drive/v3.dart';
import 'package:http/http.dart';
import 'package:logging/logging.dart';
import 'package:string_literal_finder_annotations/string_literal_finder_annotations.dart';

import 'google_sign_in/platform/google_sign_in_platform_windows.dart';

final _logger = Logger('authpass.google_drive_bloc');

@NonNls
Expand All @@ -27,6 +30,10 @@ const _METADATA_KEY_GOOGLE_DRIVE_DATA = 'googledrive.file_metadata';
class GoogleDriveProvider extends CloudStorageProvider
implements CloudStorageCustomLoginButtonAdapter {
GoogleDriveProvider({required this.env, required super.helper}) {
if(AuthPassPlatform.isWindows
|| AuthPassPlatform.isLinux){
GoogleSignInPlatform.instance = GoogleSignInPlatformWindow(secret: env.secrets!.googleClientSecret!);
}
googleSignIn.onCurrentUserChanged
.listen((final account) => _checkAuthentication());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@

import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:flutter_web_auth_2/flutter_web_auth_2.dart';
import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';
import 'package:http/http.dart' as http;
import 'package:rxdart/rxdart.dart';

class GoogleSignInPlatformWindow extends GoogleSignInPlatform {

static const String storageKey = 'GOOGLE_SIGN_IN_AUTH'; // NON-NLS
GoogleSignInPlatformWindow({required this.secret});
FlutterSecureStorage storage = const FlutterSecureStorage();
Uri? url;

Uri? callbackUrlScheme;

SignInInitParameters? params;

BehaviorSubject<GoogleSignInUserData> userData = BehaviorSubject();
String secret;

Map<String, GoogleSignInTokenData> tokens = Map();

@override
Future<bool> canAccessScopes(List<String> scopes, {String? accessToken}) async{
return true;
}

@override
Future<void> clearAuthCache({required String token}) async{
return storage.delete(key: storageKey);
}

@override
Future<void> disconnect() async{
return;
}

@override
Future<GoogleSignInTokenData> getTokens({required String email, bool? shouldRecoverAuth}) async {
return tokens[email]!;
}

@override
Future<void> init({List<String> scopes = const <String>[], SignInOption signInOption = SignInOption.standard, String? hostedDomain, String? clientId}) async{
return initWithParams(SignInInitParameters(
signInOption: signInOption,
scopes: scopes,
hostedDomain: hostedDomain,
clientId: clientId,
));
}
Future<int> getUnusedPort(InternetAddress address) {
return ServerSocket.bind(address, 0).then((socket) {
var port = socket.port;
socket.close();
return port;
});
}
@override
Future<void> initWithParams(SignInInitParameters params) async {
try {
if (await storage.containsKey(key: storageKey)) {
var mailStorage = await storage.read(key: storageKey);
var mails = jsonDecode(mailStorage!);
final List<dynamic> mailList = mails as List<dynamic>;
for (final mail in mailList) {
tokens[mail as String] = GoogleSignInTokenData(accessToken: await storage.read(
key: '$storageKey.$mail.accessToken'),// NON-NLS
// NON-NLS
idToken: await storage.read(key: '$storageKey.$mail.idToken'), // NON-NLS
// NON-NLS
serverAuthCode: await storage.read(
key: '$storageKey.$mail.serverAuthCode')); // NON-NLS
}
}
}catch(ex){
//ignore
}
final freePort = await getUnusedPort(InternetAddress.anyIPv4);
callbackUrlScheme = Uri(scheme: 'http', host: 'localhost', port: freePort);

url = Uri.https('accounts.google.com', '/o/oauth2/v2/auth', {
'response_type': 'code',
'client_id': params.clientId,
'redirect_uri': callbackUrlScheme.toString(),
'scope': '${params.scopes.join(' ')} https://www.googleapis.com/auth/userinfo.email',
});

this.params = params;
}

@override
bool get isMock => false;

@override
Future<bool> isSignedIn() async{
return tokens.isNotEmpty;
}

@override
Future<bool> requestScopes(List<String> scopes) async {
return true;
}

@override
Future<GoogleSignInUserData?> signIn() async {
if(url == null
|| callbackUrlScheme == null
|| params == null){
throw Exception('call init first');
}
final result = await FlutterWebAuth2.authenticate(url: url.toString(), callbackUrlScheme: callbackUrlScheme.toString());
final code = Uri.parse(result).queryParameters['code']; // NON-NLS

// Construct an Uri to Google's oauth2 endpoint
final tokenUrl = Uri.https('www.googleapis.com', 'oauth2/v4/token'); // NON-NLS

// Use this code to get an access token
final response = await http.post(tokenUrl, body: {
'client_id': params!.clientId,// NON-NLS
'client_secret': secret,// NON-NLS
'redirect_uri': callbackUrlScheme.toString(),// NON-NLS
'grant_type': 'authorization_code',// NON-NLS
'code': code,// NON-NLS
});

// Get the access token from the response
final json = jsonDecode(response.body);
final accessToken = json['access_token'] as String;// NON-NLS
final id = json['id_token'] as String;// NON-NLS
//https://openidconnect.googleapis.com/v1/userinfo

final userInfoUrl = Uri.https('openidconnect.googleapis.com', 'v1/userinfo', {
'access_token' : accessToken
});
final userresp = await http.post(userInfoUrl);
final userInfo = jsonDecode(userresp.body);
final email = userInfo['email'] as String;// NON-NLS

tokens[email] = GoogleSignInTokenData(accessToken: accessToken, serverAuthCode: code);
await writeStorage();
var luserData = GoogleSignInUserData(email: email, id: UniqueKey().toString(), displayName: email, idToken: id, serverAuthCode: code);
userData.add(luserData);
return luserData;
}

@override
Future<GoogleSignInUserData?> signInSilently() async {
var email = tokens.keys.firstOrNull;
if(email != null){
return GoogleSignInUserData(email: email, id: UniqueKey().toString(), displayName: email, idToken: tokens[email]!.idToken, serverAuthCode: tokens[email]!.serverAuthCode);

}else{
return null;
}
}

@override
Future<void> signOut() async{
tokens.clear();
await writeStorage();
}

Future<void> writeStorage() async {
await storage.write(key: storageKey, value: jsonEncode(List.from(tokens.keys)));
tokens.forEach((key, value) async {
await storage.write(key: '$storageKey.$key.accessToken', value: value.accessToken); // NON-NLS
await storage.write(key: '$storageKey.$key.idToken', value: value.idToken); // NON-NLS
await storage.write(key: '$storageKey.$key.serverAuthCode', value: value.serverAuthCode); // NON-NLS
});
}

@override
Stream<GoogleSignInUserData?>? get userDataEvents => userData.stream;

}
8 changes: 8 additions & 0 deletions authpass/linux/flutter/generated_plugin_registrant.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
#include <argon2_ffi/argon2_ffi_plugin.h>
#include <biometric_storage/biometric_storage_plugin.h>
#include <file_selector_linux/file_selector_plugin.h>
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
#include <hotkey_manager/hotkey_manager_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
#include <window_manager/window_manager_plugin.h>
#include <window_to_front/window_to_front_plugin.h>

void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) argon2_ffi_registrar =
Expand All @@ -23,6 +25,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin");
flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar);
g_autoptr(FlPluginRegistrar) hotkey_manager_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "HotkeyManagerPlugin");
hotkey_manager_plugin_register_with_registrar(hotkey_manager_registrar);
Expand All @@ -32,4 +37,7 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) window_manager_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin");
window_manager_plugin_register_with_registrar(window_manager_registrar);
g_autoptr(FlPluginRegistrar) window_to_front_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "WindowToFrontPlugin");
window_to_front_plugin_register_with_registrar(window_to_front_registrar);
}
2 changes: 2 additions & 0 deletions authpass/linux/flutter/generated_plugins.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ list(APPEND FLUTTER_PLUGIN_LIST
argon2_ffi
biometric_storage
file_selector_linux
flutter_secure_storage_linux
hotkey_manager
url_launcher_linux
window_manager
window_to_front
)

list(APPEND FLUTTER_FFI_PLUGIN_LIST
Expand Down
6 changes: 6 additions & 0 deletions authpass/macos/Flutter/GeneratedPluginRegistrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import biometric_storage
import device_info_plus
import file_picker_writable
import file_selector_macos
import flutter_secure_storage_macos
import flutter_web_auth_2
import google_sign_in_ios
import hotkey_manager
import just_audio
Expand All @@ -24,6 +26,7 @@ import url_launcher_macos
import video_player_avfoundation
import wakelock_plus
import window_manager
import window_to_front

func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
Argon2FfiPlugin.register(with: registry.registrar(forPlugin: "Argon2FfiPlugin"))
Expand All @@ -32,6 +35,8 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
FilePickerWritablePlugin.register(with: registry.registrar(forPlugin: "FilePickerWritablePlugin"))
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
FlutterWebAuth2Plugin.register(with: registry.registrar(forPlugin: "FlutterWebAuth2Plugin"))
FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin"))
HotkeyManagerPlugin.register(with: registry.registrar(forPlugin: "HotkeyManagerPlugin"))
JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin"))
Expand All @@ -45,4 +50,5 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin"))
WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))
WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin"))
WindowToFrontPlugin.register(with: registry.registrar(forPlugin: "WindowToFrontPlugin"))
}
74 changes: 73 additions & 1 deletion authpass/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,54 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.6.19"
flutter_secure_storage:
dependency: "direct main"
description:
name: flutter_secure_storage
sha256: ffdbb60130e4665d2af814a0267c481bcf522c41ae2e43caf69fa0146876d685
url: "https://pub.dev"
source: hosted
version: "9.0.0"
flutter_secure_storage_linux:
dependency: transitive
description:
name: flutter_secure_storage_linux
sha256: "3d5032e314774ee0e1a7d0a9f5e2793486f0dff2dd9ef5a23f4e3fb2a0ae6a9e"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
flutter_secure_storage_macos:
dependency: transitive
description:
name: flutter_secure_storage_macos
sha256: bd33935b4b628abd0b86c8ca20655c5b36275c3a3f5194769a7b3f37c905369c
url: "https://pub.dev"
source: hosted
version: "3.0.1"
flutter_secure_storage_platform_interface:
dependency: transitive
description:
name: flutter_secure_storage_platform_interface
sha256: "0d4d3a5dd4db28c96ae414d7ba3b8422fd735a8255642774803b2532c9a61d7e"
url: "https://pub.dev"
source: hosted
version: "1.0.2"
flutter_secure_storage_web:
dependency: transitive
description:
name: flutter_secure_storage_web
sha256: "30f84f102df9dcdaa2241866a958c2ec976902ebdaa8883fbfe525f1f2f3cf20"
url: "https://pub.dev"
source: hosted
version: "1.1.2"
flutter_secure_storage_windows:
dependency: transitive
description:
name: flutter_secure_storage_windows
sha256: "5809c66f9dd3b4b93b0a6e2e8561539405322ee767ac2f64d084e2ab5429d108"
url: "https://pub.dev"
source: hosted
version: "3.0.0"
flutter_speed_dial:
dependency: "direct main"
description:
Expand Down Expand Up @@ -732,6 +780,22 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_web_auth_2:
dependency: "direct main"
description:
name: flutter_web_auth_2
sha256: "3ea3a0cc539ca74319f4f2f7484f62742fe5b2ff9a0fca37575426d6e6f07901"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
flutter_web_auth_2_platform_interface:
dependency: transitive
description:
name: flutter_web_auth_2_platform_interface
sha256: e8669e262005a8354389ba2971f0fc1c36188481234ff50d013aaf993f30f739
url: "https://pub.dev"
source: hosted
version: "3.1.0"
flutter_web_plugins:
dependency: transitive
description: flutter
Expand Down Expand Up @@ -896,7 +960,7 @@ packages:
source: hosted
version: "5.7.4"
google_sign_in_platform_interface:
dependency: transitive
dependency: "direct main"
description:
name: google_sign_in_platform_interface
sha256: "1f6e5787d7a120cc0359ddf315c92309069171306242e181c09472d1b00a2971"
Expand Down Expand Up @@ -2127,6 +2191,14 @@ packages:
url: "https://github.com/authpass/window_manager.git"
source: git
version: "0.0.3"
window_to_front:
dependency: transitive
description:
name: window_to_front
sha256: "7aef379752b7190c10479e12b5fd7c0b9d92adc96817d9e96c59937929512aee"
url: "https://pub.dev"
source: hosted
version: "0.0.3"
winsparkle_flutter:
dependency: "direct main"
description:
Expand Down
3 changes: 3 additions & 0 deletions authpass/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ dependencies:
git:
url: https://github.com/authpass/window_manager.git
ref: remove-web
flutter_web_auth_2: ^3.1.1
google_sign_in_platform_interface: ^2.4.5
flutter_secure_storage: ^9.0.0

dev_dependencies:
integration_test:
Expand Down

0 comments on commit d940b4d

Please sign in to comment.