Skip to content

feat: Add connection test command for SSO login flow#177

Open
jonatascastro12 wants to merge 5 commits into
mainfrom
devin/1781191038-connection-test
Open

feat: Add connection test command for SSO login flow#177
jonatascastro12 wants to merge 5 commits into
mainfrom
devin/1781191038-connection-test

Conversation

@jonatascastro12

Copy link
Copy Markdown
Contributor

Summary

Adds workos connection test <id> — an end-to-end SSO smoke test for a connection, run entirely from the CLI:

  1. Registers http://localhost:<port>/callback as an environment redirect URI automatically via the existing POST /user_management/redirect_uris wrapper (client.redirectUris.add). If registration fails (e.g. insufficient permissions), it prints the URI and asks the user to add it in the Dashboard before continuing (errors out in agent/CI mode instead of prompting).
  2. Builds an SSO authorize URL with sso.getAuthorizationUrl({ clientId, redirectUri, connection, state }), where clientId resolves from --client-idWORKOS_CLIENT_ID → the active environment's stored client ID.
  3. Starts a localhost HTTP callback server, opens the URL in the browser (--no-open to disable), waits for the IdP redirect (default 300s timeout, --timeout to override), validates state, exchanges the code via sso.getProfileAndToken, and prints the authenticated profile.

Flags: --client-id, --port (default 4807), --timeout, --open/--no-open, plus the usual --api-key/--json.

JSON mode outputs { connectionId, redirectUri, redirectUriRegistered, authorizationUrl, profile }.

Also registered in bin.ts and the help-json.ts command registry, with spec coverage for the happy path, flag overrides, IdP error callbacks, state mismatch, registration fallback prompts, agent-mode behavior, and JSON output.

Test plan

  • pnpm test (2102 passed), pnpm typecheck, pnpm lint, pnpm format:check, pnpm build all pass
  • New unit tests in src/commands/connection.spec.ts mock the HTTP server, browser open, and SDK to exercise the full callback flow

Link to Devin session: https://app.devin.ai/sessions/68e059345eaa4022851eb4f324d9c361
Requested by: @jonatascastro12

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor
Original prompt from jonatas

https://github.com/workos/cli/blob/main/src/commands/connection.ts

Can you create a command to test a connection?

It should first:

  • ask the customer to add a redirect URI that points to the CLI (a localhost on some port perhaps) [unless we already have a endpoint that adds a redirect URI in the environment, so we could automatically add it]
  • create an SSO authorize URL with the default application client ID and redirect_uri that redirects to the one suggested above

@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

@greptile-apps

greptile-apps Bot commented Jun 11, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds workos connection test <id>, an end-to-end SSO smoke-test command that registers a localhost redirect URI, builds an authorization URL, spins up a temporary HTTP callback server, exchanges the code for a profile, and prints the result. Good test coverage is included for the happy path, IdP error callbacks, state mismatch, agent mode, and JSON output.

  • src/commands/connection.ts: Core implementation — resolveClientId, waitForCallback, and runConnectionTest orchestrate the full SSO flow with proper state validation and server lifecycle management.
  • src/commands/connection.spec.ts: Unit tests mock the HTTP server, open, and SDK to cover all major code paths including the manual redirect URI fallback.
  • src/bin.ts / src/utils/help-json.ts: Registration of the new subcommand with all flags.

Confidence Score: 4/5

Safe to merge after fixing the agent-mode browser-open guard — in its current state the command will hang indefinitely when run from agent environments like Claude Code, Cursor, or Codex.

The browser auto-open guard checks only for CI mode, not agent mode. Since CI and agent are distinct modes in this codebase, isCiMode() returns false when WORKOS_AGENT, CLAUDE_CODE, or similar environment markers are set. The command will call open(), silently swallow the error, then block on callbackPromise for the full timeout (default 5 minutes) before surfacing any failure. All other aspects — state validation, server lifecycle, code exchange, redirect URI registration fallback, and JSON output — are correct and well-tested.

src/commands/connection.ts — the browser-open guard at line 283 needs to also check isAgentMode().

Important Files Changed

Filename Overview
src/commands/connection.ts Adds runConnectionTest with redirect URI registration, localhost callback server, and SSO code exchange. One logic issue: browser auto-open guard uses isCiMode() but skips isAgentMode(), so the command will hang in agent environments. Dead state-mismatch guard also present post-fix.
src/commands/connection.spec.ts Adds comprehensive unit tests for the new test command; mocks HTTP server, open, and SDK. Covers happy path, flag overrides, IdP errors, state mismatch, agent mode, manual redirect URI fallback, and JSON output.
src/bin.ts Registers the new test subcommand with correct positionals and options; delegates to runConnectionTest correctly.
src/utils/help-json.ts Adds the test command schema with all four options matching the bin.ts registration. Straightforward mechanical change.

Sequence Diagram

sequenceDiagram
    participant User
    participant CLI as workos connection test
    participant WOS as WorkOS API
    participant Browser
    participant Server as localhost callback server
    participant IdP

    CLI->>WOS: sso.getConnection(id)
    WOS-->>CLI: connection details
    CLI->>WOS: redirectUris.add(http://localhost:PORT/callback)
    WOS-->>CLI: registered / error → prompt user
    CLI->>CLI: generate random state
    CLI->>CLI: "sso.getAuthorizationUrl({ clientId, redirectUri, connection, state })"
    CLI->>Server: http.createServer() + server.listen(PORT)
    CLI->>Browser: open(authorizationUrl)
    Browser->>IdP: navigate to authorizationUrl
    IdP-->>Browser: "redirect to localhost/callback?code=...&state=..."
    Browser->>Server: "GET /callback?code=...&state=..."
    Server->>Server: validate state matches
    Server-->>Browser: 200 / 400 HTML response
    Server->>CLI: "resolve callbackPromise { code, state }"
    CLI->>WOS: "sso.getProfileAndToken({ code, clientId })"
    WOS-->>CLI: "{ profile }"
    CLI->>User: print profile / output JSON
    CLI->>Server: server.close()
Loading

Reviews (4): Last reviewed commit: "fix: Require state match on IdP error ca..." | Re-trigger Greptile

Comment thread src/commands/connection.ts
Comment thread src/commands/connection.ts
Comment thread src/commands/connection.ts
Comment thread src/commands/connection.ts
jonatascastro12 and others added 2 commits June 11, 2026 15:31
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Comment thread src/commands/connection.ts Outdated
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Comment thread src/commands/connection.ts Outdated
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant