signInWithNativeAuth method

Future<Map<String, dynamic>> signInWithNativeAuth(
  1. String provider
)

Sign in with a native provider (Google or Apple) using Amplify Hosted UI. provider must be "google" or "apple".

On success, persists tokens via TokenStorage and returns a map including localStorageItems for WebView injection (CognitoIdentityServiceProvider keys).

Requires Remit2AnyAuth.configureAmplify (or equivalent) before the first call.

Implementation

Future<Map<String, dynamic>> signInWithNativeAuth(String provider) async {
  final authProvider = provider.toLowerCase() == 'apple'
      ? AuthProvider.apple
      : provider.toLowerCase() == 'google'
          ? AuthProvider.google
          : null;
  if (authProvider == null) {
    return {
      'success': false,
      'isSignedIn': false,
      'error': 'Invalid provider: use "google" or "apple"',
    };
  }

  try {
    await _ensureAmplifyConfigured();
  } catch (e) {
    debugPrint('AuthService: Amplify configure failed: $e');
    return {
      'success': false,
      'isSignedIn': false,
      'error': 'Amplify configuration failed: ${e.toString()}',
    };
  }

  try {
    final result = await Amplify.Auth.signInWithWebUI(provider: authProvider);
    final step = result.nextStep;
    final resultJson = {
      'isSignedIn': result.isSignedIn,
      'nextStep': {
        'signInStep': step.signInStep.toString(),
        'additionalInfo': step.additionalInfo,
        'missingAttributes': step.missingAttributes,
      },
    };
    debugPrint(
        'AuthService: signInWithWebUI result: ${jsonEncode(resultJson)}');
    if (!result.isSignedIn) {
      return {'success': false, 'isSignedIn': false};
    }
    final poolTokens = await _fetchCognitoUserPoolTokens();
    if (poolTokens == null) {
      return {
        'success': false,
        'isSignedIn': true,
        'error': 'Could not fetch session tokens',
      };
    }

    final access = poolTokens.accessToken.raw;
    final idTok = poolTokens.idToken.raw;
    final refresh = poolTokens.refreshToken;
    await TokenStorage.saveAuthProvider(provider);
    final lastAuthUser = poolTokens.username.isNotEmpty
        ? poolTokens.username
        : (_getLastAuthUserFromAccessToken(access) ?? poolTokens.userId);
    debugPrint('AuthService: lastAuthUser: $lastAuthUser');
    final cognitoUserId = lastAuthUser;

    final appClientId = Remit2AnyEnvironmentConfig.userPoolClientId;
    final cognitoStoragePrefix =
        'CognitoIdentityServiceProvider.$appClientId.$cognitoUserId';
    final cognitoLastAuthUserKey =
        'CognitoIdentityServiceProvider.$appClientId.LastAuthUser';

    final Map<String, String> localStorageItems = {};
    if (cognitoUserId.isNotEmpty) {
      localStorageItems[cognitoLastAuthUserKey] = cognitoUserId;
      localStorageItems['$cognitoStoragePrefix.idToken'] = idTok;
      localStorageItems['$cognitoStoragePrefix.accessToken'] = access;
      if (refresh.isNotEmpty) {
        localStorageItems['$cognitoStoragePrefix.refreshToken'] = refresh;
      }
    }

    return localStorageItems;
  } on AuthException catch (e) {
    debugPrint('AuthService: $provider sign-in error: ${e.message}');
    return {
      'success': false,
      'isSignedIn': false,
      'error': e.message,
    };
  } catch (e) {
    debugPrint('AuthService: $provider sign-in error: $e');
    return {
      'success': false,
      'isSignedIn': false,
      'error': e.toString(),
    };
  }
}