authenticate method

Future<AuthConfig> authenticate()

Authenticate using browser-based flow Returns AuthConfig on success, throws on error

Implementation

Future<AuthConfig> authenticate() async {
  // Generate unique session ID
  final sessionId = const Uuid().v4();

  // Generate PKCE code verifier and challenge
  final codeVerifier = _generateCodeVerifier();
  final codeChallenge = _generateCodeChallenge(codeVerifier);

  if (verbose) {
    print('Session ID: $sessionId');
    print('Code verifier generated');
    print('Code challenge: $codeChallenge');
  }

  // Build CLI auth URL
  final authUrl = _buildAuthUrl(sessionId, codeChallenge);

  // Start local server
  final server = LocalAuthServer(sessionId: sessionId);

  try {
    // Print instructions
    print('\nOpening browser for authentication...');
    print('If browser does not open, visit:');
    print('  $authUrl\n');

    // Try to open browser
    final opened = await _openBrowser(authUrl);
    if (!opened && verbose) {
      print('Could not automatically open browser');
    }

    // Wait for callback
    print('Waiting for authorization...');
    final result = await server.waitForCallback();

    if (!result.isSuccess) {
      throw Exception(result.error ?? 'Authentication failed');
    }

    // If we received tokens directly
    if (result.accessToken != null) {
      return _buildAuthConfigFromTokens(result);
    }

    // If we received an auth code, we would exchange it here
    // For now, we expect the frontend to send tokens directly
    // This simplifies the flow and avoids needing a backend token endpoint
    if (result.code != null) {
      // In a full implementation, exchange code for tokens
      // For now, we expect tokens directly
      throw Exception('Received auth code but token exchange not implemented');
    }

    throw Exception('No valid authentication data received');
  } finally {
    server.stop();
  }
}