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

Flutter中使用Amplify Auth获取JWT/访问令牌及Identity ID失败的问题求助

Flutter中使用Amplify Auth获取JWT/访问令牌及Identity ID失败的问题求助

问题描述

看起来你遇到的问题是:使用Amplify Auth Cognito的WebUI登录成功后,虽然isSignedIn返回true,且能看到userPoolTokens包含访问令牌,但调用fetchCognitoAuthSession()时却报错Error retrieving auth session: The AWS credentials could not be retrieved.,无法正常获取Identity ID和JWT令牌。

先贴出你的原始代码方便分析:

import 'dart:async';

import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
import '../amplifyconfiguration.dart';
import 'package:amplify_flutter/amplify_flutter.dart';

class LogInService {
  LogInService() {
    _configureAmplify();
  }

  Future<void> _configureAmplify() async {
    try {
      AmplifyAuthCognito auth = AmplifyAuthCognito();
      await Amplify.addPlugin(auth);
      await Amplify.configure(amplifyconfig);
    } on Exception catch (e) {
      safePrint('An error occurred configuring Amplify: $e');
    }
  }

  Future<bool> signInWithWebUI() async {
    try {
      final result = await Amplify.Auth.signInWithWebUI();
      final creds = await Amplify.Auth.fetchAuthSession();
      safePrint('Sign in result: $creds');
      if (creds.isSignedIn) {
        fetchCognitoAuthSession();
        return true;
      } else {
        return false;
      }
    } on AuthException catch (e) {
      safePrint('Error signing in: ${e.message}');
      return false;
    }
  }

  Future<void> fetchCognitoAuthSession() async {
    try {
      final cognitoPlugin = Amplify.Auth.getPlugin(AmplifyAuthCognito.pluginKey);
      final result = await cognitoPlugin.fetchAuthSession();
      final accessToken = result. // 这里存在未完成的语法错误
      final identityId = result.identityIdResult.value;
      safePrint("Current user's identity ID: $identityId");
    } on AuthException catch (e) {
      safePrint('Error retrieving auth session: ${e.message}');
    }
  }

  Future<void> signOutWithWebUI() async {
    try {
      await Amplify.Auth.signOut();
      safePrint("Signed out successfully");
    } on AuthException catch (e) {
      safePrint(e.message);
    }
  }
}

问题分析

我梳理了几个可能导致问题的关键点:

  1. 语法错误阻塞逻辑:fetchCognitoAuthSession()里final accessToken = result.这行代码未完成,会直接导致编译/运行错误,影响后续的Identity ID获取逻辑。
  2. Identity ID的获取前提:要拿到Identity ID,必须确保Cognito身份池和用户池已正确关联,且身份池的认证角色拥有sts:GetFederationToken等必要权限,否则无法生成身份凭证。
  3. 会话获取方式不当:直接通过插件实例调用fetchAuthSession()的方式不够稳妥,建议通过通用的Amplify.Auth.fetchAuthSession()获取会话后,再转换为Cognito特定会话处理。
  4. JWT令牌的获取位置:其实登录成功后,JWT令牌(idToken/accessToken)已经包含在userPoolTokens中,无需单独通过插件会话重复获取。

解决办法

下面是修改后的完整代码,包含正确的令牌和Identity ID获取逻辑:

import 'dart:async';

import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
import '../amplifyconfiguration.dart';
import 'package:amplify_flutter/amplify_flutter.dart';
import 'package:amplify_auth_cognito/src/cognito_auth_session.dart';

class LogInService {
  LogInService() {
    _configureAmplify();
  }

  Future<void> _configureAmplify() async {
    try {
      AmplifyAuthCognito auth = AmplifyAuthCognito();
      await Amplify.addPlugin(auth);
      await Amplify.configure(amplifyconfig);
    } on Exception catch (e) {
      safePrint('An error occurred configuring Amplify: $e');
    }
  }

  Future<bool> signInWithWebUI() async {
    try {
      await Amplify.Auth.signInWithWebUI();
      // 登录成功后直接拉取完整认证信息
      await fetchAuthDetails();
      return true;
    } on AuthException catch (e) {
      safePrint('Error signing in: ${e.message}');
      return false;
    }
  }

  Future<void> fetchAuthDetails() async {
    try {
      // 强制刷新会话,确保拿到最新的认证信息
      final authSession = await Amplify.Auth.fetchAuthSession(
        options: const FetchAuthSessionOptions(forceRefresh: true),
      );

      if (authSession.isSignedIn && authSession is CognitoAuthSession) {
        // 获取JWT令牌(idToken用于后端API认证,accessToken用于Cognito操作)
        final tokenResult = authSession.userPoolTokensResult;
        if (tokenResult.isSuccess) {
          final tokens = tokenResult.value;
          safePrint('Access Token (JWT): ${tokens.accessToken}');
          safePrint('ID Token (JWT): ${tokens.idToken}');
        }

        // 获取Identity ID
        final identityResult = authSession.identityIdResult;
        if (identityResult.isSuccess) {
          safePrint("Current user's identity ID: ${identityResult.value}");
        } else {
          safePrint('Failed to get Identity ID: ${identityResult.error?.message}');
        }

        // 获取AWS凭证(如果需要调用S3、AppSync等其他AWS服务)
        final credResult = authSession.awsCredentialsResult;
        if (credResult.isSuccess) {
          safePrint('AWS Access Key: ${credResult.value.accessKeyId}');
        } else {
          safePrint('Failed to get AWS credentials: ${credResult.error?.message}');
        }
      } else {
        safePrint('User is not signed in');
      }
    } on AuthException catch (e) {
      safePrint('Error retrieving auth details: ${e.message}');
    }
  }

  Future<void> signOutWithWebUI() async {
    try {
      await Amplify.Auth.signOut(
        options: const SignOutOptions(globalSignOut: true), // 可选:全局登出所有设备
      );
      safePrint("Signed out successfully");
    } on AuthException catch (e) {
      safePrint(e.message);
    }
  }
}

额外注意事项

  1. 身份池配置检查:确保Cognito身份池已和用户池建立信任关系,且认证角色的IAM策略允许cognito-identity:GetId、sts:GetFederationToken等操作。
  2. 令牌使用场景:
    • idToken:用于你的后端API认证,后端可以通过Cognito公钥验证JWT的合法性
    • accessToken:主要用于Cognito用户池的操作(比如获取用户信息)
  3. 配置文件验证:检查amplifyconfiguration.dart中是否包含正确的身份池ID、用户池ID等配置项。

备注:内容来源于stack exchange,提问作者antonhs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.21 09:39:52