autoRefreshCredentials function

Future<KumihoCredentials?> autoRefreshCredentials(
  1. KumihoCredentials? credentials, {
  2. bool forceRefresh = false,
})

Auto-refreshes credentials if they're expired and auto-refresh is enabled.

Returns the refreshed credentials, or the original if refresh wasn't needed or auto-refresh is disabled.

Set KUMIHO_ENABLE_AUTO_REFRESH=true to enable auto-refresh.

Implementation

Future<KumihoCredentials?> autoRefreshCredentials(
  KumihoCredentials? credentials, {
  bool forceRefresh = false,
}) async {
  if (credentials == null) return null;

  // Check if auto-refresh is enabled
  final autoRefreshEnabled = _envFlag(AuthEnvVars.enableAutoRefresh);
  if (!autoRefreshEnabled && !forceRefresh) {
    return credentials;
  }

  // Check if token needs refresh
  if (credentials.isValid && !forceRefresh) {
    // ID token is still valid, but check CP token
    if (!credentials.isCpValid && credentials.idToken.isNotEmpty) {
      // Try to refresh CP token only
      final cpResult = await exchangeForControlPlaneToken(credentials.idToken);
      if (cpResult != null) {
        final updated = credentials.copyWith(
          controlPlaneToken: cpResult.token,
          cpExpiresAt: cpResult.expiresAt,
        );
        saveCredentials(updated);
        return updated;
      }
    }
    return credentials;
  }

  // Need to refresh ID token
  if (credentials.refreshToken.isEmpty) {
    return credentials; // Can't refresh without refresh token
  }

  try {
    final apiKey = credentials.apiKey.isNotEmpty
        ? credentials.apiKey
        : AuthDefaults.firebaseApiKey;

    final result = await refreshFirebaseToken(apiKey, credentials.refreshToken);
    final now = DateTime.now().millisecondsSinceEpoch ~/ 1000;

    var updated = credentials.copyWith(
      idToken: result.idToken,
      refreshToken: result.refreshToken,
      expiresAt: now + result.expiresIn,
    );

    // Also refresh CP token
    final cpResult = await exchangeForControlPlaneToken(result.idToken);
    if (cpResult != null) {
      updated = updated.copyWith(
        controlPlaneToken: cpResult.token,
        cpExpiresAt: cpResult.expiresAt,
      );
    }

    saveCredentials(updated);
    return updated;
  } catch (e) {
    // Refresh failed, return original credentials
    return credentials;
  }
}