refreshTokens method

Future<void> refreshTokens()

Gets user information using automatic token management Returns null if token is invalid and refresh fails Gets user information with automatic re-authentication This version requires BuildContext for UI navigation if needed

Implementation

// Future<UserInfo?> getUser() async {
//   final accessToken = await getAccessToken();
//   if (accessToken == null) {
//     debugPrint('[WARNING] No valid access token for getUser - authentication required');
//     return null;
//   }
//
//   try {
//     final response =
//         Uri.parse('${Remit2AnyEnvironmentConfig.authUrl}/oauth2/userInfo');
//     final res = await http.get(
//       response,
//       headers: {'Authorization': 'Bearer $accessToken'},
//     );
//     if (res.statusCode == 200) {
//       return UserInfo.fromJson(jsonDecode(res.body));
//     } else {
//       debugPrint('[ERROR] Failed to fetch user info: ${res.statusCode}');
//     }
//   } catch (e) {
//     debugPrint('[ERROR] Error fetching user info: $e');
//   }
//   return null;
// }

/// Gets user information with automatic re-authentication
/// This version requires BuildContext for UI navigation if needed
// Future<UserInfo?> getUserWithAuth(BuildContext context) async {
//   // First try without UI
//   final user = await getUser();
//   if (user != null) return user;
//
//   // If failed, try to get a valid token with auth
//   final accessToken = await getAccessTokenWithAuth(context);
//   if (accessToken == null) return null;
//
//   // Retry with new token
//   return await getUser();
// }

Future<void> refreshTokens() async {
  final refreshToken = await TokenStorage.getRefreshToken();
  final deviceKey = await TokenStorage.getDeviceKey();
  final currentAccessToken = await TokenStorage.getAccessToken();

  if (refreshToken == null) {
    debugPrint('[WARNING] No refresh token available for refresh');
    await _handleRefreshFailure();
    return;
  }

  try {
    final clientId = Remit2AnyEnvironmentConfig.userPoolClientId;
    final url = Uri.parse('https://cognito-idp.us-east-1.amazonaws.com/');

    debugPrint('[INFO] Refreshing tokens using Cognito API...');

    final requestBody = {
      'ClientId': clientId,
      'AuthFlow': 'REFRESH_TOKEN_AUTH',
      'AuthParameters': {
        'REFRESH_TOKEN': refreshToken,
        'DEVICE_KEY': deviceKey,
      }
    };

    final response = await http.post(
      url,
      headers: {
        'Content-Type': 'application/x-amz-json-1.1',
        'X-Amz-Target': 'AWSCognitoIdentityProviderService.InitiateAuth',
      },
      body: jsonEncode(requestBody),
    );

    debugPrint('[DEBUG] Cognito API Response Status: ${response.statusCode}');
    debugPrint('[DEBUG] Cognito API Response Body: ${response.body}');

    if (response.statusCode == 200) {
      final data = jsonDecode(response.body);

      // Check if we got a valid response with AuthenticationResult
      if (data['AuthenticationResult'] != null) {
        final authResult = data['AuthenticationResult'];
        final newAccessToken = authResult['AccessToken'];
        final newIdToken = authResult['IdToken'];

        // Check if access token is present
        if (newAccessToken == null || newAccessToken.isEmpty) {
          debugPrint(
              '[ERROR] No access token in refresh response, calling signIn');
          await _handleRefreshFailure();
          return;
        }

        // Check if the new access token is the same as current one
        if (newAccessToken == currentAccessToken) {
          debugPrint(
              '[WARNING] New access token is same as current one, calling signIn');
          await _handleRefreshFailure();
          return;
        }

        // Save the new tokens
        await TokenStorage.saveTokens(
          accessToken: newAccessToken,
          refreshToken: refreshToken, // Keep the same refresh token
          deviceKey: deviceKey, // Keep the same device key
          idToken: newIdToken,
        );

        debugPrint('[INFO] Tokens refreshed successfully');
      } else {
        debugPrint(
            '[ERROR] No AuthenticationResult in response, calling signIn');
        await _handleRefreshFailure();
      }
    } else {
      debugPrint('[ERROR] Token refresh failed: ${response.statusCode}');
      debugPrint('[ERROR] Response body: ${response.body}');
      await _handleRefreshFailure();
    }
  } catch (e) {
    debugPrint('[ERROR] Token refresh exception: $e, calling signIn');
    await _handleRefreshFailure();
  }
}