runCodeMieSsoCliFlow function

Future<CodeMieSsoCredentials?> runCodeMieSsoCliFlow({
  1. required String codeMieUrl,
  2. required void onStatus(
    1. String
    ),
  3. Future<bool> openBrowserFn(
    1. String
    ) = openBrowser,
})

Runs the CodeMie SSO login: starts the callback server, opens (or prints) the organization's login URL, waits for the token, and decodes it into CodeMieSsoCredentials. Returns null on cancel/timeout/failure.

Implementation

Future<CodeMieSsoCredentials?> runCodeMieSsoCliFlow({
  required String codeMieUrl,
  required void Function(String) onStatus,
  Future<bool> Function(String) openBrowserFn = openBrowser,
}) async {
  final server = CodeMieSsoCallbackServer();
  final port = await server.start();
  final ssoUrl = buildCodeMieSsoUrl(codeMieUrl, port);
  onStatus('listening for the CodeMie SSO callback on port $port');
  if (await openBrowserFn(ssoUrl)) {
    onStatus('browser opened; complete the CodeMie sign-in');
  } else {
    onStatus('could not open browser automatically');
    onStatus('open this URL manually: $ssoUrl');
  }
  final token = await () async {
    // The CodeMie page often signs in BY ITSELF (existing browser session →
    // instant redirect) — wait patiently with a live status line, and bail
    // only after a generous timeout instead of hanging forever.
    onStatus(
      'waiting for the CodeMie SSO callback (the page may sign in by '
      'itself)…',
    );
    const wait = Duration(minutes: 5);
    final statusTimer = Timer.periodic(const Duration(seconds: 15), (t) {
      onStatus('still waiting for the SSO callback… (${t.tick * 15}s)');
    });
    try {
      return await server.waitForToken().timeout(wait, onTimeout: () => null);
    } finally {
      statusTimer.cancel();
    }
  }();
  if (token == null) {
    onStatus('no SSO callback received (timeout or cancelled)');
    return null;
  }
  try {
    final cookies = decodeCodeMieSsoToken(token);
    final credentials = CodeMieSsoCredentials(
      cookies: cookies,
      apiUrl: codeMieApiBase(codeMieUrl),
      expiresAt: deriveCodeMieExpiresAt(cookies),
    );
    if (credentials.authToken.isEmpty) {
      onStatus('CodeMie SSO callback carried no cookies');
      return null;
    }
    onStatus('CodeMie authorized');
    return credentials;
  } on FormatException catch (error) {
    onStatus('CodeMie SSO failed: ${error.message}');
    return null;
  }
}