This commit is contained in:
Adam Velebil 2022-10-04 09:13:59 +02:00
commit ebb0a5c928
No known key found for this signature in database
GPG Key ID: AC6D6B9D715FC084
5 changed files with 93 additions and 1 deletions

View File

@ -35,10 +35,20 @@
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<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="otpauth" />
</intent-filter>
</activity>
<activity-alias

View File

@ -14,6 +14,7 @@ import androidx.core.view.WindowCompat
import androidx.lifecycle.lifecycleScope
import com.yubico.authenticator.logging.FlutterLog
import com.yubico.authenticator.logging.Log
import com.yubico.authenticator.oath.AppLinkMethodChannel
import com.yubico.authenticator.oath.OathManager
import com.yubico.authenticator.oath.OathViewModel
import com.yubico.yubikit.android.YubiKitManager
@ -150,6 +151,13 @@ class MainActivity : FlutterFragmentActivity() {
enableAliasMainActivityComponent(true)
// Handle opening through otpauth:// link
val intentData = intent.data
if (intentData != null && intentData.scheme == "otpauth") {
intent.data = null
appLinkMethodChannel.handleUri(intentData)
}
// Handle existing tag when launched from NDEF
val tag = intent.getParcelableExtra<Tag>(NfcAdapter.EXTRA_TAG)
if (tag != null) {
@ -215,6 +223,7 @@ class MainActivity : FlutterFragmentActivity() {
private lateinit var flutterLog: FlutterLog
private lateinit var flutterStreams: List<Closeable>
private lateinit var appMethodChannel: AppMethodChannel
private lateinit var appLinkMethodChannel: AppLinkMethodChannel
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
@ -226,6 +235,7 @@ class MainActivity : FlutterFragmentActivity() {
dialogManager = DialogManager(messenger, this.lifecycleScope)
appPreferences = AppPreferences(this)
appMethodChannel = AppMethodChannel(messenger)
appLinkMethodChannel = AppLinkMethodChannel(messenger)
flutterStreams = listOf(
viewModel.deviceInfo.streamTo(this, messenger, "android.devices.deviceInfo"),

View File

@ -0,0 +1,25 @@
package com.yubico.authenticator.oath
import android.net.Uri
import androidx.annotation.UiThread
import com.yubico.authenticator.logging.Log
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodChannel
import org.json.JSONObject
class AppLinkMethodChannel(messenger: BinaryMessenger) {
private val methodChannel = MethodChannel(messenger, "app.link.methods")
@UiThread
fun handleUri(uri: Uri) {
Log.t(TAG, "Handling URI: $uri")
methodChannel.invokeMethod(
"handleOtpAuthLink",
JSONObject(mapOf("link" to uri.toString())).toString()
)
}
companion object {
const val TAG = "AppLinkMethodChannel"
}
}

View File

@ -8,6 +8,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:logging/logging.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:yubico_authenticator/android/logger.dart';
import 'package:yubico_authenticator/android/oath/otp_auth_link_handler.dart';
import 'package:yubico_authenticator/android/window_state_provider.dart';
import 'package:yubico_authenticator/app/logging.dart';
@ -54,7 +55,8 @@ Future<Widget> initialize() async {
windowStateProvider.overrideWithProvider(androidWindowStateProvider),
clipboardProvider.overrideWithProvider(androidClipboardProvider),
androidSdkVersionProvider.overrideWithValue(await getAndroidSdkVersion()),
supportedThemesProvider.overrideWithProvider(androidSupportedThemesProvider)
supportedThemesProvider
.overrideWithProvider(androidSupportedThemesProvider)
],
child: DismissKeyboard(
child: YubicoAuthenticatorApp(page: Consumer(
@ -68,6 +70,9 @@ Future<Widget> initialize() async {
/// initializes global handler for dialogs
ref.read(androidDialogProvider);
/// set context which will handle otpauth links
setupOtpAuthLinkHandler(context);
return const MainPage();
},
)),

View File

@ -0,0 +1,42 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../../app/message.dart';
import '../../oath/models.dart';
import '../../oath/views/add_account_page.dart';
const _appLinkMethodsChannel = MethodChannel('app.link.methods');
void setupOtpAuthLinkHandler(BuildContext context) {
_appLinkMethodsChannel.setMethodCallHandler((call) async {
final args = jsonDecode(call.arguments);
switch (call.method) {
case 'handleOtpAuthLink':
{
var url = args['link'];
var otpauth = CredentialData.fromUri(Uri.parse(url));
Navigator.popUntil(context, ModalRoute.withName('/'));
await showBlurDialog(
context: context,
routeSettings: const RouteSettings(name: 'oath_add_account'),
builder: (_) {
return OathAddAccountPage(
null,
null,
credentials: null,
credentialData: otpauth,
);
},
);
break;
}
default:
throw PlatformException(
code: 'NotImplemented',
message: 'Method ${call.method} is not implemented',
);
}
});
}