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>
</activity>
<activity android:name="com.linusu.flutter_web_auth.CallbackActivity">
<activity
android:name=".UriReceiverActivity"
android:parentActivityName=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<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>
</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 {
ext.kotlin_version = '1.3.50'
repositories {
google()
jcenter()
@ -11,7 +10,7 @@ buildscript {
}
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 '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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:function_types/function_types.dart';
import 'package:gitjournal/analytics.dart';
@ -41,28 +42,39 @@ class GitHostSetupAutoConfigureState extends State<GitHostSetupAutoConfigure> {
gitHost = createGitHost(widget.gitHostType);
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 {
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;
await gitHost.launchOAuthScreen();
} on PlatformException catch (e, stack) {
print("LaunchOAuthScreen: Caught platform exception: " + e.toString());
print(stack);
print("Ignoring it, since I don't know what else to do");
}
widget.onDone(gitHost);
} on Exception catch (e, stacktrace) {
_handleGitHostException(e, stacktrace);
}

View File

@ -303,13 +303,6 @@ packages:
description: flutter
source: sdk
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:
dependency: transitive
description: flutter

View File

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