-
Notifications
You must be signed in to change notification settings - Fork 249
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(auth): Uncaught Hosted UI cancellation (#3686)
* chore(auth): Use `EventCompleter.ignore` instead of `unawaited` `unawaited` will still raise an error if there is one. By using `EventCompleter.ignore` we drop all completions, success or error. * fix(auth): Uncaught Hosted UI cancellation The HostedUIPlatform had a bug due to the fact that it both called `dispatcher.dispatchAndComplete` (which throws on failure states) and throwing a `UserCancelledException` which triggers a failure state. This lead to the error being thrown from `signInWithWebUI` and an uncaught exception being raised at the `dispatchAndComplete` call. This resolves the issue by only throwing from the HostedUiPlatform and letting the state machine resolving the cancellation. This also fixes an issue where `cancelSignIn` was never being called because the state machine was in a `signingIn` state at the time the cancellation was dispatched.
- Loading branch information
Showing
11 changed files
with
307 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 90 additions & 0 deletions
90
packages/auth/amplify_auth_cognito/test/hosted_ui_platform_flutter_test.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
// ignore_for_file: invalid_use_of_internal_member, non_constant_identifier_names | ||
|
||
import 'package:amplify_auth_cognito/amplify_auth_cognito.dart'; | ||
import 'package:amplify_auth_cognito/src/flows/hosted_ui/hosted_ui_platform_flutter.dart'; | ||
import 'package:amplify_auth_cognito/src/native_auth_plugin.g.dart'; | ||
import 'package:amplify_auth_cognito_dart/src/flows/hosted_ui/hosted_ui_platform.dart'; | ||
import 'package:amplify_auth_cognito_dart/src/state/cognito_state_machine.dart'; | ||
import 'package:amplify_auth_cognito_dart/src/state/state.dart'; | ||
import 'package:amplify_auth_cognito_test/amplify_auth_cognito_test.dart'; | ||
import 'package:amplify_flutter/amplify_flutter.dart'; | ||
import 'package:flutter/foundation.dart'; | ||
import 'package:flutter/services.dart'; | ||
import 'package:flutter_test/flutter_test.dart'; | ||
|
||
void main() { | ||
AWSLogger().logLevel = LogLevel.verbose; | ||
|
||
group('HostedUiPlatformFlutter', () { | ||
late AmplifyAuthCognito plugin; | ||
late SecureStorageInterface secureStorage; | ||
late DependencyManager dependencyManager; | ||
|
||
setUp(() async { | ||
secureStorage = MockSecureStorage(); | ||
dependencyManager = DependencyManager() | ||
..addInstance(hostedUiConfig) | ||
..addInstance<SecureStorageInterface>(secureStorage) | ||
..addInstance<NativeAuthBridge>(ThrowingNativeBridge()); | ||
plugin = AmplifyAuthCognito() | ||
..stateMachine = CognitoAuthStateMachine( | ||
dependencyManager: dependencyManager, | ||
); | ||
plugin.stateMachine.addBuilder<HostedUiPlatform>( | ||
HostedUiPlatformImpl.new, | ||
); | ||
await plugin.stateMachine.acceptAndComplete( | ||
ConfigurationEvent.configure(mockConfig), | ||
); | ||
}); | ||
|
||
tearDown(() => plugin.close()); | ||
|
||
test('can cancel flow', () async { | ||
// Pretend to be iOS so that the `ThrowingNativeBridge` is called, | ||
// mimicking a failure from the platform channel. | ||
debugDefaultTargetPlatformOverride = TargetPlatform.iOS; | ||
addTearDown(() => debugDefaultTargetPlatformOverride = null); | ||
|
||
final expectation = expectLater( | ||
plugin.signInWithWebUI( | ||
provider: AuthProvider.cognito, | ||
), | ||
throwsA(isA<UserCancelledException>()), | ||
); | ||
final hostedUiMachine = | ||
plugin.stateMachine.expect(HostedUiStateMachine.type); | ||
expect( | ||
hostedUiMachine.stream, | ||
emitsInOrder([ | ||
isA<HostedUiSigningIn>(), | ||
isA<HostedUiFailure>().having( | ||
(s) => s.exception, | ||
'exception', | ||
isA<UserCancelledException>(), | ||
), | ||
emitsDone, | ||
]), | ||
); | ||
await expectation; | ||
// Ensure queue is flushed and done event is emitted after | ||
// signInWithWebUI completes. | ||
await hostedUiMachine.close(); | ||
}); | ||
}); | ||
} | ||
|
||
final class ThrowingNativeBridge extends Fake implements NativeAuthBridge { | ||
@override | ||
Future<Map<String?, String?>> signInWithUrl( | ||
String arg_url, | ||
String arg_callbackUrlScheme, | ||
bool arg_preferPrivateSession, | ||
String? arg_browserPackageName, | ||
) async { | ||
throw PlatformException(code: 'CANCELLED'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.