When my SignUp process receives an error from my PreSignUp lambda the Amplify Authenticator UI is always stuck in the loading state and I can't do anything about it, solved only by manually removing query parameters and reloading the page. More details are below.
My amplify is configured in the state of the main widget like this:
class _AppState extends State<App> {
@override
void initState() {
super.initState();
configureAmplify().then((value) {
// get current user, etc etc
});
}
// etc
}
And here is my configureAmplify
function (I use the Hub to change app state based on events, but this is not relevant so I deleted a few lines):
Future<void> configureAmplify() async {
try {
await Amplify.addPlugin(AmplifyAuthCognito());
await Amplify.configure(amplifyconfig);
Amplify.Hub.listen(HubChannel.Auth, (hubEvent) {
switch (hubEvent.eventName) {
default:
print('USER EVENT: ${hubEvent.eventName}');
}
});
debugPrint('Successfully configured');
} on Exception catch (e) {
debugPrint('Error configuring Amplify: $e');
}
}
After the signup attempt with a social provider, the user is getting an error because of my PreSignUp trigger. I validate a few things to let users log in with social providers, nothing wrong here.
The problem is that after the oauth redirect (for example to http://localhost:3000/app/?error_description=PreSignUp%20failed%20with%20error%20Invalid%20Email.%20&state=9EKPg3UiN5rv2FTa9VftCHEKxXgkIw5Z&error=invalid_request
when running locally) the amplify isn't configured anymore (logging the message above) and the view (protected by the AuthenticatedView widget) is now in the loading state forever:
# Error logged by the try {} in the configureAmplify function
Error configuring Amplify: AuthException(message: Invalid Email, recoverySuggestion: null, underlyingException: null)
PS.: I'm using MaterialApp.router and configuring the authenticatorBuilder:
Authenticator(
authenticatorBuilder: getAuthenticationBuilder(),
child: MaterialApp.router(
// my app configuration
),
);
PS 2.: my authentication builder is pretty simple, it's modifying only the layout to add a logo and other elements for specific states:
Widget? Function(BuildContext, AuthenticatorState)? getAuthenticationBuilder() {
return (BuildContext context, AuthenticatorState state) {
Widget child;
switch (state.currentStep) {
case AuthenticatorStep.confirmResetPassword:
child = Padding(
padding: padding,
child: Column(
children: [
_logo(),
_logoDivider("Change your Password"),
const ConfirmResetPasswordForm(),
const Spacer(),
_dontHaveAccount(state),
],
),
);
break;
case AuthenticatorStep.resetPassword:
child = Padding(
padding: padding,
child: Column(
children: [
_logo(),
_logoDivider("Reset your Password"),
ResetPasswordForm(),
const Spacer(),
_dontHaveAccount(state),
],
),
);
break;
case AuthenticatorStep.signIn:
child = Padding(
padding: padding,
child: Column(
children: [
_logo(),
_logoDivider("Sign In with Email/Username"),
SignInForm(),
const Spacer(),
_dontHaveAccount(state),
],
),
);
break;
case AuthenticatorStep.signUp:
child = Padding(
padding: padding,
child: Column(
children: [
// app logo
_logo(),
_logoDivider("Enter your details"),
_signUpForm(),
const Spacer(),
_alreadyHaveAnAccount(state)
],
),
);
break;
default:
// use default from amplify authenticator package
return null;
}
return Center(
child: SingleChildScrollView(
child: Center(
child: ConstrainedBox(
constraints: const BoxConstraints(
maxWidth: ContainerConstants.mediumWidth,
maxHeight: ContainerConstants.mediumHeight),
child: Padding(
padding: EdgeInsets.symmetric(vertical: containerPadding),
child: Card(
child: child,
),
),
),
),
),
);
};
}
The biggest problem is that the Amplify.configure
method is always throwing an error after the redirect because of all those query parameters, and I can't just deal with the error myself (for example showing a modal) because the amplify state never changes (even calling state.changeStep
manually) and my user is never redirected to the login page again. And the Amplify.configure
is called only once in the initState
.