You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter接入AWS Cognito修改页面逻辑后登录报错idToken为null

问题背景

调整应用逻辑从启动强制登录改为先浏览内容再触发登录后,点击登录按钮触发Cognito异常,控制台报错如下:

W/CognitoUserSession(22147): CognitoUserSession is not valid because idToken is null.
D/AWSMobileClient(22147): Sending password.
D/AWSMobileClient(22147): Using USER_SRP_AUTH for flow type.
E/UserContextDataProvider(22147): Exception in creating JSON from context data
E/amplify:flutter:auth_cognito(22147): AuthException
I/flutter (22147): Could not login - Sign in failed
触发原因
  • AuthService设计存在状态不一致问题:authStateController被定义为静态属性,但loginWithCredentials、showLogin等核心方法是实例方法,调整后监听的是静态stream,但传入页面的是实例方法,两者操作的状态不互通,导致本地残留无效的空token会话。
  • 缺少初始化状态校验:应用启动时没有先等待Amplify初始化完成就加载页面,也没有主动调用checkAuthStatus清理本地残留的无效会话,本地之前缓存的空idToken会话干扰了新的登录请求。
  • TabBarFlow状态不更新:在initState中一次性初始化了_widgetOptions,传入SettingsPage的authFlowStatus是初始化时的固定值,后续auth状态变化时不会同步更新,导致页面状态和实际鉴权状态不匹配。
修复方案
  1. 统一AuthService的状态管理
    把AuthService改成单例模式,避免静态和实例方法混用导致的状态不一致,修改示例:
class AuthService {
  // 单例实现
  static final AuthService _instance = AuthService._internal();
  factory AuthService() => _instance;
  AuthService._internal();

  // 去掉static修饰,统一用单例实例访问
  final authStateController = StreamController<AuthState>.broadcast();
  late AuthCredentials _credentials;

  void showNone() {
    final state = AuthState(authFlowStatus: AuthFlowStatus.none);
    authStateController.add(state);
  }
  // 其余方法同理去掉static修饰,logOut方法也改为非静态
  void logOut() async {
    try {
      await Amplify.Auth.signOut();
      final state = AuthState(authFlowStatus: AuthFlowStatus.none);
      authStateController.add(state);
    } on AuthException catch (authError) {
      print('Could not log out - ${authError.message}');
    }
  }
  // ...其余方法保持原有逻辑不变
}

调整main.dart中stream的监听为单例实例的stream:

stream: AuthService().authStateController.stream,

所有调用AuthService方法的地方都统一用AuthService().方法名调用。

  1. 新增初始化校验逻辑
    在应用启动时先完成Amplify初始化,再调用checkAuthStatus初始化鉴权状态,示例:
// 在main函数或者应用根组件的initState中执行
Future<void> _initAmplify() async {
  try {
    await Amplify.addPlugin(AmplifyAuthCognito());
    await Amplify.configure(amplifyconfig);
    // 初始化完成后再校验鉴权状态
    AuthService().checkAuthStatus();
  } catch(e) {
    print('Amplify初始化失败: $e');
  }
}
  1. 修复TabBarFlow的状态更新逻辑
    不要在initState中固定_widgetOptions,改到build方法中构建,保证authFlowStatus变化时同步更新:
@override
Widget build(BuildContext context) {
  // 放到build里每次状态变化都重新生成widget列表
  final _widgetOptions = <Widget>[
    HomePage(),
    SearchAvatarPage(),
    SelectAvatarPage(),
    MyPage(),
    SettingsPage(
        authFlowStatus: widget.authFlowStatus,
        shouldShowSignUp: widget.shouldShowSignUp,
        shouldShowLogin: widget.shouldShowLogin
    )
  ];
  return Scaffold(
    // 原有布局逻辑保持不变
  );
}
  1. 登录前清理本地无效会话
    在loginWithCredentials方法开头新增本地会话清理逻辑,避免残留空token干扰:
void loginWithCredentials(AuthCredentials credentials) async {
  try {
    // 先清理本地残留的无效会话,未登录时signOut报错直接忽略
    try {
      await Amplify.Auth.signOut(options: SignOutOptions(globalSignOut: false));
    } catch(_) {}
    // 原有登录逻辑保持不变
    final result = await Amplify.Auth.signIn(
      username: credentials.username, password: credentials.password
    );
    // ...后续逻辑保持不变
  } on AuthException catch (authError) {
    print('Could not login - ${authError.message}');
  }
}
  1. 兼容Cognito高级安全特性报错
    如果仍然出现UserContextDataProvider相关错误,可升级amplify_auth_cognito到最新稳定版,或者到AWS Cognito控制台的用户池-高级安全设置中,关闭"启用高级安全"特性即可解决。

内容的提问来源于stack exchange,提问作者gs97ahn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 17:48:03