Revert "Use flutter_web_auth instead of our own OAuth mechanism"

This reverts commit 763cbf8493c610dec0e7e344bee40ad331e7a272.
This reverts commit ddad699b259bafe6c7ed630e7afc2eb38b7825e6.

This is causing way too many problems -

On Android with GitHub we occasionally get a User Cancelled exception.
On iOS this doesn't work < ios11

I prefer keeping my way till then. Even though it doesn't support
KeepAlive on Android.
This commit is contained in:
Vishesh Handa
2020-06-10 11:46:55 +02:00
parent 783dbaa505
commit 66a76a0767
11 changed files with 170 additions and 80 deletions

View File

@ -53,12 +53,15 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name="com.linusu.flutter_web_auth.CallbackActivity"> <activity
android:name=".UriReceiverActivity"
android:parentActivityName=".MainActivity">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="gitjournal" /> <data android:scheme="gitjournal" android:host="login.oauth2" />
<!-- Triggering URI would be gitjournal://login.oauth2 -->
</intent-filter> </intent-filter>
</activity> </activity>

View File

@ -0,0 +1,35 @@
package io.gitjournal.gitjournal;
import android.os.Bundle;
import android.util.Log;
import android.app.Activity;
import android.net.*;
import android.content.Intent;
import java.util.HashMap;
import java.util.Map;
public class UriReceiverActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Uri data = getIntent().getData();
Map<String, Object> map = new HashMap<>();
map.put("URL", data.toString());
MainActivity.channel.invokeMethod("onURL", map);
// Now that all data has been sent back to Dart-land, we should re-open the Flutter
// activity. Due to the manifest-setting of the MainActivity ("singleTop), only a single
// instance will exist, popping the old one back up and destroying the preceding
// activities on the backstack, such as the custom tab.
// Flags taken from how the AppAuth-library accomplishes the same thing
Intent mainIntent = new Intent(this, MainActivity.class);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(mainIntent);
finish();
}
}

View File

@ -1,5 +1,4 @@
buildscript { buildscript {
ext.kotlin_version = '1.3.50'
repositories { repositories {
google() google()
jcenter() jcenter()
@ -11,7 +10,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.5.0' classpath 'com.android.tools.build:gradle:3.3.2'
classpath 'com.google.gms:google-services:3.2.1' classpath 'com.google.gms:google-services:3.2.1'
classpath 'io.fabric.tools:gradle:1.+' classpath 'io.fabric.tools:gradle:1.+'
} }

View File

@ -426,4 +426,17 @@ bool handleError(FlutterResult result, int err) {
} }
} }
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
NSLog(@"openUrl called with url %@", url);
for (NSString *key in [options allKeys]) {
NSLog(@". %@: %@", key, [options objectForKey:key]);
}
NSDictionary *args = @{@"URL": [url absoluteString]};
[gitChannel invokeMethod:@"onURL" arguments:args];
return true;
}
@end @end

View File

@ -5,7 +5,8 @@ import 'package:flutter/foundation.dart';
typedef OAuthCallback = void Function(GitHostException); typedef OAuthCallback = void Function(GitHostException);
abstract class GitHost { abstract class GitHost {
Future<void> init(); void init(OAuthCallback oAuthCallback);
Future launchOAuthScreen();
Future<UserInfo> getUserInfo(); Future<UserInfo> getUserInfo();
Future<List<GitHostRepo>> listRepos(); Future<List<GitHostRepo>> listRepos();

View File

@ -2,8 +2,9 @@ import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:flutter_web_auth/flutter_web_auth.dart'; import 'package:url_launcher/url_launcher.dart';
import 'package:gitjournal/utils/logger.dart'; import 'package:gitjournal/utils/logger.dart';
import 'githost.dart'; import 'githost.dart';
@ -12,29 +13,39 @@ class GitHub implements GitHost {
static const _clientID = "aa3072cbfb02b1db14ed"; static const _clientID = "aa3072cbfb02b1db14ed";
static const _clientSecret = "010d303ea99f82330f2b228977cef9ddbf7af2cd"; static const _clientSecret = "010d303ea99f82330f2b228977cef9ddbf7af2cd";
var _platform = const MethodChannel('gitjournal.io/git');
var _accessCode = ""; var _accessCode = "";
@override @override
Future<void> init() async { void init(OAuthCallback callback) {
var url = "https://github.com/login/oauth/authorize?client_id=" + Future _handleMessages(MethodCall call) async {
_clientID + if (call.method != "onURL") {
"&scope=repo"; Log.d("GitHub Unknown Call: " + call.method);
return;
}
var resultUrl = await FlutterWebAuth.authenticate( closeWebView();
url: url, callbackUrlScheme: "gitjournal"); Log.d("GitHub: Called onUrl with " + call.arguments.toString());
var uri = Uri.parse(resultUrl); String url = call.arguments["URL"];
var authCode = uri.queryParameters['code']; var uri = Uri.parse(url);
if (authCode == null) { var authCode = uri.queryParameters['code'];
Log.d("GitHub: Missing auth code. Now what?"); if (authCode == null) {
throw GitHostException.OAuthFailed; Log.d("GitHub: Missing auth code. Now what?");
callback(GitHostException.OAuthFailed);
}
_accessCode = await _getAccessCode(authCode);
if (_accessCode == null || _accessCode.isEmpty) {
Log.d("GitHub: AccessCode is invalid: " + _accessCode);
callback(GitHostException.OAuthFailed);
}
callback(null);
} }
_accessCode = await _getAccessCode(authCode); _platform.setMethodCallHandler(_handleMessages);
if (_accessCode == null || _accessCode.isEmpty) { Log.d("GitHub: Installed Handler");
Log.d("GitHub: AccessCode is invalid: " + _accessCode);
throw GitHostException.OAuthFailed;
}
} }
Future<String> _getAccessCode(String authCode) async { Future<String> _getAccessCode(String authCode) async {
@ -55,6 +66,16 @@ class GitHub implements GitHost {
return map["access_token"]; return map["access_token"];
} }
@override
Future launchOAuthScreen() async {
// FIXME: Add some 'state' over here!
var url = "https://github.com/login/oauth/authorize?client_id=" +
_clientID +
"&scope=repo";
return launch(url);
}
@override @override
Future<List<GitHostRepo>> listRepos() async { Future<List<GitHostRepo>> listRepos() async {
if (_accessCode.isEmpty) { if (_accessCode.isEmpty) {

View File

@ -3,8 +3,9 @@ import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:math'; import 'dart:math';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:flutter_web_auth/flutter_web_auth.dart'; import 'package:url_launcher/url_launcher.dart';
import 'package:gitjournal/utils/logger.dart'; import 'package:gitjournal/utils/logger.dart';
import 'githost.dart'; import 'githost.dart';
@ -13,48 +14,54 @@ class GitLab implements GitHost {
static const _clientID = static const _clientID =
"faf33c3716faf05bfb701b1b31e36c83a23c3ec2d7161f4ff00fba2275524d09"; "faf33c3716faf05bfb701b1b31e36c83a23c3ec2d7161f4ff00fba2275524d09";
var _platform = const MethodChannel('gitjournal.io/git');
var _accessCode = ""; var _accessCode = "";
var _stateOAuth = ""; var _stateOAuth = "";
@override @override
Future<void> init() async { void init(OAuthCallback callback) {
_stateOAuth = _randomString(10); Future _handleMessages(MethodCall call) async {
if (call.method != "onURL") {
Log.d("GitLab Unknown Call: " + call.method);
return;
}
var launchUrl = closeWebView();
"https://gitlab.com/oauth/authorize?client_id=$_clientID&response_type=token&state=$_stateOAuth&redirect_uri=gitjournal://login.oauth2"; Log.d("GitLab: Called onUrl with " + call.arguments.toString());
var url = await FlutterWebAuth.authenticate( String url = call.arguments["URL"];
url: launchUrl, callbackUrlScheme: "gitjournal"); var queryParamters = url.substring(url.indexOf('#') + 1);
var map = Uri.splitQueryString(queryParamters);
var receievedState = _fetchQueryParam(url, "state"); var state = map['state'];
if (receievedState != _stateOAuth) { if (state != _stateOAuth) {
Log.d("GitLab: OAuth State incorrect"); Log.d("GitLab: OAuth State incorrect");
Log.d("Required State: $_stateOAuth"); Log.d("Required State: " + _stateOAuth);
Log.d("Actual State: $receievedState"); Log.d("Actual State: " + state);
throw GitHostException.OAuthFailed; callback(GitHostException.OAuthFailed);
return;
}
_accessCode = map['access_token'];
if (_accessCode == null) {
callback(GitHostException.OAuthFailed);
return;
}
callback(null);
} }
_accessCode = _fetchQueryParam(url, "access_token"); _platform.setMethodCallHandler(_handleMessages);
if (_accessCode == null) { Log.d("GitLab: Installed Handler");
throw GitHostException.OAuthFailed;
}
} }
// Example: gitjournal://login.oauth2#access_token=49ce9d1s11145acc7bddf0b6b2a5fbe2a15496e4975808731e054eceeb49468f&token_type=Bearer&state=qxpYY%5CckY%5D @override
String _fetchQueryParam(String url, String param) { Future launchOAuthScreen() async {
var map = Uri.parse(url).queryParameters; _stateOAuth = _randomString(10);
var value = map[param];
if (value != null && value.isNotEmpty) {
return value;
}
var paramIndex = url.indexOf("$param="); var url =
if (paramIndex != -1) { "https://gitlab.com/oauth/authorize?client_id=$_clientID&response_type=token&state=$_stateOAuth&redirect_uri=gitjournal://login.oauth2";
var stateStr = url.substring(paramIndex + "$param=".length).split('&')[0]; return launch(url);
return Uri.decodeQueryComponent(stateStr);
}
return "";
} }
@override @override

View File

@ -20,6 +20,13 @@ class OAuthAppState extends State<OAuthApp> {
super.initState(); super.initState();
githost = createGitHost(GitHostType.GitHub); githost = createGitHost(GitHostType.GitHub);
githost.init((GitHostException e) {
if (e != null) {
print("Got exeception: $e");
} else {
print("GitHost initialized and has access code");
}
});
} }
@override @override
@ -34,7 +41,7 @@ class OAuthAppState extends State<OAuthApp> {
RaisedButton( RaisedButton(
child: const Text("Open OAuth URL"), child: const Text("Open OAuth URL"),
onPressed: () { onPressed: () {
githost.init(); githost.launchOAuthScreen();
}, },
), ),
RaisedButton( RaisedButton(

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:function_types/function_types.dart'; import 'package:function_types/function_types.dart';
import 'package:gitjournal/analytics.dart'; import 'package:gitjournal/analytics.dart';
@ -41,28 +42,39 @@ class GitHostSetupAutoConfigureState extends State<GitHostSetupAutoConfigure> {
gitHost = createGitHost(widget.gitHostType); gitHost = createGitHost(widget.gitHostType);
try { try {
await gitHost.init(); gitHost.init((Exception error) async {
if (error != null) {
throw error;
}
Log.d("GitHost Initalized: " + widget.gitHostType.toString());
Log.d("GitHost Initalized: " + widget.gitHostType.toString()); try {
setState(() {
_message = "Reading User Info";
});
var userInfo = await gitHost.getUserInfo();
if (userInfo.name != null && userInfo.name.isNotEmpty) {
Settings.instance.gitAuthor = userInfo.name;
}
if (userInfo.email != null && userInfo.email.isNotEmpty) {
Settings.instance.gitAuthorEmail = userInfo.email;
}
Settings.instance.save();
} on Exception catch (e, stacktrace) {
_handleGitHostException(e, stacktrace);
return;
}
widget.onDone(gitHost);
});
try { try {
setState(() { await gitHost.launchOAuthScreen();
_message = "Reading User Info"; } on PlatformException catch (e, stack) {
}); print("LaunchOAuthScreen: Caught platform exception: " + e.toString());
print(stack);
var userInfo = await gitHost.getUserInfo(); print("Ignoring it, since I don't know what else to do");
if (userInfo.name != null && userInfo.name.isNotEmpty) {
Settings.instance.gitAuthor = userInfo.name;
}
if (userInfo.email != null && userInfo.email.isNotEmpty) {
Settings.instance.gitAuthorEmail = userInfo.email;
}
Settings.instance.save();
} on Exception catch (e, stacktrace) {
_handleGitHostException(e, stacktrace);
return;
} }
widget.onDone(gitHost);
} on Exception catch (e, stacktrace) { } on Exception catch (e, stacktrace) {
_handleGitHostException(e, stacktrace); _handleGitHostException(e, stacktrace);
} }

View File

@ -303,13 +303,6 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_web_auth:
dependency: "direct main"
description:
name: flutter_web_auth
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.4"
flutter_web_plugins: flutter_web_plugins:
dependency: transitive dependency: transitive
description: flutter description: flutter

View File

@ -57,7 +57,6 @@ dependencies:
quick_actions: ^0.4.0+5 quick_actions: ^0.4.0+5
receive_sharing_intent: ^1.4.0+2 receive_sharing_intent: ^1.4.0+2
flutter_plugin_android_lifecycle: ^1.0.8 # for fixing the build flutter_plugin_android_lifecycle: ^1.0.8 # for fixing the build
flutter_web_auth: ^0.2.4
dev_dependencies: dev_dependencies:
flutter_launcher_icons: "^0.7.2" flutter_launcher_icons: "^0.7.2"