diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 27e8691603..074c95baf6 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -117,6 +117,8 @@ PODS:
- SDWebImage/Core (5.20.0)
- share_plus (0.0.1):
- Flutter
+ - sign_in_with_apple (0.0.1):
+ - Flutter
- sqlite3 (3.47.2):
- sqlite3/common (= 3.47.2)
- sqlite3/common (3.47.2)
@@ -157,6 +159,7 @@ DEPENDENCIES:
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- share_plus (from `.symlinks/plugins/share_plus/ios`)
+ - sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`)
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`)
@@ -202,6 +205,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
share_plus:
:path: ".symlinks/plugins/share_plus/ios"
+ sign_in_with_apple:
+ :path: ".symlinks/plugins/sign_in_with_apple/ios"
sqlite3_flutter_libs:
:path: ".symlinks/plugins/sqlite3_flutter_libs/darwin"
url_launcher_ios:
@@ -212,14 +217,14 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/wakelock_plus/ios"
SPEC CHECKSUMS:
- app_settings: 017320c6a680cdc94c799949d95b84cb69389ebc
- device_info_plus: bf2e3232933866d73fe290f2942f2156cdd10342
+ app_settings: 3507c575c2b18a462c99948f61d5de21d4420999
+ device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
- file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655
+ file_picker: 9b3292d7c8bc68c8a7bf8eb78f730e49c8efc517
Firebase: 374a441a91ead896215703a674d58cdb3e9d772b
- firebase_core: feb37e79f775c2bd08dd35e02d83678291317e10
- firebase_messaging: e2f0ba891b1509668c07f5099761518a5af8fe3c
+ firebase_core: 2337982fb78ee4d8d91e608b0a3d4f44346a93c8
+ firebase_messaging: f3bddfa28c2cad70b3341bf461e987a24efd28d6
FirebaseCore: 48b0dd707581cf9c1a1220da68223fb0a562afaa
FirebaseCoreInternal: d98ab91e2d80a56d7b246856a8885443b302c0c2
FirebaseInstallations: efc0946fc756e4d22d8113f7c761948120322e8c
@@ -227,20 +232,21 @@ SPEC CHECKSUMS:
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
- image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
- integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573
+ image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
+ integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
- package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
- path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
+ package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
+ path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
SDWebImage: 73c6079366fea25fa4bb9640d5fb58f0893facd8
- share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
+ share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
+ sign_in_with_apple: c5dcc141574c8c54d5ac99dd2163c0c72ad22418
sqlite3: 7559e33dae4c78538df563795af3a86fc887ee71
- sqlite3_flutter_libs: 58ae36c0dd086395d066b4fe4de9cdca83e717b3
+ sqlite3_flutter_libs: 5235ce0546528db87927a3ef1baff8b7d5107f0e
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
- url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
- video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3
- wakelock_plus: 373cfe59b235a6dd5837d0fb88791d2f13a90d56
+ url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
+ video_player_avfoundation: 2cef49524dd1f16c5300b9cd6efd9611ce03639b
+ wakelock_plus: 04623e3f525556020ebd4034310f20fe7fda8b49
PODFILE CHECKSUM: 7ed5116924b3be7e8fb75f7aada61e057028f5c7
diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements
index 903def2af5..80b5221de7 100644
--- a/ios/Runner/Runner.entitlements
+++ b/ios/Runner/Runner.entitlements
@@ -4,5 +4,9 @@
aps-environment
development
+ com.apple.developer.applesignin
+
+ Default
+
diff --git a/lib/api/model/web_auth.dart b/lib/api/model/web_auth.dart
index 490c4b79db..53efde2bc5 100644
--- a/lib/api/model/web_auth.dart
+++ b/lib/api/model/web_auth.dart
@@ -75,6 +75,8 @@ String generateOtp() {
return hex.encode(bytes);
}
+String generateRandomToken() => generateOtp();
+
/// For tests, create an OTP-encrypted API key.
@visibleForTesting
String debugEncodeApiKey(String apiKey, String otp) {
diff --git a/lib/widgets/login.dart b/lib/widgets/login.dart
index 504289adc1..df86ae1a68 100644
--- a/lib/widgets/login.dart
+++ b/lib/widgets/login.dart
@@ -3,6 +3,7 @@ import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
+import 'package:sign_in_with_apple/sign_in_with_apple.dart';
import 'package:url_launcher/url_launcher.dart';
import '../api/exception.dart';
@@ -347,19 +348,6 @@ class _LoginPageState extends State {
} catch (e) {
assert(debugLog(e.toString()));
- if (e is PlatformException
- && defaultTargetPlatform == TargetPlatform.iOS
- && e.message != null && e.message!.startsWith('Error while launching')) {
- // Ignore; I've seen this on my iPhone even when auth succeeds.
- // Specifically, Apple web auth…which on iOS should be replaced by
- // Apple native auth; that's #462.
- // Possibly related:
- // https://github.com/flutter/flutter/issues/91660
- // but in that issue, people report authentication not succeeding.
- // TODO(#462) remove this?
- return;
- }
-
if (!mounted) return;
final zulipLocalizations = ZulipLocalizations.of(context);
@@ -425,6 +413,33 @@ class _LoginPageState extends State {
}
}
+ Future _handleNativeAppleAuth() async {
+ final state = generateRandomToken();
+ final credential = await SignInWithApple.getAppleIDCredential(
+ state: state,
+ scopes: [
+ AppleIDAuthorizationScopes.fullName,
+ AppleIDAuthorizationScopes.email,
+ ],
+ );
+ if (credential.state != state) throw Exception('`state` mismatch');
+
+ __otp = generateOtp();
+
+ final url = widget.serverSettings.realmUrl.resolve('/complete/apple/')
+ .replace(queryParameters: {'mobile_flow_otp': _otp!, 'native_flow': 'true', 'id_token': credential.identityToken});
+
+ await ZulipBinding.instance.launchUrl(url, mode: LaunchMode.inAppBrowserView);
+ }
+
+ Future _handleExtAuth(ExternalAuthenticationMethod method) async {
+ if (method.name == 'apple' && defaultTargetPlatform == TargetPlatform.iOS) {
+ await _handleNativeAppleAuth();
+ } else {
+ await _beginWebAuth(method);
+ }
+ }
+
@override
Widget build(BuildContext context) {
assert(!PerAccountStoreWidget.debugExistsOf(context));
@@ -447,7 +462,7 @@ class _LoginPageState extends State {
? Image.network(icon, width: 24, height: 24)
: null,
onPressed: !_inProgress
- ? () => _beginWebAuth(method)
+ ? () => _handleExtAuth(method)
: null,
label: Text(
zulipLocalizations.signInWithFoo(method.displayName)));
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index 83889555f8..b02a56cab1 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -12,6 +12,7 @@ import firebase_messaging
import package_info_plus
import path_provider_foundation
import share_plus
+import sign_in_with_apple
import sqlite3_flutter_libs
import url_launcher_macos
import video_player_avfoundation
@@ -25,6 +26,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
+ SignInWithApplePlugin.register(with: registry.registrar(forPlugin: "SignInWithApplePlugin"))
Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin"))
diff --git a/pubspec.lock b/pubspec.lock
index 4ee3317f8d..5c28e55755 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -955,6 +955,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.1"
+ sign_in_with_apple:
+ dependency: "direct main"
+ description:
+ name: sign_in_with_apple
+ sha256: e84a62e17b7e463abf0a64ce826c2cd1f0b72dff07b7b275e32d5302d76fb4c5
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.1.4"
+ sign_in_with_apple_platform_interface:
+ dependency: transitive
+ description:
+ name: sign_in_with_apple_platform_interface
+ sha256: c2ef2ce6273fce0c61acd7e9ff5be7181e33d7aa2b66508b39418b786cca2119
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.0"
+ sign_in_with_apple_web:
+ dependency: transitive
+ description:
+ name: sign_in_with_apple_web
+ sha256: "2f7c38368f49e3f2043bca4b46a4a61aaae568c140a79aa0675dc59ad0ca49bc"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.1"
sky_engine:
dependency: transitive
description: flutter
diff --git a/pubspec.yaml b/pubspec.yaml
index c17bebe704..2e46d78a1f 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -56,6 +56,7 @@ dependencies:
path_provider: ^2.0.13
share_plus: ^10.1.3
share_plus_platform_interface: ^5.0.2
+ sign_in_with_apple: ^6.1.4
sqlite3: ^2.4.0
sqlite3_flutter_libs: ^0.5.13
url_launcher: ^6.1.11