From c14cc53e2cdb3cf5ad038da336bc6cbe66629b17 Mon Sep 17 00:00:00 2001
From: Panagiotis Giannoutsos <36935711+Panosfunk@users.noreply.github.com>
Date: Mon, 8 Jun 2026 15:11:54 +0200
Subject: [PATCH] HTTPS applink support for iOS and Android first try
specifying deep link paths to allow for anonymous auth in android at the same time
specifying deep link paths to allow for anonymous auth in android at the same time
works for the most part
it works
removing prints
Merge fixes
---
android/app/build.gradle | 9 +-
android/app/src/main/AndroidManifest.xml | 47 ++++--
ios/Podfile.lock | 135 ------------------
.../xcshareddata/swiftpm/Package.resolved | 9 --
.../xcshareddata/xcschemes/Runner.xcscheme | 9 +-
.../xcshareddata/swiftpm/Package.resolved | 9 --
ios/Runner/Info.plist | 1 +
ios/Runner/Runner.entitlements | 4 +-
ios/Runner/RunnerRelease.entitlements | 4 +-
lib/carp_study_app.dart | 20 +++
lib/data/carp_backend.dart | 9 +-
lib/main.dart | 1 -
lib/ui/pages/login_page.dart | 7 +-
lib/ui/pages/qr_scanner.dart | 3 +-
pubspec.lock | 69 +++++----
pubspec.yaml | 6 +-
16 files changed, 127 insertions(+), 215 deletions(-)
delete mode 100644 ios/Podfile.lock
diff --git a/android/app/build.gradle b/android/app/build.gradle
index bc2192c5..b95ac025 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -65,7 +65,14 @@ android {
keyPassword keyProperties.getProperty('keyPassword')
}
}
- debug {}
+ debug {
+ if (signingConfigExists) {
+ storeFile file(keyProperties.getProperty('storeFile'))
+ storePassword keyProperties.getProperty('storePassword')
+ keyAlias keyProperties.getProperty('keyAlias')
+ keyPassword keyProperties.getProperty('keyPassword')
+ }
+ }
}
buildTypes {
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 0356ad36..c459676d 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -44,14 +44,16 @@
-
+
-
+
-
+
-
-
-
-
-
-
-
-
@@ -171,15 +165,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
6.1.0)
- - PolarBleSdk (6.1.0):
- - RxSwift (~> 6.8.0)
- - SwiftProtobuf (~> 1.0)
- - Zip (~> 2.1.2)
- - RxSwift (6.8.0)
- - screen_state (1.0.0):
- - Flutter
- - SwiftProtobuf (1.33.3)
- - Zip (2.1.2)
-
-DEPENDENCIES:
- - audio_streamer (from `.symlinks/plugins/audio_streamer/ios`)
- - dchs_flutter_beacon (from `.symlinks/plugins/dchs_flutter_beacon/ios`)
- - Flutter (from `Flutter`)
- - flutter_activity_recognition (from `.symlinks/plugins/flutter_activity_recognition/ios`)
- - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
- - flutter_sound (from `.symlinks/plugins/flutter_sound/ios`)
- - flutter_web_auth_2 (from `.symlinks/plugins/flutter_web_auth_2/ios`)
- - health (from `.symlinks/plugins/health/ios`)
- - location (from `.symlinks/plugins/location/ios`)
- - mdsflutter (from `.symlinks/plugins/mdsflutter/ios`)
- - Movesense (from `https://bitbucket.org/movesense/movesense-mobile-lib/`)
- - oidc_ios (from `.symlinks/plugins/oidc_ios/ios`)
- - open_settings_plus (from `.symlinks/plugins/open_settings_plus/ios`)
- - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- - polar (from `.symlinks/plugins/polar/ios`)
- - screen_state (from `.symlinks/plugins/screen_state/ios`)
-
-SPEC REPOS:
- trunk:
- - flutter_sound_core
- - PolarBleSdk
- - RxSwift
- - SwiftProtobuf
- - Zip
-
-EXTERNAL SOURCES:
- audio_streamer:
- :path: ".symlinks/plugins/audio_streamer/ios"
- dchs_flutter_beacon:
- :path: ".symlinks/plugins/dchs_flutter_beacon/ios"
- Flutter:
- :path: Flutter
- flutter_activity_recognition:
- :path: ".symlinks/plugins/flutter_activity_recognition/ios"
- flutter_secure_storage:
- :path: ".symlinks/plugins/flutter_secure_storage/ios"
- flutter_sound:
- :path: ".symlinks/plugins/flutter_sound/ios"
- flutter_web_auth_2:
- :path: ".symlinks/plugins/flutter_web_auth_2/ios"
- health:
- :path: ".symlinks/plugins/health/ios"
- location:
- :path: ".symlinks/plugins/location/ios"
- mdsflutter:
- :path: ".symlinks/plugins/mdsflutter/ios"
- Movesense:
- :git: https://bitbucket.org/movesense/movesense-mobile-lib/
- oidc_ios:
- :path: ".symlinks/plugins/oidc_ios/ios"
- open_settings_plus:
- :path: ".symlinks/plugins/open_settings_plus/ios"
- permission_handler_apple:
- :path: ".symlinks/plugins/permission_handler_apple/ios"
- polar:
- :path: ".symlinks/plugins/polar/ios"
- screen_state:
- :path: ".symlinks/plugins/screen_state/ios"
-
-CHECKOUT OPTIONS:
- Movesense:
- :commit: 580c812f2696ff05ed2c1c1e93053c137ef7942a
- :git: https://bitbucket.org/movesense/movesense-mobile-lib/
-
-SPEC CHECKSUMS:
- audio_streamer: 2e472b9f81cec5e381c4cf7667afa3055dcb45a4
- dchs_flutter_beacon: 88d72cc467de508d621e454ea66c6231d0897d4c
- Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
- flutter_activity_recognition: 52dfad4c1e9cec99f0841b3ed0efcc9d424b3deb
- flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
- flutter_sound: d95194f6476c9ad211d22b3a414d852c12c7ca44
- flutter_sound_core: 7f2626d249d3a57bfa6da892ef7e22d234482c1a
- flutter_web_auth_2: 5c8d9dcd7848b5a9efb086d24e7a9adcae979c80
- health: fe206e65f13a9b88623605fbd8af8f029e23dc35
- location: 155caecf9da4f280ab5fe4a55f94ceccfab838f8
- mdsflutter: bd3c0b3335d50947d1a192cf70f930e0fb04a766
- Movesense: dc64047c1feb856b7f7ac6ea2c67685350d99dd5
- oidc_ios: 16966cad509ce6850ca4ca1216c5138bef2a8726
- open_settings_plus: d19f91e8a04649358a51c19b484ce2e637149d70
- permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
- polar: 0374f6063ade7e2dd85d626f87cbe2393d3eda7c
- PolarBleSdk: bfb57cf8350f0c53d441b8632ba6df363ce7c79f
- RxSwift: 4e28be97cbcfeee614af26d83415febbf2bf6f45
- screen_state: 52d6e997d31bddba6417c60d9cdd22effd0320a7
- SwiftProtobuf: e1b437c8e31a4c5577b643249a0bb62ed4f02153
- Zip: b3fef584b147b6e582b2256a9815c897d60ddc67
-
-PODFILE CHECKSUM: 45842edf150243fea66883d4dfad1e5ddb428147
-
-COCOAPODS: 1.16.2
diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
index 7f1c67b8..a71b474b 100644
--- a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -1,14 +1,5 @@
{
"pins" : [
- {
- "identity" : "appauth-ios",
- "kind" : "remoteSourceControl",
- "location" : "https://github.com/openid/AppAuth-iOS",
- "state" : {
- "revision" : "145104f5ea9d58ae21b60add007c33c1cc0c948e",
- "version" : "2.0.0"
- }
- },
{
"identity" : "phonenumberkit",
"kind" : "remoteSourceControl",
diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index e596a992..f613b6b9 100644
--- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,7 +1,7 @@
+ version = "1.7">
@@ -91,6 +91,13 @@
ReferencedContainer = "container:Runner.xcodeproj">
+
+
+
+
CFBundleURLSchemes
carp-studies
+ carp-studies-anonymous
carp-studies-auth
diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements
index b8ebe5cc..0fe07231 100644
--- a/ios/Runner/Runner.entitlements
+++ b/ios/Runner/Runner.entitlements
@@ -4,7 +4,9 @@
com.apple.developer.associated-domains
- applinks:carp.computerome.dk
+ applinks:study.app.dev.carp.dk
+ applinks:study.app.test.carp.dk
+ applinks:study.app.carp.computerome.dk
com.apple.developer.authentication-services.autofill-credential-provider
diff --git a/ios/Runner/RunnerRelease.entitlements b/ios/Runner/RunnerRelease.entitlements
index 94a192bd..8521f0b3 100644
--- a/ios/Runner/RunnerRelease.entitlements
+++ b/ios/Runner/RunnerRelease.entitlements
@@ -6,8 +6,8 @@
development
com.apple.developer.associated-domains
- webcredentials:carp.computerome.com
- applinks:carp.computerome.dk
+ applinks:app.dev.carp.dk
+ applinks:app.carp.computerome.dk
com.apple.developer.authentication-services.autofill-credential-provider
diff --git a/lib/carp_study_app.dart b/lib/carp_study_app.dart
index eb34048e..446d7a94 100644
--- a/lib/carp_study_app.dart
+++ b/lib/carp_study_app.dart
@@ -154,6 +154,26 @@ class CarpStudyAppState extends State {
return task?.widget ?? const ErrorPage();
},
),
+ // Handle external magic-link callbacks from the auth server. The
+ // identity provider posts a link like
+ // /auth/realms/Carp/login-actions/action-token?key=...
+ // We attempt to authenticate using the URI. On
+ // success we go to '/', on failure we redirect to the login page.
+ GoRoute(
+ path: '/auth/realms/Carp/login-actions/action-token',
+ parentNavigatorKey: _rootNavigatorKey,
+ redirect: (context, state) async {
+ // We don't show any page, but handle the magic link in the background.
+ try {
+ await bloc.backend.authenticateWithMagicLink(state.uri.toString());
+ return homeRoute;
+ } catch (error) {
+ debugPrint(
+ 'Magic-link authentication failed: $error, redirecting to login page');
+ return LoginPage.route;
+ }
+ },
+ ),
GoRoute(
path: LoginPage.route,
parentNavigatorKey: _rootNavigatorKey,
diff --git a/lib/data/carp_backend.dart b/lib/data/carp_backend.dart
index 52a08e8a..af666c47 100644
--- a/lib/data/carp_backend.dart
+++ b/lib/data/carp_backend.dart
@@ -57,7 +57,7 @@ class CarpBackend {
authURL: uri,
clientId: 'studies-app',
redirectURI: Uri.parse('carp-studies-auth://auth'),
- anonymousRedirectURI: Uri.parse('carp-studies:/anonymous'),
+ anonymousRedirectURI: Uri.parse('carp-studies-anonymous://anonymous'),
// For authentication at CAWS the path is '/auth/realms/Carp'
discoveryURL: uri.replace(pathSegments: [
'auth',
@@ -115,12 +115,15 @@ class CarpBackend {
Future authenticateWithMagicLink(String uri) async {
try {
await initialize();
+ if (Platform.isIOS) {
+ sleep(const Duration(seconds: 1));
+ }
user = await CarpAuthService().authenticateWithMagicLink(uri);
LocalSettings().isAnonymous = true;
- info('$runtimeType - ANONYMOUS User authenticated - user: $user');
+ print('$runtimeType - ANONYMOUS User authenticated - user: $user');
} catch (error) {
user = null;
- warning('$runtimeType - ANONYMOUS Error authenticating user - $error');
+ print('$runtimeType - ANONYMOUS Error authenticating user - $error');
}
}
diff --git a/lib/main.dart b/lib/main.dart
index 94c7a691..0fc4ec59 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -9,7 +9,6 @@ import 'dart:io';
import 'package:app_version_update/data/models/app_version_result.dart';
import 'package:async/async.dart';
-import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
diff --git a/lib/ui/pages/login_page.dart b/lib/ui/pages/login_page.dart
index fcc72f02..9bf54a7a 100644
--- a/lib/ui/pages/login_page.dart
+++ b/lib/ui/pages/login_page.dart
@@ -68,10 +68,15 @@ class _LoginPageState extends State {
child: TextButton(
onPressed: () async {
bool isConnected = await bloc.checkConnectivity();
+ print("isConnected: $isConnected");
if (isConnected) {
await bloc.backend.initialize();
await bloc.backend.authenticate();
- if (context.mounted) context.go(CarpStudyAppState.homeRoute);
+ if (context.mounted) {
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ context.go(CarpStudyAppState.homeRoute);
+ });
+ }
} else {
showDialog(
context: context,
diff --git a/lib/ui/pages/qr_scanner.dart b/lib/ui/pages/qr_scanner.dart
index b67ec16e..db4821e5 100644
--- a/lib/ui/pages/qr_scanner.dart
+++ b/lib/ui/pages/qr_scanner.dart
@@ -6,11 +6,11 @@ class QRViewExample extends StatefulWidget {
@override
State createState() => _QRViewExampleState();
}
+ final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
class _QRViewExampleState extends State {
qr.Barcode? result;
qr.QRViewController? controller;
- final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
// In order to get hot reload to work we need to pause the camera if the platform
// is android, or resume the camera if the platform is iOS.
@@ -115,6 +115,7 @@ class _QRViewExampleState extends State {
});
final qrcode = scanData.code;
+ print('QR code scanned: $qrcode');
if (qrcode != null && Uri.tryParse(qrcode)?.hasAbsolutePath == true) {
await bloc.backend.authenticateWithMagicLink(qrcode).then((_) {
diff --git a/pubspec.lock b/pubspec.lock
index 569ab9b3..e8d3a31a 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -93,10 +93,10 @@ packages:
dependency: transitive
description:
name: audioplayers
- sha256: a72dd459d1a48f61a6fb9c0134dba26597c9236af40639ff0eb70eb4e0baab70
+ sha256: f16640453cc47487b7de72a2b28d37c7df1ac97999849f4a46d92b1d2b0f093d
url: "https://pub.dev"
source: hosted
- version: "6.6.0"
+ version: "6.7.1"
audioplayers_android:
dependency: transitive
description:
@@ -133,18 +133,18 @@ packages:
dependency: transitive
description:
name: audioplayers_web
- sha256: faa8fa6587f996a6f604433b53af44c57a1407d4fe8dff5766cf63d6875e8de9
+ sha256: "24a6f258062bd7da8cb2157e83fccb9816a08dd306cbaaa24f9813d071470545"
url: "https://pub.dev"
source: hosted
- version: "5.2.0"
+ version: "5.2.1"
audioplayers_windows:
dependency: transitive
description:
name: audioplayers_windows
- sha256: bafff2b38b6f6d331887558ba6e0a01c9c208d9dbb3ad0005234db065122a734
+ sha256: "95f875a96c88c3dbbcb608d4f8288e300b0113d256a81d0b3197fcc18f0dc91a"
url: "https://pub.dev"
source: hosted
- version: "4.3.0"
+ version: "4.3.1"
base_codecs:
dependency: transitive
description:
@@ -370,12 +370,11 @@ packages:
source: hosted
version: "0.0.5"
carp_webservices:
- dependency: "direct main"
+ dependency: "direct overridden"
description:
- name: carp_webservices
- sha256: "6459af381237f38e65e6300763cddc04186c69e746ab97210f8134426e8a17dc"
- url: "https://pub.dev"
- source: hosted
+ path: "../carp.sensing-flutter/backends/carp_webservices"
+ relative: true
+ source: path
version: "3.8.0"
characters:
dependency: transitive
@@ -421,10 +420,10 @@ packages:
dependency: transitive
description:
name: code_assets
- sha256: "67cf6d84013f9c601e42a6f8a6b74c4c0d9dc1a1619d775f2b28b732d3551b85"
+ sha256: bf394f466ba9205f1812a0433b392d6af280f155f56651eda7c18cc32ed493b8
url: "https://pub.dev"
source: hosted
- version: "1.2.0"
+ version: "1.2.1"
code_builder:
dependency: transitive
description:
@@ -557,10 +556,10 @@ packages:
dependency: transitive
description:
name: dbus
- sha256: d0c98dcd4f5169878b6cf8f6e0a52403a9dff371a3e2f019697accbf6f44a270
+ sha256: "0ce9b0a839e6dee59a37a623d2fc26a35bbbe6404213e419b0d6411023d62645"
url: "https://pub.dev"
source: hosted
- version: "0.7.12"
+ version: "0.7.14"
dchs_flutter_beacon:
dependency: transitive
description:
@@ -799,10 +798,10 @@ packages:
dependency: "direct main"
description:
name: flutter_plugin_android_lifecycle
- sha256: "38d1c268de9097ff59cf0e844ac38759fc78f76836d37edad06fa21e182055a0"
+ sha256: "3854fe5e3bff0b113c658f260b90c95dea17c92db0f2addeac2e343dd9969785"
url: "https://pub.dev"
source: hosted
- version: "2.0.34"
+ version: "2.0.35"
flutter_secure_storage:
dependency: transitive
description:
@@ -977,10 +976,10 @@ packages:
dependency: transitive
description:
name: hooks
- sha256: a41af4e8fc687cd6d33de9751eb936c8c0204ebe2bcb6c15ecf707504bf47f31
+ sha256: "9a62a50b50b769a737bc0a8ff381f333529df3ab746b2f6b02e83760231455ba"
url: "https://pub.dev"
source: hosted
- version: "2.0.0"
+ version: "2.0.2"
html:
dependency: transitive
description:
@@ -1257,10 +1256,10 @@ packages:
dependency: transitive
description:
name: meta
- sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349"
+ sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
url: "https://pub.dev"
source: hosted
- version: "1.18.0"
+ version: "1.17.0"
mime:
dependency: transitive
description:
@@ -1585,10 +1584,10 @@ packages:
dependency: transitive
description:
name: permission_handler_apple
- sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023
+ sha256: e20daf680eef1ca62ffe8c8c526b778cc386d50137c77ac71c8ec9c88c13fb9d
url: "https://pub.dev"
source: hosted
- version: "9.4.7"
+ version: "9.4.9"
permission_handler_html:
dependency: transitive
description:
@@ -1697,10 +1696,10 @@ packages:
dependency: "direct main"
description:
name: qr_code_scanner_plus
- sha256: dae0596b2763c2fd0294f5cfddb1d3a21577ae4dc7fc1449eb5aafc957872f61
+ sha256: "2bcf9df32aa639fba07c183b1ab9c3f03eb6b1d688ab4f4f6bc868a75afd824d"
url: "https://pub.dev"
source: hosted
- version: "2.1.1"
+ version: "2.1.2"
recase:
dependency: transitive
description:
@@ -2046,26 +2045,26 @@ packages:
dependency: "direct dev"
description:
name: test
- sha256: "8d9ceddbab833f180fbefed08afa76d7c03513dfdba87ffcec2718b02bbcbf20"
+ sha256: "280d6d890011ca966ad08df7e8a4ddfab0fb3aa49f96ed6de56e3521347a9ae7"
url: "https://pub.dev"
source: hosted
- version: "1.31.0"
+ version: "1.30.0"
test_api:
dependency: transitive
description:
name: test_api
- sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e"
+ sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
url: "https://pub.dev"
source: hosted
- version: "0.7.11"
+ version: "0.7.10"
test_core:
dependency: transitive
description:
name: test_core
- sha256: "1991d4cfe85d5043241acac92962c3977c8d2f2add1ee73130c7b286417d1d34"
+ sha256: "0381bd1585d1a924763c308100f2138205252fb90c9d4eeaf28489ee65ccde51"
url: "https://pub.dev"
source: hosted
- version: "0.6.17"
+ version: "0.6.16"
timeago:
dependency: "direct main"
description:
@@ -2206,10 +2205,10 @@ packages:
dependency: transitive
description:
name: vector_graphics_compiler
- sha256: b9b3f391857781aa96acacef96066f2f49b4cd03cf9fce3ca4d8da2ef5ea129e
+ sha256: "7ee12e6dffe0fc8e755179d6d91b3b34f5924223fc104d85572ef9180d73d172"
url: "https://pub.dev"
source: hosted
- version: "1.2.3"
+ version: "1.2.5"
vector_math:
dependency: transitive
description:
@@ -2334,10 +2333,10 @@ packages:
dependency: transitive
description:
name: window_to_front
- sha256: "7aef379752b7190c10479e12b5fd7c0b9d92adc96817d9e96c59937929512aee"
+ sha256: "14fad8984db4415e2eeb30b04bb77140b180e260d6cb66b26de126a8657a9241"
url: "https://pub.dev"
source: hosted
- version: "0.0.3"
+ version: "0.0.4"
x509_plus:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 39b3f24d..e33e3d34 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -23,7 +23,7 @@ dependencies:
carp_movesense_package: ^1.7.2
carp_themes_package: ^0.0.5
- carp_webservices: ^3.8.0
+ # carp_webservices: ^3.8.0
carp_backend: ^1.9.2
research_package: ^2.2.0
@@ -93,8 +93,8 @@ dependency_overrides:
# path: ../carp/carp.sensing-flutter/packages/carp_health_package/
# carp_movesense_package:
# path: ../carp/carp.sensing-flutter/packages/carp_movesense_package/
- # carp_webservices:
- # path: ../carp.sensing-flutter/backends/carp_webservices/
+ carp_webservices:
+ path: ../carp.sensing-flutter/backends/carp_webservices/
# carp_backend:
# path: ../carp/carp.sensing-flutter/backends/carp_backend/
# research_package: