I am using Amplify with Flutter to do the user authentication but I can’t retrieve the user’s session. The error I get:
> Launching lib/main.dart on 2109119DG in debug mode...
Running Gradle task 'assembleDebug'...
✓ Built build/app/outputs/flutter-apk/app-debug.apk.
Debug service listening on ws://xxxx
Syncing files to device 2109119DG...
I/amplify:flutter:auth_cognito(27806): Added Auth plugin
E/flutter (27806): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: AmplifyException(message: Auth plugin has not been added to Amplify, recoverySuggestion: Add Auth plugin to Amplify and call configure before calling Auth related APIs, underlyingException: null)
E/flutter (27806): #0 AuthCategory.fetchAuthSession (package:amplify_core/src/category/amplify_auth_category.dart:189:11)
E/flutter (27806): #1 _MyAppState.isUserSignedIn (package:base_app/main.dart:37:39)
E/flutter (27806): #2 _MyAppState.build (package:base_app/main.dart:47:21)
E/flutter (27806): #3 StatefulElement.build (package:flutter/src/widgets/framework.dart:4992:27)
E/flutter (27806): #4 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4878:15)
E/flutter (27806): #5 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5050:11)
E/flutter (27806): #6 Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
E/flutter (27806): #7 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4859:5)
E/flutter (27806): #8 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:5041:11)
E/flutter (27806): #9 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4853:5)
E/flutter (27806): #10 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3863:16)
E/flutter (27806): #11 Element.updateChild (package:flutter/src/widgets/framework.dart:3592:18)
E/flutter (27806): #12 RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:1195:16)
E/flutter (27806): #13 RenderObjectToWidgetElement.mount (package:flutter/src/widgets/binding.dart:1164:5)
E/flutter (27806): #14 RenderObjectToWidgetAdapter.attachToRenderTree.<anonymous closure> (package:flutter/src/widgets/binding.dart:1111:18)
E/flutter (27806): #15 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2605:19)
E/flutter (27806): #16 RenderObjectToWidgetAdapter.attachToRenderTree (package:flutter/src/widgets/binding.dart:1110:13)
E/flutter (27806): #17 WidgetsBinding.attachRootWidget (package:flutter/src/widgets/binding.dart:945:7)
E/flutter (27806): #18 WidgetsBinding.scheduleAttachRootWidget.<anonymous closure> (package:flutter/src/widgets/binding.dart:925:7)
E/flutter (27806): #19 Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:18:15)
E/flutter (27806): #20 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:398:19)
E/flutter (27806): #21 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:429:5)
E/flutter (27806): #22 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)
E/flutter (27806):
D/AWSMobileClient(27806): Using the SignInProviderConfig from `awsconfiguration.json`.
D/AWSMobileClient(27806): Inspecting user state details
I/flutter (27806): Successfully configured
D/AWSMobileClient(27806): Inspecting user state details
I/TetheringManager(27806): registerTetheringEventCallback:com.dontknow.base_app
D/AWSMobileClient(27806): hasFederatedToken: false provider: cognito-idp.eu-central-1.amazonaws.com/eu-central-1_xxxx
D/AWSMobileClient(27806): hasFederatedToken: false provider: cognito-idp.eu-central-1.amazonaws.com/eu-central-1_xxxx
D/AWSMobileClient(27806): Inspecting user state details
D/AWSMobileClient(27806): hasFederatedToken: true provider: cognito-idp.eu-central-1.amazonaws.com/eu-central-1_xxxx
D/AWSMobileClient(27806): waitForSignIn: userState:SIGNED_IN
D/AWSMobileClient(27806): getCredentials: Validated user is signed-in
I strictly folloed the AWS tutorials and added the plugin before calling "configure" in the code. What is also odd, is that in the line before the error occurs the plugin is actually loaded.
Here is my main.dart:
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
_configureAmplify();
}
void _configureAmplify() async {
try {
await Amplify.addPlugin(AmplifyAuthCognito());
await Amplify.configure(amplifyconfig);
print('Successfully configured');
} on Exception catch (e) {
print('Error configuring Amplify: $e');
}
}
Future<bool> isUserSignedIn() async {
final result = await Amplify.Auth.fetchAuthSession();
return result.isSignedIn;
}
@override
Widget build(BuildContext context) {
return Authenticator(
child: MaterialApp(
builder: Authenticator.builder(),
home: FutureBuilder(
future: isUserSignedIn(),
builder: (BuildContext ctx, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return const Center(
child: CircularProgressIndicator(),
);
} else {
return Text("logged in");
}
}),
),
);
}
}
2
Answers
Finally I found a suitable fix fitting my skilllevel here github-repo
I added a state variable
_isAmplifyConfigured
which is set true when_configureAmplify()
finishes. In the builder I then check wheter amplify is configured or not with a simple if-else. Here the full code:You are trying to do asynchronous work in
initState()
, but this is not guaranteed to complete beforebuild()
is called. Therefore, when you callAmplify.Auth.fetchAuthSession()
in yourbuild()
function, the initialisation and configuration is not complete.You should try calling
_configureAmplify()
beforerunApp()
.To make this work, you also need to call
WidgetsBinding ensureInitialized()
before_configureAmplify()
.As a general advise, this kind of work does not belong into UI code (pages or widgets). Rather is should be done in the app’s state management.