Skip to content

login_page: Apple auth #1382

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 20 additions & 14 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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`)
Expand Down Expand Up @@ -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:
Expand All @@ -212,35 +217,36 @@ 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
FirebaseMessaging: e1aca1fcc23e8b9eddb0e33f375ff90944623021
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

Expand Down
4 changes: 4 additions & 0 deletions ios/Runner/Runner.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,9 @@
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.applesignin</key>
<array>
<string>Default</string>
</array>
</dict>
</plist>
2 changes: 2 additions & 0 deletions lib/api/model/web_auth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
43 changes: 29 additions & 14 deletions lib/widgets/login.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -347,19 +348,6 @@ class _LoginPageState extends State<LoginPage> {
} 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);

Expand Down Expand Up @@ -425,6 +413,33 @@ class _LoginPageState extends State<LoginPage> {
}
}

Future<void> _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<void> _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));
Expand All @@ -447,7 +462,7 @@ class _LoginPageState extends State<LoginPage> {
? Image.network(icon, width: 24, height: 24)
: null,
onPressed: !_inProgress
? () => _beginWebAuth(method)
? () => _handleExtAuth(method)
: null,
label: Text(
zulipLocalizations.signInWithFoo(method.displayName)));
Expand Down
2 changes: 2 additions & 0 deletions macos/Flutter/GeneratedPluginRegistrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"))
Expand Down
24 changes: 24 additions & 0 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down